From 4f38c6069999b27244ac341012f74a0dca7d0e3b Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 31 Dec 2017 16:44:48 -0500 Subject: [PATCH 01/86] Enable post locking via the heartbeat api, following core --- editor/index.js | 11 ++------- editor/utils/heartbeat.js | 50 +++++++++++++++++++++++++++++++++++++++ gutenberg.php | 6 +++++ 3 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 editor/utils/heartbeat.js diff --git a/editor/index.js b/editor/index.js index 2cd98d2b73bfb..eb5bff5223267 100644 --- a/editor/index.js +++ b/editor/index.js @@ -17,6 +17,7 @@ import './assets/stylesheets/main.scss'; import Layout from './edit-post/layout'; import { EditorProvider, ErrorBoundary } from './components'; import { initializeMetaBoxState } from './store/actions'; +import { setupHearthbeat } from './utils/heartbeat'; export * from './components'; import store from './store'; // Registers the state tree @@ -37,15 +38,6 @@ if ( dateSettings.timezone.string ) { moment.tz.setDefault( 'WP' ); } -/** - * Configure heartbeat to refresh the wp-api nonce, keeping the editor authorization intact. - */ -window.jQuery( document ).on( 'heartbeat-tick', ( event, response ) => { - if ( response[ 'rest-nonce' ] ) { - window.wpApiSettings.nonce = response[ 'rest-nonce' ]; - } -} ); - /** * Reinitializes the editor after the user chooses to reboot the editor after * an unhandled error occurs, replacing previously mounted editor element using @@ -83,6 +75,7 @@ export function recreateEditorInstance( target, settings ) { export function createEditorInstance( id, post, settings ) { const target = document.getElementById( id ); const reboot = recreateEditorInstance.bind( null, target, settings ); + setupHearthbeat(); render( diff --git a/editor/utils/heartbeat.js b/editor/utils/heartbeat.js new file mode 100644 index 0000000000000..45253aadbcf2f --- /dev/null +++ b/editor/utils/heartbeat.js @@ -0,0 +1,50 @@ +export function setupHearthbeat() { + /** + * Configure heartbeat to refresh the wp-api nonce, keeping the editor authorization intact. + */ + window.jQuery( document ).on( 'heartbeat-tick', ( event, response ) => { + if ( response[ 'rest-nonce' ] ) { + window.wpApiSettings.nonce = response[ 'rest-nonce' ]; + } + } ); + + /** + * Configure Heartbeat locks. + * + * Used to lock editing of an object by only one user at a time. + * + * When the user does not send a heartbeat in a heartbeat-time + * the user is no longer editing and another user can start editing. + */ + jQuery( document ).on( 'heartbeat-send.refresh-lock', function( e, data ) { + const lock = jQuery( '#active_post_lock' ).val(), + postId = jQuery( '#post_ID' ).val(), + send = {}; + + if ( ! postId ) { + return; + } + + send.postId = postId; + + if ( lock ) { + send.lock = lock; + } + + data[ 'wp-refresh-post-lock' ] = send; + } ); + + jQuery( document ).on( 'heartbeat-tick.refresh-lock', function( e, data ) { + // Post locks: update the lock string or show the dialog if somebody has taken over editing. + if ( data[ 'wp-refresh-post-lock' ] ) { + const received = data[ 'wp-refresh-post-lock' ]; + + if ( received.lock_error ) { + // @todo suspend autosaving + // @todo Show "editing taken over" message. + } else if ( received.new_lock ) { + jQuery( '#active_post_lock' ).val( received.new_lock ); + } + } + } ); +} diff --git a/gutenberg.php b/gutenberg.php index 7339c71f5509c..fecb5f2139b57 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -543,3 +543,9 @@ function gutenberg_replace_default_add_new_button() { function gutenberg_add_admin_body_class( $classes ) { return "$classes gutenberg-editor-page"; } + +function wp_heartbeat_settings_gutenberg( $settings ) { + $settings['interval'] = 15; //Anything between 15-120 + return $settings; +} +add_filter( 'heartbeat_settings', 'wp_heartbeat_settings_gutenberg' ); From 8578fc701422e1b2f2a98c4bc0865d91a81c0b35 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 31 Dec 2017 16:48:29 -0500 Subject: [PATCH 02/86] remove interval change --- gutenberg.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index fecb5f2139b57..7339c71f5509c 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -543,9 +543,3 @@ function gutenberg_replace_default_add_new_button() { function gutenberg_add_admin_body_class( $classes ) { return "$classes gutenberg-editor-page"; } - -function wp_heartbeat_settings_gutenberg( $settings ) { - $settings['interval'] = 15; //Anything between 15-120 - return $settings; -} -add_filter( 'heartbeat_settings', 'wp_heartbeat_settings_gutenberg' ); From b370721c19fd17488b18b3a50422c394a15528cc Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 31 Dec 2017 21:51:54 -0500 Subject: [PATCH 03/86] Docblock updates --- editor/utils/heartbeat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/utils/heartbeat.js b/editor/utils/heartbeat.js index 45253aadbcf2f..669c7511bf013 100644 --- a/editor/utils/heartbeat.js +++ b/editor/utils/heartbeat.js @@ -9,7 +9,7 @@ export function setupHearthbeat() { } ); /** - * Configure Heartbeat locks. + * Configure Heartbeat post locks. * * Used to lock editing of an object by only one user at a time. * @@ -34,8 +34,8 @@ export function setupHearthbeat() { data[ 'wp-refresh-post-lock' ] = send; } ); + // Refresh post locks: update the lock string or show the dialog if somebody has taken over editing. jQuery( document ).on( 'heartbeat-tick.refresh-lock', function( e, data ) { - // Post locks: update the lock string or show the dialog if somebody has taken over editing. if ( data[ 'wp-refresh-post-lock' ] ) { const received = data[ 'wp-refresh-post-lock' ]; From fbf7d08739ef62bac810bae3209e96a8074b77f6 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 6 Jul 2018 13:11:30 -0400 Subject: [PATCH 04/86] revert unintended changes --- editor/index.js | 73 +------------------------------------------------ 1 file changed, 1 insertion(+), 72 deletions(-) diff --git a/editor/index.js b/editor/index.js index b2fce0aa97c6a..170617fc80f23 100644 --- a/editor/index.js +++ b/editor/index.js @@ -1,76 +1,5 @@ import './store'; -import { setupHearthbeat } from './utils/heartbeat'; +import './hooks'; export * from './components'; export * from './utils'; - -// Configure moment globally -moment.locale( dateSettings.l10n.locale ); -if ( dateSettings.timezone.string ) { - moment.tz.setDefault( dateSettings.timezone.string ); -} else { - const momentTimezone = { - name: 'WP', - abbrs: [ 'WP' ], - untils: [ null ], - offsets: [ -dateSettings.timezone.offset * 60 ], - }; - const unpackedTimezone = moment.tz.pack( momentTimezone ); - moment.tz.add( unpackedTimezone ); - moment.tz.setDefault( 'WP' ); -} - -/** - * Reinitializes the editor after the user chooses to reboot the editor after - * an unhandled error occurs, replacing previously mounted editor element using - * an initial state from prior to the crash. - * - * @param {Element} target DOM node in which editor is rendered - * @param {?Object} settings Editor settings object - */ -export function recreateEditorInstance( target, settings ) { - unmountComponentAtNode( target ); - - const reboot = recreateEditorInstance.bind( null, target, settings ); - - render( - - - - - , - target - ); -} - -/** - * Initializes and returns an instance of Editor. - * - * The return value of this function is not necessary if we change where we - * call createEditorInstance(). This is due to metaBox timing. - * - * @param {String} id Unique identifier for editor instance - * @param {Object} post API entity for post to edit - * @param {?Object} settings Editor settings object - * @return {Object} Editor interface - */ -export function createEditorInstance( id, post, settings ) { - const target = document.getElementById( id ); - const reboot = recreateEditorInstance.bind( null, target, settings ); - setupHearthbeat(); - - render( - - - - - , - target - ); - - return { - initializeMetaBoxes( metaBoxes ) { - store.dispatch( initializeMetaBoxState( metaBoxes ) ); - }, - }; -} From e387b39ff7497e373db1370767496a2f6e1ddcaf Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 6 Jul 2018 13:14:55 -0400 Subject: [PATCH 05/86] remove nonce handling --- editor/utils/heartbeat.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/editor/utils/heartbeat.js b/editor/utils/heartbeat.js index 669c7511bf013..8c3ce34fcc223 100644 --- a/editor/utils/heartbeat.js +++ b/editor/utils/heartbeat.js @@ -1,12 +1,4 @@ export function setupHearthbeat() { - /** - * Configure heartbeat to refresh the wp-api nonce, keeping the editor authorization intact. - */ - window.jQuery( document ).on( 'heartbeat-tick', ( event, response ) => { - if ( response[ 'rest-nonce' ] ) { - window.wpApiSettings.nonce = response[ 'rest-nonce' ]; - } - } ); /** * Configure Heartbeat post locks. From 3a3deb90aedd0b03031822d76d89007ee4c9a197 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 6 Jul 2018 13:46:39 -0400 Subject: [PATCH 06/86] rename file & setup --- edit-post/index.js | 4 ++++ editor/utils/{heartbeat.js => heartbeat-post-locking.js} | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) rename editor/utils/{heartbeat.js => heartbeat-post-locking.js} (95%) diff --git a/edit-post/index.js b/edit-post/index.js index cc5692681050c..7d2ff7a72eb3e 100644 --- a/edit-post/index.js +++ b/edit-post/index.js @@ -4,6 +4,7 @@ import { registerCoreBlocks } from '@wordpress/core-blocks'; import { render, unmountComponentAtNode } from '@wordpress/element'; import { dispatch } from '@wordpress/data'; +import { setupHearthbeatPostLocking } from '../editor/utils/heartbeat-post-locking'; /** * Internal dependencies @@ -55,6 +56,9 @@ export function initializeEditor( id, postType, postId, settings, overridePost ) registerCoreBlocks(); + // Set up heartbeat post locking. + setupHearthbeatPostLocking(); + dispatch( 'core/nux' ).triggerGuide( [ 'core/editor.inserter', 'core/editor.settings', diff --git a/editor/utils/heartbeat.js b/editor/utils/heartbeat-post-locking.js similarity index 95% rename from editor/utils/heartbeat.js rename to editor/utils/heartbeat-post-locking.js index 8c3ce34fcc223..b06f61a778384 100644 --- a/editor/utils/heartbeat.js +++ b/editor/utils/heartbeat-post-locking.js @@ -1,4 +1,4 @@ -export function setupHearthbeat() { +export function setupHearthbeatPostLocking() { /** * Configure Heartbeat post locks. From 6980a89f796be397163680005bef63bdcb144fe3 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 6 Jul 2018 13:55:59 -0400 Subject: [PATCH 07/86] Ensure heartbeat interval is low enough to work for post locking --- gutenberg.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/gutenberg.php b/gutenberg.php index c7198f1281bee..9fd19b121ed0d 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -410,3 +410,15 @@ function toggleDropdown() { function gutenberg_add_admin_body_class( $classes ) { return "$classes gutenberg-editor-page"; } + +/** + * Ensure heartbeat interval is low enough to work for post locking. + * + * @param array $settings Settings. + * @return array Filtered settings. + */ +function wp_heartbeat_settings_gutenberg( $settings ) { + $settings['interval'] = 15; + return $settings; +} +add_filter( 'heartbeat_settings', 'wp_heartbeat_settings_gutenberg' ); From 810119dbf549acb717f27a3801213c242ca3a0d9 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 6 Jul 2018 15:11:38 -0400 Subject: [PATCH 08/86] Unlock the post when the window is closed or exited. --- editor/utils/heartbeat-post-locking.js | 31 ++++++++++++++++++++++++++ gutenberg.php | 11 +++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/editor/utils/heartbeat-post-locking.js b/editor/utils/heartbeat-post-locking.js index b06f61a778384..8875f7d26acf3 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/editor/utils/heartbeat-post-locking.js @@ -39,4 +39,35 @@ export function setupHearthbeatPostLocking() { } } } ); + + // Unlock the post when the window is closed or exited. + $(window).on( 'unload.edit-post', function( event ) { + + // Make sure we process only the main document unload. + if ( event.target && event.target.nodeName != '#document' ) { + return; + } + + var postID = $('#post_ID').val(); + var postLock = $('#active_post_lock').val(); + + if ( ! postID || ! postLock ) { + return; + } + + var data = { + action: 'wp-remove-post-lock', + _wpnonce: $('#_wpnonce').val(), + post_ID: postID, + active_post_lock: postLock + }; + + $.post({ + async: false, + data: data, + url: ajaxurl + }); + }); + + } diff --git a/gutenberg.php b/gutenberg.php index 9fd19b121ed0d..bedc97d030822 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -24,8 +24,15 @@ * @since 0.1.0 */ function the_gutenberg_project() { - global $post_type_object; - ?> + global $post_type_object, $post; + + if ( ! wp_check_post_lock( $post->ID ) ) { + $active_post_lock = wp_set_post_lock( $post->ID ); + } + + if ( ! empty( $active_post_lock ) ) { ?> + +

labels->edit_item ); ?>

From c510e37851ef367943108b06d815e7654fa9c938 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 6 Jul 2018 15:17:04 -0400 Subject: [PATCH 09/86] Fixes for eslint --- editor/utils/heartbeat-post-locking.js | 27 ++++++++++++-------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/editor/utils/heartbeat-post-locking.js b/editor/utils/heartbeat-post-locking.js index 8875f7d26acf3..71617a3b9f8c1 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/editor/utils/heartbeat-post-locking.js @@ -1,5 +1,5 @@ +/* global ajaxurl */ export function setupHearthbeatPostLocking() { - /** * Configure Heartbeat post locks. * @@ -41,33 +41,30 @@ export function setupHearthbeatPostLocking() { } ); // Unlock the post when the window is closed or exited. - $(window).on( 'unload.edit-post', function( event ) { + jQuery( window ).on( 'unload.edit-post', function( event ) { + const postID = jQuery( '#post_ID' ).val(); + const postLock = jQuery( '#active_post_lock' ).val(); // Make sure we process only the main document unload. - if ( event.target && event.target.nodeName != '#document' ) { + if ( event.target && event.target.nodeName !== '#document' ) { return; } - var postID = $('#post_ID').val(); - var postLock = $('#active_post_lock').val(); - if ( ! postID || ! postLock ) { return; } - var data = { + const data = { action: 'wp-remove-post-lock', - _wpnonce: $('#_wpnonce').val(), + _wpnonce: jQuery( '#_wpnonce' ).val(), post_ID: postID, - active_post_lock: postLock + active_post_lock: postLock, }; - $.post({ + jQuery.post( { async: false, data: data, - url: ajaxurl - }); - }); - - + url: ajaxurl, + } ); + } ); } From 60c6ccc88a681a4413373387fe17d599ba4ae336 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 26 Jul 2018 12:35:53 -0600 Subject: [PATCH 10/86] tabs not spaces --- gutenberg.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index d7fc8b306d84f..3da5c4655222b 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -431,7 +431,7 @@ function gutenberg_add_admin_body_class( $classes ) { * @return array Filtered settings. */ function wp_heartbeat_settings_gutenberg( $settings ) { - $settings['interval'] = 15; - return $settings; + $settings['interval'] = 15; + return $settings; } add_filter( 'heartbeat_settings', 'wp_heartbeat_settings_gutenberg' ); From c611a7b518535a055bc9be18a536f209aa94a275 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 27 Jul 2018 12:42:31 -0600 Subject: [PATCH 11/86] post locking WIP --- editor/store/actions.js | 42 ++++++++++++++++++++++++++ editor/store/reducer.js | 24 +++++++++++++++ editor/utils/heartbeat-post-locking.js | 21 +++++++++++++ lib/client-assets.php | 28 +++++++++++++++++ 4 files changed, 115 insertions(+) diff --git a/editor/store/actions.js b/editor/store/actions.js index b68839160204e..1ef6312c04ea7 100644 --- a/editor/store/actions.js +++ b/editor/store/actions.js @@ -590,6 +590,48 @@ export function removeNotice( id ) { }; } +/** + * Returns an action object used to create a modal. + * + * @param {WPElement} content The modal content. + * @param {?Object} options The modal options. Available options: + * `id` (string; default auto-generated) + * `isDismissible` (boolean; default `true`). + * + * @return {Object} Action object. + */ +export function createModal( content, options = {} ) { + const { + id = uuid(), + isDismissible = true, + spokenMessage, + } = options; + return { + type: 'CREATE_MODAL', + modal: { + id, + status, + content, + isDismissible, + spokenMessage, + }, + }; +} + +/** + * Returns an action object used to remove a modal. + * + * @param {string} id The modal id. + * + * @return {Object} Action object. + */ +export function removeModal( id ) { + return { + type: 'REMOVE_MODAL', + modalId: id, + }; +} + export const createSuccessNotice = partial( createNotice, 'success' ); export const createInfoNotice = partial( createNotice, 'info' ); export const createErrorNotice = partial( createNotice, 'error' ); diff --git a/editor/store/reducer.js b/editor/store/reducer.js index 4c1faf4ea4eac..98939a8e6c4d6 100644 --- a/editor/store/reducer.js +++ b/editor/store/reducer.js @@ -919,6 +919,30 @@ export function notices( state = [], action ) { return state; } +export function modals( state = [], action ) { + switch ( action.type ) { + case 'CREATE_MODAL': + return [ + ...reject( state, { id: action.modal.id } ), + action.modal, + ]; + + case 'REMOVE_MODAL': + const { modalId } = action; + const index = findIndex( state, { id: modalId } ); + if ( index === -1 ) { + return state; + } + + return [ + ...state.slice( 0, index ), + ...state.slice( index + 1 ), + ]; + } + + return state; +} + export const sharedBlocks = combineReducers( { data( state = {}, action ) { switch ( action.type ) { diff --git a/editor/utils/heartbeat-post-locking.js b/editor/utils/heartbeat-post-locking.js index 71617a3b9f8c1..d133d47b53a8f 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/editor/utils/heartbeat-post-locking.js @@ -1,4 +1,15 @@ /* global ajaxurl */ + +/** + * Internal dependencies + */ +import { createModal } from '../store/actions'; + +/** + * WordPress dependencies + */ +import { element } from '@wordpress/element'; + export function setupHearthbeatPostLocking() { /** * Configure Heartbeat post locks. @@ -17,6 +28,13 @@ export function setupHearthbeatPostLocking() { return; } + // Check if the post is locked. + const { locked } = select( 'core/editor' ).getEditorSettings(); + if ( locked ) { + console.log( 'LOCKED!' ); + } + return + send.postId = postId; if ( lock ) { @@ -34,8 +52,11 @@ export function setupHearthbeatPostLocking() { if ( received.lock_error ) { // @todo suspend autosaving // @todo Show "editing taken over" message. + const modalContent = wp.element.createElement( Greeting, { toWhom: 'World' } ); + dispatch( 'core/editor' ).createModal( modalContent ); } else if ( received.new_lock ) { jQuery( '#active_post_lock' ).val( received.new_lock ); + dispatch( 'core/editor' ).removeModal(); } } } ); diff --git a/lib/client-assets.php b/lib/client-assets.php index f1e94ce845b38..b75d3f4da2538 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1261,6 +1261,34 @@ function gutenberg_editor_scripts_and_styles( $hook ) { ); } + // Check to see if the post is locked. + $user = null; + if ( $user_id = wp_check_post_lock( $post->ID ) ) { + $user = get_userdata( $user_id ); + } + + if ( $user ) { + + /** + * Filters whether to show the post locked dialog. + * + * Returning a falsey value to the filter will short-circuit displaying the dialog. + * + * @since 3.6.0 + * + * @param bool $display Whether to display the dialog. Default true. + * @param WP_Post $post Post object. + * @param WP_User|bool $user WP_User object on success, false otherwise. + */ + if ( apply_filters( 'show_post_locked_dialog', true, $post, $user ) ) { + $locked = true; + } + + } else { + $locked = false; + } + $editor_settings['locked'] = $locked; + if ( false !== $color_palette ) { $editor_settings['colors'] = editor_color_palette_slugs( $color_palette ); } From a5d1764cc9d07afe4a27374dbf34b4ec3caf6c42 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 2 Aug 2018 22:26:27 -0600 Subject: [PATCH 12/86] modal on load first pass --- editor/utils/heartbeat-post-locking.js | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/editor/utils/heartbeat-post-locking.js b/editor/utils/heartbeat-post-locking.js index d133d47b53a8f..39a0c1c2fd2c6 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/editor/utils/heartbeat-post-locking.js @@ -3,14 +3,20 @@ /** * Internal dependencies */ -import { createModal } from '../store/actions'; +import { createModal } from '../../packages/editor/src/store/actions'; /** * WordPress dependencies */ import { element } from '@wordpress/element'; +import { dispatch, select } from '@wordpress/data'; + export function setupHearthbeatPostLocking() { + const { + getEditorSettings, + } = select( 'core/editor' ); + /** * Configure Heartbeat post locks. * @@ -29,11 +35,13 @@ export function setupHearthbeatPostLocking() { } // Check if the post is locked. - const { locked } = select( 'core/editor' ).getEditorSettings(); + const { locked } = getEditorSettings(); if ( locked ) { console.log( 'LOCKED!' ); + const modalContent = wp.element.createElement( 'div', {}, 'locked' ); + dispatch( 'core/editor' ).createModal( modalContent ); + return; } - return send.postId = postId; @@ -88,4 +96,16 @@ export function setupHearthbeatPostLocking() { url: ajaxurl, } ); } ); + + // Show the locked modal on load if the post is locked. + jQuery( window ).on( 'load', function() { + console.log( 'ready - settings', getEditorSettings() ); + const { locked } = getEditorSettings(); + console.log( 'locked?', locked ); + if ( locked ) { + console.log( 'LOCKED!' ); + const modalContent = wp.element.createElement( 'div', {}, 'locked' ); + dispatch( 'core/editor' ).createModal( modalContent ); + } + } ); } From 2c3aeccb077da416df7ce433cde010353da1ce48 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 6 Aug 2018 08:37:09 -0600 Subject: [PATCH 13/86] Fixes for phpunit --- lib/client-assets.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index 44bde46531668..262492f60e265 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1291,7 +1291,8 @@ function gutenberg_editor_scripts_and_styles( $hook ) { // Check to see if the post is locked. $user = null; - if ( $user_id = wp_check_post_lock( $post->ID ) ) { + $user_id = wp_check_post_lock( $post->ID ) + if ( $user_id ) { $user = get_userdata( $user_id ); } @@ -1311,7 +1312,6 @@ function gutenberg_editor_scripts_and_styles( $hook ) { if ( apply_filters( 'show_post_locked_dialog', true, $post, $user ) ) { $locked = true; } - } else { $locked = false; } From 68f209925292f3af3622c044a12106dec2e1b4cf Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 6 Aug 2018 08:37:31 -0600 Subject: [PATCH 14/86] Enable a Modal showCloseIcon property --- packages/components/src/modal/README.md | 8 ++++++++ packages/components/src/modal/header.js | 14 ++++++++------ packages/components/src/modal/index.js | 3 +++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/components/src/modal/README.md b/packages/components/src/modal/README.md index 8c416614d6507..615094ca9f8dd 100644 --- a/packages/components/src/modal/README.md +++ b/packages/components/src/modal/README.md @@ -137,6 +137,14 @@ If this property is added, it will determine whether the modal requests to close - Required: No - Default: true +### showCloseIcon + +If this property is set to false, the modal will not display a close icon. + +- Type: `bool` +- Required: No +- Default: true + ### className If this property is added, it will an additional class name to the modal content `div`. diff --git a/packages/components/src/modal/header.js b/packages/components/src/modal/header.js index c9710d810bb3b..f4cc1cfb53b7a 100644 --- a/packages/components/src/modal/header.js +++ b/packages/components/src/modal/header.js @@ -8,7 +8,7 @@ import { __ } from '@wordpress/i18n'; */ import IconButton from '../icon-button'; -const ModalHeader = ( { icon, title, onClose, closeLabel, headingId } ) => { +const ModalHeader = ( { icon, title, onClose, closeLabel, headingId, showCloseIcon } ) => { const label = closeLabel ? closeLabel : __( 'Close dialog' ); return ( @@ -28,11 +28,13 @@ const ModalHeader = ( { icon, title, onClose, closeLabel, headingId } ) => { }
- + { showCloseIcon && + + } ); }; diff --git a/packages/components/src/modal/index.js b/packages/components/src/modal/index.js index a65c45f4b1ecd..56190e517443a 100644 --- a/packages/components/src/modal/index.js +++ b/packages/components/src/modal/index.js @@ -117,6 +117,7 @@ class Modal extends Component { children, aria, instanceId, + showCloseIcon, ...otherProps } = this.props; @@ -143,6 +144,7 @@ class Modal extends Component { { ...otherProps } > Date: Mon, 6 Aug 2018 09:17:39 -0600 Subject: [PATCH 15/86] Add a post locked modal, first pass --- .../components/src/post-locked-modal/index.js | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 packages/components/src/post-locked-modal/index.js diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js new file mode 100644 index 0000000000000..6261681a2c522 --- /dev/null +++ b/packages/components/src/post-locked-modal/index.js @@ -0,0 +1,72 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Modal } from '@wordpress/components'; +import { Component, Fragment } from '@wordpress/element'; + +class PostLockedModal extends Component { + constructor() { + super( ...arguments ); + this.state = { + isOpen: true, + } + + this.openModal = this.openModal.bind( this ); + this.closeModal = this.closeModal.bind( this ); + } + + openModal() { + if ( ! this.state.isOpen ) { + this.setState( { isOpen: true } ); + } + } + + closeModal() { + if ( this.state.isOpen ) { + this.setState( { isOpen: false } ); + } + } + + render() { + return ( + + + { this.state.isOpen ? + +
+ { __( 'Username is already editing this post. Do you want to take over?')} +
+ + + +
+ : null } +
+ ); + } +} + +export default PostLockedModal; From f6696821593afdc18dac91706e05e8db0b9aa5dd Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 6 Aug 2018 09:17:50 -0600 Subject: [PATCH 16/86] =?UTF-8?q?Add=20an=20=E2=80=9CisPostLocked=E2=80=9D?= =?UTF-8?q?=20selector?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor/src/store/selectors.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index ffabf1c82f701..bea887426a87c 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -1873,6 +1873,18 @@ export function getTokenSettings( state, name ) { return state.tokens[ name ]; } +/** + * Returns whether the post is locked. + * + * @param {Object} state Global application state. + * + * @return {boolean} Is locked. + */ +export function isPostLocked( state ) { + console.log( 'isPostLocked?', !!state.locked, state ); + return !! state.locked; +} + /** * Returns whether or not the user has the unfiltered_html capability. * From 5515ba189d69aa7bbaa62775a79809d43408ceca Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 6 Aug 2018 09:18:03 -0600 Subject: [PATCH 17/86] Add a locked reducer --- packages/editor/src/store/reducer.js | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/packages/editor/src/store/reducer.js b/packages/editor/src/store/reducer.js index 85c2bec723cfd..ec0cf153bc551 100644 --- a/packages/editor/src/store/reducer.js +++ b/packages/editor/src/store/reducer.js @@ -919,25 +919,14 @@ export function notices( state = [], action ) { return state; } -export function modals( state = [], action ) { +export function locked( state = false, action ) { switch ( action.type ) { - case 'CREATE_MODAL': - return [ - ...reject( state, { id: action.modal.id } ), - action.modal, - ]; - - case 'REMOVE_MODAL': - const { modalId } = action; - const index = findIndex( state, { id: modalId } ); - if ( index === -1 ) { - return state; - } - - return [ - ...state.slice( 0, index ), - ...state.slice( index + 1 ), - ]; + case 'LOCK_POST': + console.log( 'LOCK_POST', action ); + return { + ...state, + isValid: action.lock, + }; } return state; @@ -1157,6 +1146,7 @@ export default optimist( combineReducers( { isInsertionPointVisible, preferences, saving, + locked, notices, reusableBlocks, template, From 6fda398fdadd23ed1964f446d7c5e222143ef03e Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 6 Aug 2018 09:18:24 -0600 Subject: [PATCH 18/86] =?UTF-8?q?action=20is=20=E2=80=98lockPost=E2=80=99?= =?UTF-8?q?=20and=20takes=20a=20boolean?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor/src/store/actions.js | 37 ++++------------------------ 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index 6d70856a4e8c2..c9e8fd5d6f75c 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -591,45 +591,18 @@ export function removeNotice( id ) { }; } -/** - * Returns an action object used to create a modal. - * - * @param {WPElement} content The modal content. - * @param {?Object} options The modal options. Available options: - * `id` (string; default auto-generated) - * `isDismissible` (boolean; default `true`). - * - * @return {Object} Action object. - */ -export function createModal( content, options = {} ) { - const { - id = uuid(), - isDismissible = true, - spokenMessage, - } = options; - return { - type: 'CREATE_MODAL', - modal: { - id, - status, - content, - isDismissible, - spokenMessage, - }, - }; -} - /** * Returns an action object used to remove a modal. * - * @param {string} id The modal id. + * @param {boolean} lock The modal id. * * @return {Object} Action object. */ -export function removeModal( id ) { +export function lockPost( lock ) { + console.log( 'lockPost', lock ); return { - type: 'REMOVE_MODAL', - modalId: id, + type: 'LOCK_POST', + lock }; } From 3157fc230b3c5f950358368e887cfd78c86e3bc7 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 6 Aug 2018 09:18:35 -0600 Subject: [PATCH 19/86] fixes for phpunit --- lib/client-assets.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index 262492f60e265..33ab1053d3739 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1291,7 +1291,7 @@ function gutenberg_editor_scripts_and_styles( $hook ) { // Check to see if the post is locked. $user = null; - $user_id = wp_check_post_lock( $post->ID ) + $user_id = wp_check_post_lock( $post->ID ); if ( $user_id ) { $user = get_userdata( $user_id ); } @@ -1312,6 +1312,8 @@ function gutenberg_editor_scripts_and_styles( $hook ) { if ( apply_filters( 'show_post_locked_dialog', true, $post, $user ) ) { $locked = true; } + $editor_settings['lockedUser'] = $user; + } else { $locked = false; } From 413e75b133a6d02f78865f6986498b0fd0efc305 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 6 Aug 2018 09:19:13 -0600 Subject: [PATCH 20/86] cleanup hearbeat post locking --- editor/utils/heartbeat-post-locking.js | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/editor/utils/heartbeat-post-locking.js b/editor/utils/heartbeat-post-locking.js index 39a0c1c2fd2c6..257776ff4922f 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/editor/utils/heartbeat-post-locking.js @@ -3,7 +3,7 @@ /** * Internal dependencies */ -import { createModal } from '../../packages/editor/src/store/actions'; +import { lockPost } from '../../packages/editor/src/store/actions'; /** * WordPress dependencies @@ -35,11 +35,8 @@ export function setupHearthbeatPostLocking() { } // Check if the post is locked. - const { locked } = getEditorSettings(); + const locked = select( 'core/editor' ).isPostLocked(); if ( locked ) { - console.log( 'LOCKED!' ); - const modalContent = wp.element.createElement( 'div', {}, 'locked' ); - dispatch( 'core/editor' ).createModal( modalContent ); return; } @@ -60,11 +57,11 @@ export function setupHearthbeatPostLocking() { if ( received.lock_error ) { // @todo suspend autosaving // @todo Show "editing taken over" message. - const modalContent = wp.element.createElement( Greeting, { toWhom: 'World' } ); - dispatch( 'core/editor' ).createModal( modalContent ); + dispatch( 'core/editor' ).lockPost( true ); } else if ( received.new_lock ) { jQuery( '#active_post_lock' ).val( received.new_lock ); - dispatch( 'core/editor' ).removeModal(); + + dispatch( 'core/editor' ).lockPost( false ); } } } ); @@ -99,13 +96,10 @@ export function setupHearthbeatPostLocking() { // Show the locked modal on load if the post is locked. jQuery( window ).on( 'load', function() { - console.log( 'ready - settings', getEditorSettings() ); - const { locked } = getEditorSettings(); + const locked = select( 'core/editor' ).isPostLocked(); console.log( 'locked?', locked ); if ( locked ) { - console.log( 'LOCKED!' ); - const modalContent = wp.element.createElement( 'div', {}, 'locked' ); - dispatch( 'core/editor' ).createModal( modalContent ); + dispatch( 'core/editor' ).lockPost( true ); } } ); } From d79f3ca34b5418757067f9331043d1e6b8e25098 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 6 Aug 2018 09:19:48 -0600 Subject: [PATCH 21/86] Show the post locked modal when the post is locked --- edit-post/editor.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/edit-post/editor.js b/edit-post/editor.js index 42ff1f5da8303..deb6bdbd4a971 100644 --- a/edit-post/editor.js +++ b/edit-post/editor.js @@ -4,13 +4,13 @@ import { withSelect } from '@wordpress/data'; import { EditorProvider, ErrorBoundary } from '@wordpress/editor'; import { StrictMode } from '@wordpress/element'; - +import PostLockedModal from '../packages/components/src/post-locked-modal' /** * Internal dependencies */ import Layout from './components/layout'; -function Editor( { settings, hasFixedToolbar, post, overridePost, onError, ...props } ) { +function Editor( { settings, hasFixedToolbar, post, isLocked, overridePost, onError, ...props } ) { if ( ! post ) { return null; } @@ -26,6 +26,7 @@ function Editor( { settings, hasFixedToolbar, post, overridePost, onError, ...pr + { isLocked && }
); @@ -34,4 +35,5 @@ function Editor( { settings, hasFixedToolbar, post, overridePost, onError, ...pr export default withSelect( ( select, { postId, postType } ) => ( { hasFixedToolbar: select( 'core/edit-post' ).isFeatureActive( 'fixedToolbar' ), post: select( 'core' ).getEntityRecord( 'postType', postType, postId ), + isLocked: select( 'core/editor' ).isPostLocked(), } ) )( Editor ); From 825e0a5bfef6213b1378c9bbb378e7c3324e2c59 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 6 Aug 2018 09:45:29 -0600 Subject: [PATCH 22/86] spaces for phpcs --- lib/client-assets.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index 33ab1053d3739..ee6ce17d71527 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1290,7 +1290,7 @@ function gutenberg_editor_scripts_and_styles( $hook ) { } // Check to see if the post is locked. - $user = null; + $user = null; $user_id = wp_check_post_lock( $post->ID ); if ( $user_id ) { $user = get_userdata( $user_id ); From 27f45dc1af0fbe6b1f470a7ac4ed047c2341381f Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 7 Aug 2018 12:38:28 -0600 Subject: [PATCH 23/86] passed lock & user at initialization --- edit-post/editor.js | 2 +- editor/utils/heartbeat-post-locking.js | 20 ------ lib/client-assets.php | 2 +- .../components/src/post-locked-modal/index.js | 67 ++++++++++--------- .../editor/src/components/provider/index.js | 2 +- packages/editor/src/store/actions.js | 11 +-- packages/editor/src/store/reducer.js | 4 +- packages/editor/src/store/selectors.js | 14 +++- 8 files changed, 58 insertions(+), 64 deletions(-) diff --git a/edit-post/editor.js b/edit-post/editor.js index deb6bdbd4a971..59b2d8e9933ea 100644 --- a/edit-post/editor.js +++ b/edit-post/editor.js @@ -4,7 +4,7 @@ import { withSelect } from '@wordpress/data'; import { EditorProvider, ErrorBoundary } from '@wordpress/editor'; import { StrictMode } from '@wordpress/element'; -import PostLockedModal from '../packages/components/src/post-locked-modal' +import PostLockedModal from '../packages/components/src/post-locked-modal'; /** * Internal dependencies */ diff --git a/editor/utils/heartbeat-post-locking.js b/editor/utils/heartbeat-post-locking.js index 257776ff4922f..0a6163b9b72d5 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/editor/utils/heartbeat-post-locking.js @@ -1,22 +1,11 @@ /* global ajaxurl */ -/** - * Internal dependencies - */ -import { lockPost } from '../../packages/editor/src/store/actions'; - /** * WordPress dependencies */ -import { element } from '@wordpress/element'; import { dispatch, select } from '@wordpress/data'; - export function setupHearthbeatPostLocking() { - const { - getEditorSettings, - } = select( 'core/editor' ); - /** * Configure Heartbeat post locks. * @@ -93,13 +82,4 @@ export function setupHearthbeatPostLocking() { url: ajaxurl, } ); } ); - - // Show the locked modal on load if the post is locked. - jQuery( window ).on( 'load', function() { - const locked = select( 'core/editor' ).isPostLocked(); - console.log( 'locked?', locked ); - if ( locked ) { - dispatch( 'core/editor' ).lockPost( true ); - } - } ); } diff --git a/lib/client-assets.php b/lib/client-assets.php index ee6ce17d71527..24be2e23024ac 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1312,7 +1312,7 @@ function gutenberg_editor_scripts_and_styles( $hook ) { if ( apply_filters( 'show_post_locked_dialog', true, $post, $user ) ) { $locked = true; } - $editor_settings['lockedUser'] = $user; + $editor_settings['lockedUser'] = $locked ? $user : false; } else { $locked = false; diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index 6261681a2c522..6d2055898d624 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -4,13 +4,14 @@ import { __ } from '@wordpress/i18n'; import { Modal } from '@wordpress/components'; import { Component, Fragment } from '@wordpress/element'; +import { select } from '@wordpress/data'; class PostLockedModal extends Component { constructor() { super( ...arguments ); this.state = { isOpen: true, - } + }; this.openModal = this.openModal.bind( this ); this.closeModal = this.closeModal.bind( this ); @@ -29,41 +30,43 @@ class PostLockedModal extends Component { } render() { + const user = select( 'core/editor' ).getPostLockUser(); return ( - { this.state.isOpen ? - -
- { __( 'Username is already editing this post. Do you want to take over?')} -
- - - -
- : null } + + + + + : + null + }
); } diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index cc655af81c717..86f2e8153cf5f 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -26,7 +26,7 @@ class EditorProvider extends Component { // Assume that we don't need to initialize in the case of an error recovery. if ( ! props.recovery ) { this.props.updateEditorSettings( props.settings ); - this.props.setupEditor( props.post, props.settings.autosave ); + this.props.setupEditor( props.post, props.settings.autosave, props.settings.lockedUser ); } } diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index c9e8fd5d6f75c..cbbd18db000bb 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -19,13 +19,15 @@ import deprecated from '@wordpress/deprecated'; * * @param {Object} post Post object. * @param {Object} autosaveStatus The Post's autosave status. + * @param {Object} lockedUser The Post's locked user, or false if not locked. * * @return {Object} Action object. */ -export function setupEditor( post, autosaveStatus ) { +export function setupEditor( post, autosaveStatus, lockedUser ) { return { type: 'SETUP_EDITOR', autosave: autosaveStatus, + locked: lockedUser, post, }; } @@ -594,15 +596,14 @@ export function removeNotice( id ) { /** * Returns an action object used to remove a modal. * - * @param {boolean} lock The modal id. + * @param {boolean} locked Whether the editor should be locked. * * @return {Object} Action object. */ -export function lockPost( lock ) { - console.log( 'lockPost', lock ); +export function lockPost( locked ) { return { type: 'LOCK_POST', - lock + locked, }; } diff --git a/packages/editor/src/store/reducer.js b/packages/editor/src/store/reducer.js index ec0cf153bc551..053207d06a66f 100644 --- a/packages/editor/src/store/reducer.js +++ b/packages/editor/src/store/reducer.js @@ -922,10 +922,10 @@ export function notices( state = [], action ) { export function locked( state = false, action ) { switch ( action.type ) { case 'LOCK_POST': - console.log( 'LOCK_POST', action ); + case 'SETUP_EDITOR': return { ...state, - isValid: action.lock, + locked: action.locked, }; } diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index bea887426a87c..3f18eb91d4609 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -1881,8 +1881,18 @@ export function getTokenSettings( state, name ) { * @return {boolean} Is locked. */ export function isPostLocked( state ) { - console.log( 'isPostLocked?', !!state.locked, state ); - return !! state.locked; + return !! state.locked.locked; +} + +/** + * Returns whether the post lock user. + * + * @param {Object} state Global application state. + * + * @return {Object} A user object. + */ +export function getPostLockUser( state ) { + return state.locked.locked; } /** From ad0c4ae5518b7171c366fae8d228619e98dc3dc3 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 8 Aug 2018 08:26:49 -0600 Subject: [PATCH 24/86] update inline docs --- editor/utils/heartbeat-post-locking.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/utils/heartbeat-post-locking.js b/editor/utils/heartbeat-post-locking.js index 0a6163b9b72d5..9c3dd36b503f2 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/editor/utils/heartbeat-post-locking.js @@ -11,7 +11,7 @@ export function setupHearthbeatPostLocking() { * * Used to lock editing of an object by only one user at a time. * - * When the user does not send a heartbeat in a heartbeat-time + * When the user does not send a heartbeat in a heartbeat-tick * the user is no longer editing and another user can start editing. */ jQuery( document ).on( 'heartbeat-send.refresh-lock', function( e, data ) { @@ -23,7 +23,7 @@ export function setupHearthbeatPostLocking() { return; } - // Check if the post is locked. + // Check if the post is already locked by another user. const locked = select( 'core/editor' ).isPostLocked(); if ( locked ) { return; From c2e6d744ce351ae84278c8b486aa0a6be1cc63c4 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 8 Aug 2018 08:27:10 -0600 Subject: [PATCH 25/86] pass a unlocking lockNonce to settings if the post is locked --- lib/client-assets.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/client-assets.php b/lib/client-assets.php index 51b1272312ad2..cc30de98bd68c 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1341,6 +1341,7 @@ function gutenberg_editor_scripts_and_styles( $hook ) { $locked = true; } $editor_settings['lockedUser'] = $locked ? $user : false; + $editor_settings['lockNonce'] = wp_create_nonce( 'lock-post_' + $post->ID ); } else { $locked = false; From 560222fafedbd8213f9cb48301730dc1dd470f01 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 8 Aug 2018 08:28:12 -0600 Subject: [PATCH 26/86] Lock modal actions, first pass; leverage existing PostPreviewButton * note previews open in a new tab, unlike classic editor where it happens in the main window --- .../components/src/post-locked-modal/index.js | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index 6d2055898d624..27870c42b37fa 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -5,6 +5,12 @@ import { __ } from '@wordpress/i18n'; import { Modal } from '@wordpress/components'; import { Component, Fragment } from '@wordpress/element'; import { select } from '@wordpress/data'; +import { + PostPreviewButton, +} from '@wordpress/editor'; +import './style.scss'; +import { addQueryArgs } from '@wordpress/url'; +import { getPostEditURL } from '../../../../edit-post/components/browser-url'; class PostLockedModal extends Component { constructor() { @@ -14,7 +20,9 @@ class PostLockedModal extends Component { }; this.openModal = this.openModal.bind( this ); - this.closeModal = this.closeModal.bind( this ); + this.takeOver = this.takeOver.bind( this ); + + this.takeover = __( ' admin has taken over and is currently editing. Your latest changes were saved as a revision. ' ); } openModal() { @@ -23,10 +31,21 @@ class PostLockedModal extends Component { } } - closeModal() { - if ( this.state.isOpen ) { - this.setState( { isOpen: false } ); - } + takeOver() { + const { getCurrentPost, getEditorSettings } = select( 'core/editor' ); + const { id } = getCurrentPost(); + const { lockNonce } = getEditorSettings(); + const unlockUrl = addQueryArgs( getPostEditURL(), { + 'get-post-lock': '1', + 'nonce': lockNonce, + lockKey: true, + } ); + + document.location = unlockUrl; + } + + goBack() { + window.history.back(); } render() { @@ -48,19 +67,14 @@ class PostLockedModal extends Component { + - From b5c1d48a476efe447eca62d727fc012de95f7c7c Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 8 Aug 2018 08:28:22 -0600 Subject: [PATCH 27/86] Add some style --- packages/components/src/post-locked-modal/style.scss | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 packages/components/src/post-locked-modal/style.scss diff --git a/packages/components/src/post-locked-modal/style.scss b/packages/components/src/post-locked-modal/style.scss new file mode 100644 index 0000000000000..6b2f5d7bedbf4 --- /dev/null +++ b/packages/components/src/post-locked-modal/style.scss @@ -0,0 +1,8 @@ +.post-locked-modal { + max-height: 140px; + + button.button, + button.components-button { + margin: 5px; + } +} From 1514d066c57dde6da581986df613a8efd0f3ac1c Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 8 Aug 2018 08:38:49 -0600 Subject: [PATCH 28/86] improve modal string construction, nonce setup, linting fixes --- lib/client-assets.php | 2 +- .../components/src/post-locked-modal/index.js | 27 +++++++------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index cc30de98bd68c..b45cbfb2ac0bb 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1341,7 +1341,7 @@ function gutenberg_editor_scripts_and_styles( $hook ) { $locked = true; } $editor_settings['lockedUser'] = $locked ? $user : false; - $editor_settings['lockNonce'] = wp_create_nonce( 'lock-post_' + $post->ID ); + $editor_settings['lockNonce'] = wp_create_nonce( 'lock-post_' . $post->ID ); } else { $locked = false; diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index 27870c42b37fa..9ba885888acc5 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; import { Modal } from '@wordpress/components'; import { Component, Fragment } from '@wordpress/element'; import { select } from '@wordpress/data'; @@ -19,28 +19,21 @@ class PostLockedModal extends Component { isOpen: true, }; - this.openModal = this.openModal.bind( this ); - this.takeOver = this.takeOver.bind( this ); + this.takeOverPost = this.takeOverPost.bind( this ); - this.takeover = __( ' admin has taken over and is currently editing. Your latest changes were saved as a revision. ' ); - } - - openModal() { - if ( ! this.state.isOpen ) { - this.setState( { isOpen: true } ); - } + const user = select( 'core/editor' ).getPostLockUser(); + this.takeover = sprintf( __( '%s has taken over and is currently editing. Your latest changes were saved as a revision.' ), user.data.display_name ); + this.alreadyEditing = sprintf( __( '%s is already editing this post. Do you want to take over?' ), user.data.display_name ); } - takeOver() { - const { getCurrentPost, getEditorSettings } = select( 'core/editor' ); - const { id } = getCurrentPost(); + takeOverPost() { + const { getEditorSettings } = select( 'core/editor' ); const { lockNonce } = getEditorSettings(); const unlockUrl = addQueryArgs( getPostEditURL(), { 'get-post-lock': '1', - 'nonce': lockNonce, + nonce: lockNonce, lockKey: true, } ); - document.location = unlockUrl; } @@ -49,14 +42,12 @@ class PostLockedModal extends Component { } render() { - const user = select( 'core/editor' ).getPostLockUser(); return ( - { this.state.isOpen ? Date: Fri, 10 Aug 2018 15:22:42 -0600 Subject: [PATCH 29/86] better setup, fix beforeunload --- editor/utils/heartbeat-post-locking.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/editor/utils/heartbeat-post-locking.js b/editor/utils/heartbeat-post-locking.js index 9c3dd36b503f2..6251969ed55fe 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/editor/utils/heartbeat-post-locking.js @@ -36,10 +36,10 @@ export function setupHearthbeatPostLocking() { } data[ 'wp-refresh-post-lock' ] = send; - } ); + } ) // Refresh post locks: update the lock string or show the dialog if somebody has taken over editing. - jQuery( document ).on( 'heartbeat-tick.refresh-lock', function( e, data ) { + .on( 'heartbeat-tick.refresh-lock', function( e, data ) { if ( data[ 'wp-refresh-post-lock' ] ) { const received = data[ 'wp-refresh-post-lock' ]; @@ -55,8 +55,8 @@ export function setupHearthbeatPostLocking() { } } ); - // Unlock the post when the window is closed or exited. - jQuery( window ).on( 'unload.edit-post', function( event ) { + // Unlock the post before the window is exited. + jQuery( window ).on( 'beforeunload.edit-post', function( event ) { const postID = jQuery( '#post_ID' ).val(); const postLock = jQuery( '#active_post_lock' ).val(); From 3dfd55ba80a0076e01aa64ffbbb82ea3e5af49c0 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sat, 18 Aug 2018 17:49:58 -0700 Subject: [PATCH 30/86] complete takeover action logic --- packages/components/src/post-locked-modal/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index 9ba885888acc5..5d642640bcd67 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -27,12 +27,14 @@ class PostLockedModal extends Component { } takeOverPost() { - const { getEditorSettings } = select( 'core/editor' ); + const { getEditorSettings, getCurrentPost } = select( 'core/editor' ); const { lockNonce } = getEditorSettings(); + const { id } = getCurrentPost(); const unlockUrl = addQueryArgs( getPostEditURL(), { 'get-post-lock': '1', - nonce: lockNonce, + _wpnonce: lockNonce, lockKey: true, + post: id, } ); document.location = unlockUrl; } @@ -65,7 +67,7 @@ class PostLockedModal extends Component { From 434f9ffc466887afc467f96cb2de9421b4fab45b Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sat, 18 Aug 2018 17:50:13 -0700 Subject: [PATCH 31/86] update core data readme --- docs/data/data-core-editor.md | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/data/data-core-editor.md b/docs/data/data-core-editor.md index f6e07d9416aff..a1b21a1123d18 100644 --- a/docs/data/data-core-editor.md +++ b/docs/data/data-core-editor.md @@ -1030,6 +1030,30 @@ Returns the editor settings. The editor settings object +### isPostLocked + +Returns whether the post is locked. + +*Parameters* + + * state: Global application state. + +*Returns* + +Is locked. + +### getPostLockUser + +Returns the post lock user. + +*Parameters* + + * state: Global application state. + +*Returns* + +A user object. + ### canUserUseUnfilteredHTML Returns whether or not the user has the unfiltered_html capability. @@ -1053,6 +1077,7 @@ the specified post object and editor settings. * post: Post object. * autosaveStatus: The Post's autosave status. + * lockedUser: The Post's locked user, or false if not locked. ### resetPost @@ -1330,6 +1355,14 @@ Returns an action object used to remove a notice. * id: The notice id. +### lockPost + +Returns an action object used to remove a modal. + +*Parameters* + + * locked: Whether the editor should be locked. + ### fetchReusableBlocks Returns an action object used to fetch a single reusable block or all @@ -1422,4 +1455,4 @@ Returns an action object used in signalling that the editor settings have been u *Parameters* - * settings: Updated settings \ No newline at end of file + * settings: Updated settings From 836ba7a6af44f381929f5451e2375cf263038dc6 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sat, 18 Aug 2018 18:09:51 -0700 Subject: [PATCH 32/86] Complete takeover action, reaction --- editor/utils/heartbeat-post-locking.js | 2 +- packages/components/src/post-locked-modal/index.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/editor/utils/heartbeat-post-locking.js b/editor/utils/heartbeat-post-locking.js index 6251969ed55fe..95d65b5d515e2 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/editor/utils/heartbeat-post-locking.js @@ -29,7 +29,7 @@ export function setupHearthbeatPostLocking() { return; } - send.postId = postId; + send.post_id = postId; if ( lock ) { send.lock = lock; diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index 5d642640bcd67..1479d09150650 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -22,8 +22,9 @@ class PostLockedModal extends Component { this.takeOverPost = this.takeOverPost.bind( this ); const user = select( 'core/editor' ).getPostLockUser(); - this.takeover = sprintf( __( '%s has taken over and is currently editing. Your latest changes were saved as a revision.' ), user.data.display_name ); - this.alreadyEditing = sprintf( __( '%s is already editing this post. Do you want to take over?' ), user.data.display_name ); + const displayName = ( user && user.data ) ? user.data.display_name : __( 'Another user' ); + this.takeover = sprintf( __( '%s has taken over and is currently editing. Your latest changes were saved as a revision.' ), displayName ); + this.alreadyEditing = sprintf( __( '%s is already editing this post. Do you want to take over?' ), displayName ); } takeOverPost() { From 28490b61ccb103f9ee6528a7522da0f3aef2c604 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 19 Aug 2018 10:13:03 -0700 Subject: [PATCH 33/86] alignment for eslint --- editor/utils/heartbeat-post-locking.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/editor/utils/heartbeat-post-locking.js b/editor/utils/heartbeat-post-locking.js index 95d65b5d515e2..bddc5a3720e3b 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/editor/utils/heartbeat-post-locking.js @@ -38,22 +38,22 @@ export function setupHearthbeatPostLocking() { data[ 'wp-refresh-post-lock' ] = send; } ) - // Refresh post locks: update the lock string or show the dialog if somebody has taken over editing. - .on( 'heartbeat-tick.refresh-lock', function( e, data ) { - if ( data[ 'wp-refresh-post-lock' ] ) { - const received = data[ 'wp-refresh-post-lock' ]; + // Refresh post locks: update the lock string or show the dialog if somebody has taken over editing. + .on( 'heartbeat-tick.refresh-lock', function( e, data ) { + if ( data[ 'wp-refresh-post-lock' ] ) { + const received = data[ 'wp-refresh-post-lock' ]; - if ( received.lock_error ) { - // @todo suspend autosaving - // @todo Show "editing taken over" message. - dispatch( 'core/editor' ).lockPost( true ); - } else if ( received.new_lock ) { - jQuery( '#active_post_lock' ).val( received.new_lock ); + if ( received.lock_error ) { + // @todo suspend autosaving + // @todo Show "editing taken over" message. + dispatch( 'core/editor' ).lockPost( true ); + } else if ( received.new_lock ) { + jQuery( '#active_post_lock' ).val( received.new_lock ); - dispatch( 'core/editor' ).lockPost( false ); + dispatch( 'core/editor' ).lockPost( false ); + } } - } - } ); + } ); // Unlock the post before the window is exited. jQuery( window ).on( 'beforeunload.edit-post', function( event ) { From e37b9d5efbb5a1de95a57e573b6b6993d655c149 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 19 Aug 2018 12:03:11 -0700 Subject: [PATCH 34/86] Add the lock details to the lockPost dispatch --- editor/utils/heartbeat-post-locking.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/utils/heartbeat-post-locking.js b/editor/utils/heartbeat-post-locking.js index bddc5a3720e3b..078b817ad45ce 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/editor/utils/heartbeat-post-locking.js @@ -46,7 +46,7 @@ export function setupHearthbeatPostLocking() { if ( received.lock_error ) { // @todo suspend autosaving // @todo Show "editing taken over" message. - dispatch( 'core/editor' ).lockPost( true ); + dispatch( 'core/editor' ).lockPost( true, received.lock_error ); } else if ( received.new_lock ) { jQuery( '#active_post_lock' ).val( received.new_lock ); From f168ed39e7596c13e0e1e23da62341a7b99a58c4 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 19 Aug 2018 12:07:09 -0700 Subject: [PATCH 35/86] Ensure modal header can display an icon when passed its src --- packages/components/src/modal/header.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/modal/header.js b/packages/components/src/modal/header.js index f4cc1cfb53b7a..cf3d3d9a24624 100644 --- a/packages/components/src/modal/header.js +++ b/packages/components/src/modal/header.js @@ -18,7 +18,7 @@ const ModalHeader = ( { icon, title, onClose, closeLabel, headingId, showCloseIc
{ icon && - { icon } + { icon && { } } { title && From 08f13e6755b57ecfdd02874543578723b625718c Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 19 Aug 2018 12:07:31 -0700 Subject: [PATCH 36/86] modal icon img styles --- packages/components/src/modal/style.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/components/src/modal/style.scss b/packages/components/src/modal/style.scss index e3f5f5027194a..97212f77770a1 100644 --- a/packages/components/src/modal/style.scss +++ b/packages/components/src/modal/style.scss @@ -87,3 +87,9 @@ overflow: auto; padding: $panel-padding; } + +.components-modal__icon-container img { + width: 28px; + height: 28px; + margin-right: 5px; +} From d7062a0f9da0a26035afa6a1062e1d022a2242f0 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 19 Aug 2018 12:08:00 -0700 Subject: [PATCH 37/86] Improve post lock modal, improve all posts url construction --- .../components/src/post-locked-modal/index.js | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index 1479d09150650..ce02e0d4fe8ec 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -11,6 +11,7 @@ import { import './style.scss'; import { addQueryArgs } from '@wordpress/url'; import { getPostEditURL } from '../../../../edit-post/components/browser-url'; +import { getWPAdminURL } from '../../../editor/src/utils/url'; class PostLockedModal extends Component { constructor() { @@ -20,11 +21,18 @@ class PostLockedModal extends Component { }; this.takeOverPost = this.takeOverPost.bind( this ); + const { getLockDetails, getPostLockUser } = select( 'core/editor' ); + const lockDetails = getLockDetails(); - const user = select( 'core/editor' ).getPostLockUser(); - const displayName = ( user && user.data ) ? user.data.display_name : __( 'Another user' ); - this.takeover = sprintf( __( '%s has taken over and is currently editing. Your latest changes were saved as a revision.' ), displayName ); - this.alreadyEditing = sprintf( __( '%s is already editing this post. Do you want to take over?' ), displayName ); + if ( lockDetails && lockDetails.text ) { + this.modalText = lockDetails.text; + this.avatar = lockDetails.avatar_src; + this.takeover = true; + } else { + const user = getPostLockUser(); + const displayName = ( user && user.data ) ? user.data.display_name : __( 'Another user' ); + this.modalText = sprintf( __( '%s is already editing this post. Do you want to take over?' ), displayName ); + } } takeOverPost() { @@ -40,8 +48,8 @@ class PostLockedModal extends Component { document.location = unlockUrl; } - goBack() { - window.history.back(); + allPosts() { + document.location = getWPAdminURL( 'edit.php' ); } render() { @@ -50,28 +58,32 @@ class PostLockedModal extends Component { { this.state.isOpen ? - - - + { ! this.takeover && + + + + + } : null } From 4efcff13ba54babdc749a15e41ad66a2516c5f69 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 19 Aug 2018 12:08:23 -0700 Subject: [PATCH 38/86] Add lockedDetails to the lockPost action --- packages/editor/src/store/actions.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index a68e352579fe9..d18474ee255f3 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -595,14 +595,16 @@ export function removeNotice( id ) { /** * Returns an action object used to remove a modal. * - * @param {boolean} locked Whether the editor should be locked. + * @param {boolean} locked Whether the editor should be locked. + * @param {Object} lockDetails Details about the lock user and their avatar. * * @return {Object} Action object. */ -export function lockPost( locked ) { +export function lockPost( locked, lockDetails ) { return { type: 'LOCK_POST', locked, + lockDetails, }; } From 73c9bc55613ce4fc3e6025f03d7692eff328ec4d Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 19 Aug 2018 12:08:39 -0700 Subject: [PATCH 39/86] add lockDetails to the locked reducer --- packages/editor/src/store/reducer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/editor/src/store/reducer.js b/packages/editor/src/store/reducer.js index f1361c4353c0f..9d6e36d954d50 100644 --- a/packages/editor/src/store/reducer.js +++ b/packages/editor/src/store/reducer.js @@ -883,6 +883,7 @@ export function locked( state = false, action ) { return { ...state, locked: action.locked, + lockDetails: action.lockDetails, }; } From d2a971e4617f5c764333cad728693a6f94709f7e Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 19 Aug 2018 12:08:53 -0700 Subject: [PATCH 40/86] new selector: getLockDetails --- packages/editor/src/store/selectors.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index a7ec7f74fd7e1..2aa38d82f751d 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -1904,6 +1904,17 @@ export function isPostLocked( state ) { return !! state.locked.locked; } +/** + * Returns whether the post is locked. + * + * @param {Object} state Global application state. + * + * @return {Object} The lock details object. + */ +export function getLockDetails( state ) { + return state.locked.lockDetails; +} + /** * Returns whether the post lock user. * From c15bddcb7af755ee0846769d05382783ea233e40 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 19 Aug 2018 12:32:19 -0700 Subject: [PATCH 41/86] Add avatgar data for existing locks --- lib/client-assets.php | 9 ++++++++- packages/components/src/post-locked-modal/index.js | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index 75bbbde28b55a..38e4187183d4c 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1344,8 +1344,15 @@ function gutenberg_editor_scripts_and_styles( $hook ) { if ( apply_filters( 'show_post_locked_dialog', true, $post, $user ) ) { $locked = true; } + + if ( $avatar = get_avatar( $user->ID, 64 ) ) { + if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { + $user->avatar_src = $matches[1]; + } + } + $editor_settings['lockedUser'] = $locked ? $user : false; - $editor_settings['lockNonce'] = wp_create_nonce( 'lock-post_' . $post->ID ); + $editor_settings['lockNonce'] = wp_create_nonce( 'lock-post_' . $post->ID ); } else { $locked = false; diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index ce02e0d4fe8ec..700c4e1b1c372 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -32,6 +32,7 @@ class PostLockedModal extends Component { const user = getPostLockUser(); const displayName = ( user && user.data ) ? user.data.display_name : __( 'Another user' ); this.modalText = sprintf( __( '%s is already editing this post. Do you want to take over?' ), displayName ); + this.avatar = user.data.avatar_src; } } From 30eb34664f1b63451c25caebb105511065b2ce58 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 19 Aug 2018 12:42:05 -0700 Subject: [PATCH 42/86] dispatch an autosave when the post is taken over --- editor/utils/heartbeat-post-locking.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/editor/utils/heartbeat-post-locking.js b/editor/utils/heartbeat-post-locking.js index 078b817ad45ce..7470a60983926 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/editor/utils/heartbeat-post-locking.js @@ -42,14 +42,12 @@ export function setupHearthbeatPostLocking() { .on( 'heartbeat-tick.refresh-lock', function( e, data ) { if ( data[ 'wp-refresh-post-lock' ] ) { const received = data[ 'wp-refresh-post-lock' ]; - if ( received.lock_error ) { - // @todo suspend autosaving - // @todo Show "editing taken over" message. + // Auto save and display the takeover modal. + dispatch( 'core/editor' ).autosave(); dispatch( 'core/editor' ).lockPost( true, received.lock_error ); } else if ( received.new_lock ) { jQuery( '#active_post_lock' ).val( received.new_lock ); - dispatch( 'core/editor' ).lockPost( false ); } } From 4d1437d5d439f2fe8cd6f4733a83a624700e158e Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 19 Aug 2018 22:05:20 -0400 Subject: [PATCH 43/86] Fix for phpcs, also smaller gravatar size x2 display --- lib/client-assets.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index ecd4934162afa..1c31ceea49b47 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1420,7 +1420,8 @@ function gutenberg_editor_scripts_and_styles( $hook ) { $locked = true; } - if ( $avatar = get_avatar( $user->ID, 64 ) ) { + $avatar = get_avatar( $user->ID, 56 ); + if ( $avatar ) { if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { $user->avatar_src = $matches[1]; } From c515d54fa4d9cb42194939970672cfb490edf63a Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 19 Aug 2018 22:10:37 -0400 Subject: [PATCH 44/86] Add docs for getLockDetails --- docs/data/data-core-editor.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/data/data-core-editor.md b/docs/data/data-core-editor.md index a1b21a1123d18..df8e7b4fbb227 100644 --- a/docs/data/data-core-editor.md +++ b/docs/data/data-core-editor.md @@ -1042,6 +1042,18 @@ Returns whether the post is locked. Is locked. +### getLockDetails + +Returns details about the current post lock if available. + +*Parameters* + + * state: Global application state. + +*Returns* + +Post lock details. + ### getPostLockUser Returns the post lock user. From 809a86b5b04529207db72f1248eaa298aa88bf6f Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 19 Aug 2018 23:23:32 -0400 Subject: [PATCH 45/86] improve post locking modal style to match designs --- lib/client-assets.php | 2 +- packages/components/src/modal/index.js | 21 ++++--- packages/components/src/modal/style.scss | 6 +- .../components/src/post-locked-modal/index.js | 56 +++++++++++++------ .../src/post-locked-modal/style.scss | 10 +++- packages/editor/src/store/selectors.js | 2 +- 6 files changed, 65 insertions(+), 32 deletions(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index 1c31ceea49b47..d29e7bbc9d3ff 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1420,7 +1420,7 @@ function gutenberg_editor_scripts_and_styles( $hook ) { $locked = true; } - $avatar = get_avatar( $user->ID, 56 ); + $avatar = get_avatar( $user->ID, 64 ); if ( $avatar ) { if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { $user->avatar_src = $matches[1]; diff --git a/packages/components/src/modal/index.js b/packages/components/src/modal/index.js index 56190e517443a..8e336357bcf7c 100644 --- a/packages/components/src/modal/index.js +++ b/packages/components/src/modal/index.js @@ -118,6 +118,7 @@ class Modal extends Component { aria, instanceId, showCloseIcon, + hideTitleSection, ...otherProps } = this.props; @@ -142,15 +143,19 @@ class Modal extends Component { describedby: aria.describedby, } } { ...otherProps } > - + { + ! hideTitleSection && + + }
+ className={ 'components-modal__content' + hideTitleSection ? ' noheader' : '' }> { children }
diff --git a/packages/components/src/modal/style.scss b/packages/components/src/modal/style.scss index 97212f77770a1..a509cd9c86733 100644 --- a/packages/components/src/modal/style.scss +++ b/packages/components/src/modal/style.scss @@ -88,8 +88,6 @@ padding: $panel-padding; } -.components-modal__icon-container img { - width: 28px; - height: 28px; - margin-right: 5px; +.components-modal__content.noheader { + height: calc(100% - #{ $admin-bar-height }); } diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index 700c4e1b1c372..0c0638214a4eb 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -59,7 +59,7 @@ class PostLockedModal extends Component { { this.state.isOpen ? - - { ! this.takeover && - - - - + { + this.avatar && + { } + +
+ { this.modalText } +
+ { + this.takeover ? +

+ { __( 'View all posts' ) } +

: + + } + { ! this.takeover && + + + + + } +
: null } diff --git a/packages/components/src/post-locked-modal/style.scss b/packages/components/src/post-locked-modal/style.scss index 6b2f5d7bedbf4..ffedc9127ddc2 100644 --- a/packages/components/src/post-locked-modal/style.scss +++ b/packages/components/src/post-locked-modal/style.scss @@ -1,8 +1,16 @@ .post-locked-modal { - max-height: 140px; + max-height: 100px; + padding-right: 10px; + padding-left: 10px; + padding-top: 20px; button.button, button.components-button { margin: 5px; } + img.components-modal__image { + float: left; + margin: 8px; + margin-right: 15px; + } } diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index 2aa38d82f751d..0b25b22fc5f68 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -1905,7 +1905,7 @@ export function isPostLocked( state ) { } /** - * Returns whether the post is locked. + * Returns details about the current post lock if available. * * @param {Object} state Global application state. * From 4436ec389fbc41f7472d146b9f96be144d45e9ae Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Aug 2018 16:22:53 -0400 Subject: [PATCH 46/86] switch ajaxurl from global to editor settings --- editor/utils/heartbeat-post-locking.js | 4 ++-- lib/client-assets.php | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/editor/utils/heartbeat-post-locking.js b/editor/utils/heartbeat-post-locking.js index 7470a60983926..6c49e497d1f79 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/editor/utils/heartbeat-post-locking.js @@ -1,5 +1,3 @@ -/* global ajaxurl */ - /** * WordPress dependencies */ @@ -73,6 +71,8 @@ export function setupHearthbeatPostLocking() { post_ID: postID, active_post_lock: postLock, }; + const { getEditorSettings } = select( 'core/editor' ); + const { ajaxurl } = getEditorSettings(); jQuery.post( { async: false, diff --git a/lib/client-assets.php b/lib/client-assets.php index d29e7bbc9d3ff..f6144d6ea7d35 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1387,6 +1387,7 @@ function gutenberg_editor_scripts_and_styles( $hook ) { 'autosaveInterval' => 10, 'maxUploadFileSize' => $max_upload_size, 'allowedMimeTypes' => get_allowed_mime_types(), + 'ajaxurl' => admin_url( 'admin-ajax.php' ), ); $post_autosave = get_autosave_newer_than_post_save( $post ); From b674cf78e826e81e6a8638a9a49ca7204c2a6c6f Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Aug 2018 16:55:17 -0400 Subject: [PATCH 47/86] =?UTF-8?q?Don=E2=80=99t=20hide=20the=20modal=20titl?= =?UTF-8?q?e=20-=20display=20it=20above=20the=20existing=20content?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/components/src/modal/index.js | 22 ++++++++----------- packages/components/src/modal/style.scss | 4 ---- .../components/src/post-locked-modal/index.js | 4 +--- .../src/post-locked-modal/style.scss | 11 ++++++++-- 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/packages/components/src/modal/index.js b/packages/components/src/modal/index.js index 8e336357bcf7c..07209461a8b59 100644 --- a/packages/components/src/modal/index.js +++ b/packages/components/src/modal/index.js @@ -118,7 +118,6 @@ class Modal extends Component { aria, instanceId, showCloseIcon, - hideTitleSection, ...otherProps } = this.props; @@ -143,19 +142,16 @@ class Modal extends Component { describedby: aria.describedby, } } { ...otherProps } > - { - ! hideTitleSection && - - } +
+ className={ 'components-modal__content' }> { children }
diff --git a/packages/components/src/modal/style.scss b/packages/components/src/modal/style.scss index a509cd9c86733..e3f5f5027194a 100644 --- a/packages/components/src/modal/style.scss +++ b/packages/components/src/modal/style.scss @@ -87,7 +87,3 @@ overflow: auto; padding: $panel-padding; } - -.components-modal__content.noheader { - height: calc(100% - #{ $admin-bar-height }); -} diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index 0c0638214a4eb..b44fa0d5d73fc 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -59,15 +59,13 @@ class PostLockedModal extends Component { { this.state.isOpen ? { this.avatar && diff --git a/packages/components/src/post-locked-modal/style.scss b/packages/components/src/post-locked-modal/style.scss index ffedc9127ddc2..2408b6ab84864 100644 --- a/packages/components/src/post-locked-modal/style.scss +++ b/packages/components/src/post-locked-modal/style.scss @@ -1,8 +1,8 @@ .post-locked-modal { - max-height: 100px; + max-height: 152px; padding-right: 10px; padding-left: 10px; - padding-top: 20px; + padding-top: 10px; button.button, button.components-button { @@ -13,4 +13,11 @@ margin: 8px; margin-right: 15px; } + h1 { + font-size: 2em; + margin-top: 8px; + } + .components-modal__header { + height: 36px; + } } From 31a503281f3b1ab21ef565f006d0bbd84718e043 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Aug 2018 16:57:37 -0400 Subject: [PATCH 48/86] import { setupHearthbeatPostLocking } from '@wordpress/editor'; --- edit-post/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edit-post/index.js b/edit-post/index.js index d2035b55a94b8..eafbb76826bb0 100644 --- a/edit-post/index.js +++ b/edit-post/index.js @@ -4,7 +4,7 @@ import { registerCoreBlocks } from '@wordpress/block-library'; import { render, unmountComponentAtNode } from '@wordpress/element'; import { dispatch } from '@wordpress/data'; -import { setupHearthbeatPostLocking } from '../editor/utils/heartbeat-post-locking'; +import { setupHearthbeatPostLocking } from '@wordpress/editor'; /** * Internal dependencies From cc37e6a5bea8172ca1202502ea19b3b7d2666be6 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Aug 2018 17:06:03 -0400 Subject: [PATCH 49/86] complete move of setupHearthbeatPostLocking to editor package --- .../editor/src}/utils/heartbeat-post-locking.js | 6 ++++-- packages/editor/src/utils/index.js | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) rename {editor => packages/editor/src}/utils/heartbeat-post-locking.js (96%) diff --git a/editor/utils/heartbeat-post-locking.js b/packages/editor/src/utils/heartbeat-post-locking.js similarity index 96% rename from editor/utils/heartbeat-post-locking.js rename to packages/editor/src/utils/heartbeat-post-locking.js index 6c49e497d1f79..7e707fa4c4f45 100644 --- a/editor/utils/heartbeat-post-locking.js +++ b/packages/editor/src/utils/heartbeat-post-locking.js @@ -3,7 +3,7 @@ */ import { dispatch, select } from '@wordpress/data'; -export function setupHearthbeatPostLocking() { +const setupHearthbeatPostLocking = () => { /** * Configure Heartbeat post locks. * @@ -80,4 +80,6 @@ export function setupHearthbeatPostLocking() { url: ajaxurl, } ); } ); -} +}; + +export default setupHearthbeatPostLocking; diff --git a/packages/editor/src/utils/index.js b/packages/editor/src/utils/index.js index 3a49f66b86c90..b63cba4ce3a10 100644 --- a/packages/editor/src/utils/index.js +++ b/packages/editor/src/utils/index.js @@ -4,3 +4,7 @@ import mediaUpload from './media-upload'; export { mediaUpload }; + +import setupHearthbeatPostLocking from './heartbeat-post-locking'; + +export { setupHearthbeatPostLocking }; From 6818df1106090d76eb99a01759b50135ef897c5e Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Aug 2018 17:18:23 -0400 Subject: [PATCH 50/86] showCloseIcon -> isDismissable --- packages/components/src/modal/README.md | 4 ++-- packages/components/src/modal/header.js | 4 ++-- packages/components/src/modal/index.js | 6 +++--- packages/components/src/post-locked-modal/index.js | 2 +- packages/components/src/post-locked-modal/style.scss | 3 +++ 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/components/src/modal/README.md b/packages/components/src/modal/README.md index 2d6eb39a7cc71..85c141c602eed 100644 --- a/packages/components/src/modal/README.md +++ b/packages/components/src/modal/README.md @@ -97,9 +97,9 @@ If this property is added, it will determine whether the modal requests to close - Required: No - Default: true -### showCloseIcon +### isDismissable -If this property is set to false, the modal will not display a close icon. +If this property is set to false, the modal will not display a close icon and cannot be dismissed. - Type: `bool` - Required: No diff --git a/packages/components/src/modal/header.js b/packages/components/src/modal/header.js index cf3d3d9a24624..1dba7fcacae76 100644 --- a/packages/components/src/modal/header.js +++ b/packages/components/src/modal/header.js @@ -8,7 +8,7 @@ import { __ } from '@wordpress/i18n'; */ import IconButton from '../icon-button'; -const ModalHeader = ( { icon, title, onClose, closeLabel, headingId, showCloseIcon } ) => { +const ModalHeader = ( { icon, title, onClose, closeLabel, headingId, isDismissable } ) => { const label = closeLabel ? closeLabel : __( 'Close dialog' ); return ( @@ -28,7 +28,7 @@ const ModalHeader = ( { icon, title, onClose, closeLabel, headingId, showCloseIc }
- { showCloseIcon && + { isDismissable && { diff --git a/packages/components/src/post-locked-modal/style.scss b/packages/components/src/post-locked-modal/style.scss index 2408b6ab84864..2105deb61e880 100644 --- a/packages/components/src/post-locked-modal/style.scss +++ b/packages/components/src/post-locked-modal/style.scss @@ -20,4 +20,7 @@ .components-modal__header { height: 36px; } + .components-modal__content { + overflow: hidden; + } } From 2c1fcf0ab2086d9d6e909386745aa71c1169a725 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Aug 2018 17:29:08 -0400 Subject: [PATCH 51/86] post lock modal - switch to withSelect --- docs/data/data-core-editor.md | 7 +++--- .../components/src/post-locked-modal/index.js | 22 +++++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/docs/data/data-core-editor.md b/docs/data/data-core-editor.md index df8e7b4fbb227..a2dc5bc9dd84f 100644 --- a/docs/data/data-core-editor.md +++ b/docs/data/data-core-editor.md @@ -1052,11 +1052,11 @@ Returns details about the current post lock if available. *Returns* -Post lock details. +The lock details object. ### getPostLockUser -Returns the post lock user. +Returns whether the post lock user. *Parameters* @@ -1374,6 +1374,7 @@ Returns an action object used to remove a modal. *Parameters* * locked: Whether the editor should be locked. + * lockDetails: Details about the lock user and their avatar. ### fetchReusableBlocks @@ -1467,4 +1468,4 @@ Returns an action object used in signalling that the editor settings have been u *Parameters* - * settings: Updated settings + * settings: Updated settings \ No newline at end of file diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index 330278df6ffe4..695d6b36e8c91 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -4,10 +4,11 @@ import { __, sprintf } from '@wordpress/i18n'; import { Modal } from '@wordpress/components'; import { Component, Fragment } from '@wordpress/element'; -import { select } from '@wordpress/data'; import { PostPreviewButton, } from '@wordpress/editor'; +import { withSelect } from '@wordpress/data'; + import './style.scss'; import { addQueryArgs } from '@wordpress/url'; import { getPostEditURL } from '../../../../edit-post/components/browser-url'; @@ -21,15 +22,14 @@ class PostLockedModal extends Component { }; this.takeOverPost = this.takeOverPost.bind( this ); - const { getLockDetails, getPostLockUser } = select( 'core/editor' ); - const lockDetails = getLockDetails(); + const { lockDetails } = this.props; if ( lockDetails && lockDetails.text ) { this.modalText = lockDetails.text; this.avatar = lockDetails.avatar_src; this.takeover = true; } else { - const user = getPostLockUser(); + const { user } = this.props; const displayName = ( user && user.data ) ? user.data.display_name : __( 'Another user' ); this.modalText = sprintf( __( '%s is already editing this post. Do you want to take over?' ), displayName ); this.avatar = user.data.avatar_src; @@ -37,9 +37,7 @@ class PostLockedModal extends Component { } takeOverPost() { - const { getEditorSettings, getCurrentPost } = select( 'core/editor' ); - const { lockNonce } = getEditorSettings(); - const { id } = getCurrentPost(); + const { lockNonce, id } = this.props(); const unlockUrl = addQueryArgs( getPostEditURL(), { 'get-post-lock': '1', _wpnonce: lockNonce, @@ -112,5 +110,11 @@ class PostLockedModal extends Component { ); } } - -export default PostLockedModal; +withSelect( ( select ) => { + return { + lockDetails: select( 'core/edit-post' ).getLockDetails(), + user: select( 'core/edit-post' ).getPostLockUser(), + id: select( 'core/edit-post' ).getCurrentPost(), + lockNonce: select( 'core/edit-post' ).getEditorSettings(), + }; +} )( PostLockedModal ); From 7e2119ef035ce70d3a6db08f6c01e3ec42ef0ffa Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 24 Aug 2018 14:01:50 -0600 Subject: [PATCH 52/86] Revert "post lock modal - switch to withSelect" This reverts commit 2c1fcf0ab2086d9d6e909386745aa71c1169a725. --- docs/data/data-core-editor.md | 7 +++--- .../components/src/post-locked-modal/index.js | 22 ++++++++----------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/docs/data/data-core-editor.md b/docs/data/data-core-editor.md index a2dc5bc9dd84f..df8e7b4fbb227 100644 --- a/docs/data/data-core-editor.md +++ b/docs/data/data-core-editor.md @@ -1052,11 +1052,11 @@ Returns details about the current post lock if available. *Returns* -The lock details object. +Post lock details. ### getPostLockUser -Returns whether the post lock user. +Returns the post lock user. *Parameters* @@ -1374,7 +1374,6 @@ Returns an action object used to remove a modal. *Parameters* * locked: Whether the editor should be locked. - * lockDetails: Details about the lock user and their avatar. ### fetchReusableBlocks @@ -1468,4 +1467,4 @@ Returns an action object used in signalling that the editor settings have been u *Parameters* - * settings: Updated settings \ No newline at end of file + * settings: Updated settings diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index 695d6b36e8c91..330278df6ffe4 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -4,11 +4,10 @@ import { __, sprintf } from '@wordpress/i18n'; import { Modal } from '@wordpress/components'; import { Component, Fragment } from '@wordpress/element'; +import { select } from '@wordpress/data'; import { PostPreviewButton, } from '@wordpress/editor'; -import { withSelect } from '@wordpress/data'; - import './style.scss'; import { addQueryArgs } from '@wordpress/url'; import { getPostEditURL } from '../../../../edit-post/components/browser-url'; @@ -22,14 +21,15 @@ class PostLockedModal extends Component { }; this.takeOverPost = this.takeOverPost.bind( this ); - const { lockDetails } = this.props; + const { getLockDetails, getPostLockUser } = select( 'core/editor' ); + const lockDetails = getLockDetails(); if ( lockDetails && lockDetails.text ) { this.modalText = lockDetails.text; this.avatar = lockDetails.avatar_src; this.takeover = true; } else { - const { user } = this.props; + const user = getPostLockUser(); const displayName = ( user && user.data ) ? user.data.display_name : __( 'Another user' ); this.modalText = sprintf( __( '%s is already editing this post. Do you want to take over?' ), displayName ); this.avatar = user.data.avatar_src; @@ -37,7 +37,9 @@ class PostLockedModal extends Component { } takeOverPost() { - const { lockNonce, id } = this.props(); + const { getEditorSettings, getCurrentPost } = select( 'core/editor' ); + const { lockNonce } = getEditorSettings(); + const { id } = getCurrentPost(); const unlockUrl = addQueryArgs( getPostEditURL(), { 'get-post-lock': '1', _wpnonce: lockNonce, @@ -110,11 +112,5 @@ class PostLockedModal extends Component { ); } } -withSelect( ( select ) => { - return { - lockDetails: select( 'core/edit-post' ).getLockDetails(), - user: select( 'core/edit-post' ).getPostLockUser(), - id: select( 'core/edit-post' ).getCurrentPost(), - lockNonce: select( 'core/edit-post' ).getEditorSettings(), - }; -} )( PostLockedModal ); + +export default PostLockedModal; From a7987b8c15ecbe1414db63362f9f16e8b3bd8a57 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 24 Aug 2018 14:15:20 -0600 Subject: [PATCH 53/86] modal cleanup and withSelect rework --- .../components/src/post-locked-modal/index.js | 20 ++++++++++--------- .../src/post-locked-modal/style.scss | 5 +---- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index 330278df6ffe4..3c50b1963a96b 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -4,7 +4,7 @@ import { __, sprintf } from '@wordpress/i18n'; import { Modal } from '@wordpress/components'; import { Component, Fragment } from '@wordpress/element'; -import { select } from '@wordpress/data'; +import { withSelect } from '@wordpress/data'; import { PostPreviewButton, } from '@wordpress/editor'; @@ -19,17 +19,14 @@ class PostLockedModal extends Component { this.state = { isOpen: true, }; - this.takeOverPost = this.takeOverPost.bind( this ); - const { getLockDetails, getPostLockUser } = select( 'core/editor' ); - const lockDetails = getLockDetails(); + const { lockDetails, user } = this.props; if ( lockDetails && lockDetails.text ) { this.modalText = lockDetails.text; this.avatar = lockDetails.avatar_src; this.takeover = true; } else { - const user = getPostLockUser(); const displayName = ( user && user.data ) ? user.data.display_name : __( 'Another user' ); this.modalText = sprintf( __( '%s is already editing this post. Do you want to take over?' ), displayName ); this.avatar = user.data.avatar_src; @@ -37,9 +34,7 @@ class PostLockedModal extends Component { } takeOverPost() { - const { getEditorSettings, getCurrentPost } = select( 'core/editor' ); - const { lockNonce } = getEditorSettings(); - const { id } = getCurrentPost(); + const { lockNonce, id } = this.props; const unlockUrl = addQueryArgs( getPostEditURL(), { 'get-post-lock': '1', _wpnonce: lockNonce, @@ -113,4 +108,11 @@ class PostLockedModal extends Component { } } -export default PostLockedModal; +export default withSelect( ( select ) => { + return { + lockDetails: select( 'core/editor' ).getLockDetails(), + user: select( 'core/editor' ).getPostLockUser(), + id: select( 'core/editor' ).getCurrentPost().id, + lockNonce: select( 'core/editor' ).getEditorSettings().lockNonce, + }; +} )( PostLockedModal ); diff --git a/packages/components/src/post-locked-modal/style.scss b/packages/components/src/post-locked-modal/style.scss index 2105deb61e880..86f07dce26344 100644 --- a/packages/components/src/post-locked-modal/style.scss +++ b/packages/components/src/post-locked-modal/style.scss @@ -13,10 +13,7 @@ margin: 8px; margin-right: 15px; } - h1 { - font-size: 2em; - margin-top: 8px; - } + .components-modal__header { height: 36px; } From b9aac75c9a52e92efdff9258efd194012e50165a Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 24 Aug 2018 14:21:03 -0600 Subject: [PATCH 54/86] improve avatar image alignment --- packages/components/src/post-locked-modal/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/post-locked-modal/style.scss b/packages/components/src/post-locked-modal/style.scss index 86f07dce26344..6ad3982f9f71e 100644 --- a/packages/components/src/post-locked-modal/style.scss +++ b/packages/components/src/post-locked-modal/style.scss @@ -10,7 +10,7 @@ } img.components-modal__image { float: left; - margin: 8px; + margin: 5px; margin-right: 15px; } From b7ff092f3bd8acba221eed4838d3067a5687326e Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 24 Aug 2018 14:36:48 -0600 Subject: [PATCH 55/86] Use a href links instead of action handlers for buttons --- .../components/src/post-locked-modal/index.js | 43 ++++++++----------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index 3c50b1963a96b..fec13ae2c4714 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -19,7 +19,6 @@ class PostLockedModal extends Component { this.state = { isOpen: true, }; - this.takeOverPost = this.takeOverPost.bind( this ); const { lockDetails, user } = this.props; if ( lockDetails && lockDetails.text ) { @@ -33,7 +32,7 @@ class PostLockedModal extends Component { } } - takeOverPost() { + render() { const { lockNonce, id } = this.props; const unlockUrl = addQueryArgs( getPostEditURL(), { 'get-post-lock': '1', @@ -41,14 +40,8 @@ class PostLockedModal extends Component { lockKey: true, post: id, } ); - document.location = unlockUrl; - } + const allPosts = getWPAdminURL( 'edit.php' ); - allPosts() { - document.location = getWPAdminURL( 'edit.php' ); - } - - render() { return ( { @@ -76,27 +69,25 @@ class PostLockedModal extends Component { { this.takeover ? -

- { __( 'View all posts' ) } -

: - +

+ + { __( 'View all posts' ) } + +

: + + + } { ! this.takeover && - + + + } From 04760237aded4f2987ea04225af11e9e654d23b0 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 24 Aug 2018 14:41:04 -0600 Subject: [PATCH 56/86] no closing --- packages/components/src/post-locked-modal/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index fec13ae2c4714..61489498c5eb7 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -48,7 +48,6 @@ class PostLockedModal extends Component { this.state.isOpen ? Date: Fri, 24 Aug 2018 15:13:39 -0600 Subject: [PATCH 57/86] Try moving to editor package --- edit-post/editor.js | 3 +-- packages/components/src/modal/style.scss | 25 +++++++++++++++++++ packages/editor/src/components/index.js | 1 + .../components}/post-locked-modal/index.js | 22 +++++++--------- .../components}/post-locked-modal/style.scss | 1 + 5 files changed, 37 insertions(+), 15 deletions(-) rename packages/{components/src => editor/src/components}/post-locked-modal/index.js (81%) rename packages/{components/src => editor/src/components}/post-locked-modal/style.scss (96%) diff --git a/edit-post/editor.js b/edit-post/editor.js index 59b2d8e9933ea..1d016eede943a 100644 --- a/edit-post/editor.js +++ b/edit-post/editor.js @@ -2,9 +2,8 @@ * WordPress dependencies */ import { withSelect } from '@wordpress/data'; -import { EditorProvider, ErrorBoundary } from '@wordpress/editor'; +import { EditorProvider, ErrorBoundary, PostLockedModal } from '@wordpress/editor'; import { StrictMode } from '@wordpress/element'; -import PostLockedModal from '../packages/components/src/post-locked-modal'; /** * Internal dependencies */ diff --git a/packages/components/src/modal/style.scss b/packages/components/src/modal/style.scss index e3f5f5027194a..df8256e4f222c 100644 --- a/packages/components/src/modal/style.scss +++ b/packages/components/src/modal/style.scss @@ -87,3 +87,28 @@ overflow: auto; padding: $panel-padding; } + +.post-locked-modal { + max-height: 152px; + padding-right: 10px; + padding-left: 10px; + padding-top: 10px; + border: red; + + a.button, + button.components-button { + margin: 5px; + } + img.components-modal__image { + float: left; + margin: 5px; + margin-right: 15px; + } + + .components-modal__header { + height: 36px; + } + .components-modal__content { + overflow: hidden; + } +} diff --git a/packages/editor/src/components/index.js b/packages/editor/src/components/index.js index 3e909f4f784f6..5d201d0f92551 100644 --- a/packages/editor/src/components/index.js +++ b/packages/editor/src/components/index.js @@ -77,6 +77,7 @@ export { default as PostVisibilityCheck } from './post-visibility/check'; export { default as TableOfContents } from './table-of-contents'; export { default as UnsavedChangesWarning } from './unsaved-changes-warning'; export { default as WordCount } from './word-count'; +export { default as PostLockedModal } from './post-locked-modal'; // Content Related Components export { default as BlockInspector } from './block-inspector'; diff --git a/packages/components/src/post-locked-modal/index.js b/packages/editor/src/components/post-locked-modal/index.js similarity index 81% rename from packages/components/src/post-locked-modal/index.js rename to packages/editor/src/components/post-locked-modal/index.js index 61489498c5eb7..f5b0c6b0d6252 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/editor/src/components/post-locked-modal/index.js @@ -7,11 +7,11 @@ import { Component, Fragment } from '@wordpress/element'; import { withSelect } from '@wordpress/data'; import { PostPreviewButton, -} from '@wordpress/editor'; -import './style.scss'; +} from '../post-preview-button'; + import { addQueryArgs } from '@wordpress/url'; -import { getPostEditURL } from '../../../../edit-post/components/browser-url'; -import { getWPAdminURL } from '../../../editor/src/utils/url'; +import { getPostEditURL } from '../../../../../edit-post/components/browser-url'; +import { getWPAdminURL } from '../../../src/utils/url'; class PostLockedModal extends Component { constructor() { @@ -69,23 +69,19 @@ class PostLockedModal extends Component { { this.takeover ?

- + { __( 'View all posts' ) }

: - - + + { __( 'All Posts' ) } } { ! this.takeover && - - + + { __( 'Take Over' ) } } diff --git a/packages/components/src/post-locked-modal/style.scss b/packages/editor/src/components/post-locked-modal/style.scss similarity index 96% rename from packages/components/src/post-locked-modal/style.scss rename to packages/editor/src/components/post-locked-modal/style.scss index 6ad3982f9f71e..d01e1c41b971e 100644 --- a/packages/components/src/post-locked-modal/style.scss +++ b/packages/editor/src/components/post-locked-modal/style.scss @@ -3,6 +3,7 @@ padding-right: 10px; padding-left: 10px; padding-top: 10px; + border: red; button.button, button.components-button { From 95f5f5c7459968d9ab31dc1b4225bd9b32f6826c Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 24 Aug 2018 15:14:13 -0600 Subject: [PATCH 58/86] Revert "Try moving to editor package" This reverts commit ca9fa6055770bd55e7c95729aca0ecc5c8f64680. --- edit-post/editor.js | 3 ++- packages/components/src/modal/style.scss | 25 ------------------- .../src}/post-locked-modal/index.js | 22 +++++++++------- .../src}/post-locked-modal/style.scss | 1 - packages/editor/src/components/index.js | 1 - 5 files changed, 15 insertions(+), 37 deletions(-) rename packages/{editor/src/components => components/src}/post-locked-modal/index.js (81%) rename packages/{editor/src/components => components/src}/post-locked-modal/style.scss (96%) diff --git a/edit-post/editor.js b/edit-post/editor.js index 1d016eede943a..59b2d8e9933ea 100644 --- a/edit-post/editor.js +++ b/edit-post/editor.js @@ -2,8 +2,9 @@ * WordPress dependencies */ import { withSelect } from '@wordpress/data'; -import { EditorProvider, ErrorBoundary, PostLockedModal } from '@wordpress/editor'; +import { EditorProvider, ErrorBoundary } from '@wordpress/editor'; import { StrictMode } from '@wordpress/element'; +import PostLockedModal from '../packages/components/src/post-locked-modal'; /** * Internal dependencies */ diff --git a/packages/components/src/modal/style.scss b/packages/components/src/modal/style.scss index df8256e4f222c..e3f5f5027194a 100644 --- a/packages/components/src/modal/style.scss +++ b/packages/components/src/modal/style.scss @@ -87,28 +87,3 @@ overflow: auto; padding: $panel-padding; } - -.post-locked-modal { - max-height: 152px; - padding-right: 10px; - padding-left: 10px; - padding-top: 10px; - border: red; - - a.button, - button.components-button { - margin: 5px; - } - img.components-modal__image { - float: left; - margin: 5px; - margin-right: 15px; - } - - .components-modal__header { - height: 36px; - } - .components-modal__content { - overflow: hidden; - } -} diff --git a/packages/editor/src/components/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js similarity index 81% rename from packages/editor/src/components/post-locked-modal/index.js rename to packages/components/src/post-locked-modal/index.js index f5b0c6b0d6252..61489498c5eb7 100644 --- a/packages/editor/src/components/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -7,11 +7,11 @@ import { Component, Fragment } from '@wordpress/element'; import { withSelect } from '@wordpress/data'; import { PostPreviewButton, -} from '../post-preview-button'; - +} from '@wordpress/editor'; +import './style.scss'; import { addQueryArgs } from '@wordpress/url'; -import { getPostEditURL } from '../../../../../edit-post/components/browser-url'; -import { getWPAdminURL } from '../../../src/utils/url'; +import { getPostEditURL } from '../../../../edit-post/components/browser-url'; +import { getWPAdminURL } from '../../../editor/src/utils/url'; class PostLockedModal extends Component { constructor() { @@ -69,19 +69,23 @@ class PostLockedModal extends Component { { this.takeover ?

- + { __( 'View all posts' ) }

: - - { __( 'All Posts' ) } + + } { ! this.takeover && - - { __( 'Take Over' ) } + + } diff --git a/packages/editor/src/components/post-locked-modal/style.scss b/packages/components/src/post-locked-modal/style.scss similarity index 96% rename from packages/editor/src/components/post-locked-modal/style.scss rename to packages/components/src/post-locked-modal/style.scss index d01e1c41b971e..6ad3982f9f71e 100644 --- a/packages/editor/src/components/post-locked-modal/style.scss +++ b/packages/components/src/post-locked-modal/style.scss @@ -3,7 +3,6 @@ padding-right: 10px; padding-left: 10px; padding-top: 10px; - border: red; button.button, button.components-button { diff --git a/packages/editor/src/components/index.js b/packages/editor/src/components/index.js index 5d201d0f92551..3e909f4f784f6 100644 --- a/packages/editor/src/components/index.js +++ b/packages/editor/src/components/index.js @@ -77,7 +77,6 @@ export { default as PostVisibilityCheck } from './post-visibility/check'; export { default as TableOfContents } from './table-of-contents'; export { default as UnsavedChangesWarning } from './unsaved-changes-warning'; export { default as WordCount } from './word-count'; -export { default as PostLockedModal } from './post-locked-modal'; // Content Related Components export { default as BlockInspector } from './block-inspector'; From c03878f8d8903f766da26db679dbf8eb50d7306c Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 24 Aug 2018 15:18:03 -0600 Subject: [PATCH 59/86] remove inner buttons, not needed --- packages/components/src/post-locked-modal/index.js | 12 ++++-------- packages/components/src/post-locked-modal/style.scss | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index 61489498c5eb7..ce8ffa02be729 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -73,19 +73,15 @@ class PostLockedModal extends Component { { __( 'View all posts' ) }

: - - + + { __( 'All Posts' ) } } { ! this.takeover && - - + + { __( 'Take Over' ) } } diff --git a/packages/components/src/post-locked-modal/style.scss b/packages/components/src/post-locked-modal/style.scss index 6ad3982f9f71e..8a41035e21d3f 100644 --- a/packages/components/src/post-locked-modal/style.scss +++ b/packages/components/src/post-locked-modal/style.scss @@ -4,7 +4,7 @@ padding-left: 10px; padding-top: 10px; - button.button, + a.button, button.components-button { margin: 5px; } From 7cdb082f7fbcbdc89519be0502f864ffe867d0e5 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sat, 25 Aug 2018 22:07:08 -0600 Subject: [PATCH 60/86] clean up modal imports --- packages/components/src/post-locked-modal/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js index ce8ffa02be729..b223043576417 100644 --- a/packages/components/src/post-locked-modal/index.js +++ b/packages/components/src/post-locked-modal/index.js @@ -5,13 +5,10 @@ import { __, sprintf } from '@wordpress/i18n'; import { Modal } from '@wordpress/components'; import { Component, Fragment } from '@wordpress/element'; import { withSelect } from '@wordpress/data'; -import { - PostPreviewButton, -} from '@wordpress/editor'; +import { PostPreviewButton, getWPAdminURL } from '@wordpress/editor'; import './style.scss'; import { addQueryArgs } from '@wordpress/url'; import { getPostEditURL } from '../../../../edit-post/components/browser-url'; -import { getWPAdminURL } from '../../../editor/src/utils/url'; class PostLockedModal extends Component { constructor() { From 42e45dcebff5a5b304ed5f3f3712bc666c131e32 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 26 Aug 2018 16:04:41 -0600 Subject: [PATCH 61/86] improve heartbeat post locking setup --- edit-post/index.js | 4 +- gutenberg.php | 9 +---- lib/client-assets.php | 8 ++++ .../src/utils/heartbeat-post-locking.js | 38 +++++++++++-------- packages/editor/src/utils/index.js | 7 ++-- 5 files changed, 37 insertions(+), 29 deletions(-) diff --git a/edit-post/index.js b/edit-post/index.js index eafbb76826bb0..86bdba36bbf54 100644 --- a/edit-post/index.js +++ b/edit-post/index.js @@ -4,7 +4,7 @@ import { registerCoreBlocks } from '@wordpress/block-library'; import { render, unmountComponentAtNode } from '@wordpress/element'; import { dispatch } from '@wordpress/data'; -import { setupHearthbeatPostLocking } from '@wordpress/editor'; +import { hearthbeatPostLocking } from '@wordpress/editor'; /** * Internal dependencies @@ -57,7 +57,7 @@ export function initializeEditor( id, postType, postId, settings, overridePost ) registerCoreBlocks(); // Set up heartbeat post locking. - setupHearthbeatPostLocking(); + hearthbeatPostLocking( postId, settings ); dispatch( 'core/nux' ).triggerGuide( [ 'core/editor.inserter', diff --git a/gutenberg.php b/gutenberg.php index 8e51e7650c717..8a6b40f77695c 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -25,14 +25,7 @@ */ function the_gutenberg_project() { global $post_type_object, $post; - - if ( ! wp_check_post_lock( $post->ID ) ) { - $active_post_lock = wp_set_post_lock( $post->ID ); - } - - if ( ! empty( $active_post_lock ) ) { ?> - - + ?>

labels->edit_item ); ?>

diff --git a/lib/client-assets.php b/lib/client-assets.php index f6144d6ea7d35..e7c82e6720c9b 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1402,6 +1402,11 @@ function gutenberg_editor_scripts_and_styles( $hook ) { $user_id = wp_check_post_lock( $post->ID ); if ( $user_id ) { $user = get_userdata( $user_id ); + } else { + + // Lock the post. + $active_post_lock = wp_set_post_lock( $post->ID ); + $editor_settings['activePostLock'] = esc_attr( implode( ':', $active_post_lock ) ); } if ( $user ) { @@ -1436,6 +1441,9 @@ function gutenberg_editor_scripts_and_styles( $hook ) { } $editor_settings['locked'] = $locked; + // Add a nonce for post unlocking on window unload. + $editor_settings['_wpnonce'] = wp_create_nonce( 'update-post_' . $post->ID ); + if ( false !== $color_palette ) { $editor_settings['colors'] = $color_palette; } diff --git a/packages/editor/src/utils/heartbeat-post-locking.js b/packages/editor/src/utils/heartbeat-post-locking.js index 7e707fa4c4f45..7eb43e47688e1 100644 --- a/packages/editor/src/utils/heartbeat-post-locking.js +++ b/packages/editor/src/utils/heartbeat-post-locking.js @@ -3,18 +3,26 @@ */ import { dispatch, select } from '@wordpress/data'; -const setupHearthbeatPostLocking = () => { +/** + * Configure Heartbeat post locks. + * + * Used to lock editing of an object by only one user at a time. + * + * @param {number} postId The post Id. + * @param {Object} settings The editor settings. + */ +const hearthbeatPostLocking = ( postId, settings ) => { + // Track the current post lock. + let activePostLock = settings.activePostLock; + /** - * Configure Heartbeat post locks. - * - * Used to lock editing of an object by only one user at a time. + * Keep the lock refreshed. * * When the user does not send a heartbeat in a heartbeat-tick * the user is no longer editing and another user can start editing. */ jQuery( document ).on( 'heartbeat-send.refresh-lock', function( e, data ) { - const lock = jQuery( '#active_post_lock' ).val(), - postId = jQuery( '#post_ID' ).val(), + const lock = activePostLock, send = {}; if ( ! postId ) { @@ -45,7 +53,7 @@ const setupHearthbeatPostLocking = () => { dispatch( 'core/editor' ).autosave(); dispatch( 'core/editor' ).lockPost( true, received.lock_error ); } else if ( received.new_lock ) { - jQuery( '#active_post_lock' ).val( received.new_lock ); + activePostLock = received.new_lock; dispatch( 'core/editor' ).lockPost( false ); } } @@ -53,33 +61,31 @@ const setupHearthbeatPostLocking = () => { // Unlock the post before the window is exited. jQuery( window ).on( 'beforeunload.edit-post', function( event ) { - const postID = jQuery( '#post_ID' ).val(); - const postLock = jQuery( '#active_post_lock' ).val(); + const postLock = activePostLock; // Make sure we process only the main document unload. if ( event.target && event.target.nodeName !== '#document' ) { return; } - if ( ! postID || ! postLock ) { + if ( ! postId || ! postLock ) { return; } const data = { action: 'wp-remove-post-lock', - _wpnonce: jQuery( '#_wpnonce' ).val(), - post_ID: postID, + _wpnonce: settings._wpnonce, + post_ID: postId, active_post_lock: postLock, }; - const { getEditorSettings } = select( 'core/editor' ); - const { ajaxurl } = getEditorSettings(); jQuery.post( { async: false, data: data, - url: ajaxurl, + url: settings.ajaxurl, } ); } ); }; -export default setupHearthbeatPostLocking; +export default hearthbeatPostLocking; + diff --git a/packages/editor/src/utils/index.js b/packages/editor/src/utils/index.js index b63cba4ce3a10..966568635c381 100644 --- a/packages/editor/src/utils/index.js +++ b/packages/editor/src/utils/index.js @@ -2,9 +2,10 @@ * Internal dependencies */ import mediaUpload from './media-upload'; - export { mediaUpload }; -import setupHearthbeatPostLocking from './heartbeat-post-locking'; +import hearthbeatPostLocking from './heartbeat-post-locking'; +export { hearthbeatPostLocking }; -export { setupHearthbeatPostLocking }; +import { getWPAdminURL } from './url'; +export { getWPAdminURL }; From a0c57de5b2ca5f652a4d13495ade4b9f5d8347c3 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 26 Aug 2018 16:16:08 -0600 Subject: [PATCH 62/86] docs update --- docs/data/data-core-editor.md | 2 +- packages/editor/src/store/actions.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/data/data-core-editor.md b/docs/data/data-core-editor.md index df8e7b4fbb227..b3bf79639b840 100644 --- a/docs/data/data-core-editor.md +++ b/docs/data/data-core-editor.md @@ -1369,7 +1369,7 @@ Returns an action object used to remove a notice. ### lockPost -Returns an action object used to remove a modal. +Returns an action object used to lock the editor. *Parameters* diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index d18474ee255f3..3092554fbfc39 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -593,7 +593,7 @@ export function removeNotice( id ) { } /** - * Returns an action object used to remove a modal. + * Returns an action object used to lock the editor. * * @param {boolean} locked Whether the editor should be locked. * @param {Object} lockDetails Details about the lock user and their avatar. From aad9b92ac7fa64d71560fc7a69d51eeb29c15f53 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 26 Aug 2018 16:17:37 -0600 Subject: [PATCH 63/86] more docs cleanup --- packages/editor/src/store/selectors.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index 0b25b22fc5f68..ef3e622cffd81 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -1896,7 +1896,7 @@ export function getTokenSettings( state, name ) { /** * Returns whether the post is locked. * - * @param {Object} state Global application state. + * @param {Object} state Global application state. * * @return {boolean} Is locked. */ @@ -1916,9 +1916,9 @@ export function getLockDetails( state ) { } /** - * Returns whether the post lock user. + * Returns details about the post lock user. * - * @param {Object} state Global application state. + * @param {Object} state Global application state. * * @return {Object} A user object. */ From 0534539c8e9bc2812f82e6868cc6837e5e9c2369 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Sun, 26 Aug 2018 16:49:19 -0600 Subject: [PATCH 64/86] Fixes for phpcs --- lib/client-assets.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index e7c82e6720c9b..d376764a3ac30 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1405,7 +1405,7 @@ function gutenberg_editor_scripts_and_styles( $hook ) { } else { // Lock the post. - $active_post_lock = wp_set_post_lock( $post->ID ); + $active_post_lock = wp_set_post_lock( $post->ID ); $editor_settings['activePostLock'] = esc_attr( implode( ':', $active_post_lock ) ); } @@ -1442,7 +1442,7 @@ function gutenberg_editor_scripts_and_styles( $hook ) { $editor_settings['locked'] = $locked; // Add a nonce for post unlocking on window unload. - $editor_settings['_wpnonce'] = wp_create_nonce( 'update-post_' . $post->ID ); + $editor_settings['_wpnonce'] = wp_create_nonce( 'update-post_' . $post->ID ); if ( false !== $color_palette ) { $editor_settings['colors'] = $color_palette; From 8d071c18fc96c592f0de5960614c3b1e801da581 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 29 Aug 2018 10:40:41 +0100 Subject: [PATCH 65/86] Remove specific Modal Header Icon --- packages/components/src/modal/header.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/modal/header.js b/packages/components/src/modal/header.js index 1dba7fcacae76..7ce8b7473e89c 100644 --- a/packages/components/src/modal/header.js +++ b/packages/components/src/modal/header.js @@ -18,7 +18,7 @@ const ModalHeader = ( { icon, title, onClose, closeLabel, headingId, isDismissab
{ icon && - { icon && { } + { icon } } { title && From 5d767cb3c9cc44f66158f7cc5904365dde0ca5de Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 29 Aug 2018 10:58:01 +0100 Subject: [PATCH 66/86] Move the PostLockedModal to the editor module --- edit-post/editor.js | 8 +- .../components/src/post-locked-modal/index.js | 101 ------------------ packages/editor/src/components/index.js | 1 + .../src/components/post-locked-modal/index.js | 94 ++++++++++++++++ .../components}/post-locked-modal/style.scss | 0 packages/editor/src/style.scss | 1 + 6 files changed, 99 insertions(+), 106 deletions(-) delete mode 100644 packages/components/src/post-locked-modal/index.js create mode 100644 packages/editor/src/components/post-locked-modal/index.js rename packages/{components/src => editor/src/components}/post-locked-modal/style.scss (100%) diff --git a/edit-post/editor.js b/edit-post/editor.js index 59b2d8e9933ea..a6b0d10218168 100644 --- a/edit-post/editor.js +++ b/edit-post/editor.js @@ -2,15 +2,14 @@ * WordPress dependencies */ import { withSelect } from '@wordpress/data'; -import { EditorProvider, ErrorBoundary } from '@wordpress/editor'; +import { EditorProvider, ErrorBoundary, PostLockedModal } from '@wordpress/editor'; import { StrictMode } from '@wordpress/element'; -import PostLockedModal from '../packages/components/src/post-locked-modal'; /** * Internal dependencies */ import Layout from './components/layout'; -function Editor( { settings, hasFixedToolbar, post, isLocked, overridePost, onError, ...props } ) { +function Editor( { settings, hasFixedToolbar, post, overridePost, onError, ...props } ) { if ( ! post ) { return null; } @@ -26,7 +25,7 @@ function Editor( { settings, hasFixedToolbar, post, isLocked, overridePost, onEr - { isLocked && } + ); @@ -35,5 +34,4 @@ function Editor( { settings, hasFixedToolbar, post, isLocked, overridePost, onEr export default withSelect( ( select, { postId, postType } ) => ( { hasFixedToolbar: select( 'core/edit-post' ).isFeatureActive( 'fixedToolbar' ), post: select( 'core' ).getEntityRecord( 'postType', postType, postId ), - isLocked: select( 'core/editor' ).isPostLocked(), } ) )( Editor ); diff --git a/packages/components/src/post-locked-modal/index.js b/packages/components/src/post-locked-modal/index.js deleted file mode 100644 index b223043576417..0000000000000 --- a/packages/components/src/post-locked-modal/index.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * WordPress dependencies - */ -import { __, sprintf } from '@wordpress/i18n'; -import { Modal } from '@wordpress/components'; -import { Component, Fragment } from '@wordpress/element'; -import { withSelect } from '@wordpress/data'; -import { PostPreviewButton, getWPAdminURL } from '@wordpress/editor'; -import './style.scss'; -import { addQueryArgs } from '@wordpress/url'; -import { getPostEditURL } from '../../../../edit-post/components/browser-url'; - -class PostLockedModal extends Component { - constructor() { - super( ...arguments ); - this.state = { - isOpen: true, - }; - const { lockDetails, user } = this.props; - - if ( lockDetails && lockDetails.text ) { - this.modalText = lockDetails.text; - this.avatar = lockDetails.avatar_src; - this.takeover = true; - } else { - const displayName = ( user && user.data ) ? user.data.display_name : __( 'Another user' ); - this.modalText = sprintf( __( '%s is already editing this post. Do you want to take over?' ), displayName ); - this.avatar = user.data.avatar_src; - } - } - - render() { - const { lockNonce, id } = this.props; - const unlockUrl = addQueryArgs( getPostEditURL(), { - 'get-post-lock': '1', - _wpnonce: lockNonce, - lockKey: true, - post: id, - } ); - const allPosts = getWPAdminURL( 'edit.php' ); - - return ( - - { - this.state.isOpen ? - - { - this.avatar && - { - } - -
- { this.modalText } -
- { - this.takeover ? -

- - { __( 'View all posts' ) } - -

: - - { __( 'All Posts' ) } - - } - { ! this.takeover && - - - - { __( 'Take Over' ) } - - - } -
-
: - null - } -
- ); - } -} - -export default withSelect( ( select ) => { - return { - lockDetails: select( 'core/editor' ).getLockDetails(), - user: select( 'core/editor' ).getPostLockUser(), - id: select( 'core/editor' ).getCurrentPost().id, - lockNonce: select( 'core/editor' ).getEditorSettings().lockNonce, - }; -} )( PostLockedModal ); diff --git a/packages/editor/src/components/index.js b/packages/editor/src/components/index.js index 3e909f4f784f6..e014e0517a59d 100644 --- a/packages/editor/src/components/index.js +++ b/packages/editor/src/components/index.js @@ -49,6 +49,7 @@ export { default as PostFormat } from './post-format'; export { default as PostFormatCheck } from './post-format/check'; export { default as PostLastRevision } from './post-last-revision'; export { default as PostLastRevisionCheck } from './post-last-revision/check'; +export { default as PostLockedModal } from './post-locked-modal'; export { default as PostPendingStatus } from './post-pending-status'; export { default as PostPendingStatusCheck } from './post-pending-status/check'; export { default as PostPingbacks } from './post-pingbacks'; diff --git a/packages/editor/src/components/post-locked-modal/index.js b/packages/editor/src/components/post-locked-modal/index.js new file mode 100644 index 0000000000000..02a2d5a123495 --- /dev/null +++ b/packages/editor/src/components/post-locked-modal/index.js @@ -0,0 +1,94 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; +import { Modal } from '@wordpress/components'; +import { Fragment } from '@wordpress/element'; +import { withSelect } from '@wordpress/data'; +import { addQueryArgs } from '@wordpress/url'; + +/** + * Internal dependencies + */ +import { getWPAdminURL } from '../../utils/url'; +import PostPreviewButton from '../post-preview-button'; + +function PostLockedModal( { lockNonce, lockDetails, user, postId, isLocked } ) { + if ( ! isLocked ) { + return null; + } + + let modalText, avatar, takeover; + if ( lockDetails && lockDetails.text ) { + modalText = lockDetails.text; + avatar = lockDetails.avatar_src; + takeover = true; + } else { + const displayName = ( user && user.data ) ? user.data.display_name : __( 'Another user' ); + modalText = sprintf( __( '%s is already editing this post. Do you want to take over?' ), displayName ); + avatar = user.data.avatar_src; + } + + const unlockUrl = addQueryArgs( 'post.php', { + 'get-post-lock': '1', + _wpnonce: lockNonce, + lockKey: true, + post: postId, + action: 'edit', + } ); + const allPosts = getWPAdminURL( 'edit.php' ); + + return ( + + + { + !! avatar && + { + } + +
{ modalText }
+ { + !! takeover ? +

+ + { __( 'View all posts' ) } + +

: + + { __( 'All Posts' ) } + + } + { ! takeover && + + + + { __( 'Take Over' ) } + + + } +
+
+
+ ); +} + +export default withSelect( ( select ) => { + return { + isLocked: select( 'core/editor' ).isPostLocked(), + lockDetails: select( 'core/editor' ).getLockDetails(), + user: select( 'core/editor' ).getPostLockUser(), + postId: select( 'core/editor' ).getCurrentPost().id, + lockNonce: select( 'core/editor' ).getEditorSettings().lockNonce, + }; +} )( PostLockedModal ); diff --git a/packages/components/src/post-locked-modal/style.scss b/packages/editor/src/components/post-locked-modal/style.scss similarity index 100% rename from packages/components/src/post-locked-modal/style.scss rename to packages/editor/src/components/post-locked-modal/style.scss diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index 04b45188b04a4..ffece7d3db0b1 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -26,6 +26,7 @@ @import "./components/post-featured-image/style.scss"; @import "./components/post-format/style.scss"; @import "./components/post-last-revision/style.scss"; +@import "./components/post-locked-modal/style.scss"; @import "./components/post-permalink/style.scss"; @import "./components/post-publish-panel/style.scss"; @import "./components/post-saved-state/style.scss"; From 7e60a81f72b4acf5bc0fc0ce5b31d7490ad0148d Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 29 Aug 2018 11:19:20 +0100 Subject: [PATCH 67/86] Styles cleaning for the post locked modal --- edit-post/assets/stylesheets/main.scss | 4 +- .../src/components/post-locked-modal/index.js | 46 +++++++++---------- .../components/post-locked-modal/style.scss | 31 +++++++------ 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/edit-post/assets/stylesheets/main.scss b/edit-post/assets/stylesheets/main.scss index 63f488d136390..eb4751eff959a 100644 --- a/edit-post/assets/stylesheets/main.scss +++ b/edit-post/assets/stylesheets/main.scss @@ -80,7 +80,9 @@ body.gutenberg-editor-page { } } -.gutenberg { +.gutenberg, +// The modals are shown outside the .gutenberg wrapper, they need these styles +.components-modal__frame { box-sizing: border-box; *, diff --git a/packages/editor/src/components/post-locked-modal/index.js b/packages/editor/src/components/post-locked-modal/index.js index 02a2d5a123495..8fb2b639ff92f 100644 --- a/packages/editor/src/components/post-locked-modal/index.js +++ b/packages/editor/src/components/post-locked-modal/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { Modal } from '@wordpress/components'; +import { Modal, Button } from '@wordpress/components'; import { Fragment } from '@wordpress/element'; import { withSelect } from '@wordpress/data'; import { addQueryArgs } from '@wordpress/url'; @@ -46,38 +46,36 @@ function PostLockedModal( { lockNonce, lockDetails, user, postId, isLocked } ) { shouldCloseOnClickOutside={ false } shouldCloseOnEsc={ false } isDismissable={ false } - className="post-locked-modal" + className="editor-post-locked-modal" > - { - !! avatar && + { !! avatar && ( { - } - + ) } +
{ modalText }
- { - !! takeover ? -

- - { __( 'View all posts' ) } - -

: - - { __( 'All Posts' ) } + { !! takeover && ( +

+ + { __( 'View all posts' ) } - } +

+ ) } { ! takeover && - - - - { __( 'Take Over' ) } - - +
+ + + +
} - +
); diff --git a/packages/editor/src/components/post-locked-modal/style.scss b/packages/editor/src/components/post-locked-modal/style.scss index 8a41035e21d3f..cbe1390ee7ea6 100644 --- a/packages/editor/src/components/post-locked-modal/style.scss +++ b/packages/editor/src/components/post-locked-modal/style.scss @@ -1,23 +1,28 @@ -.post-locked-modal { - max-height: 152px; +.editor-post-locked-modal { + height: auto; padding-right: 10px; padding-left: 10px; padding-top: 10px; - a.button, - button.components-button { - margin: 5px; - } - img.components-modal__image { - float: left; - margin: 5px; - margin-right: 15px; - } - .components-modal__header { height: 36px; } + .components-modal__content { - overflow: hidden; + height: auto; + } +} + +.editor-post-locked-modal__buttons { + margin-top: 10px; + + .components-button { + margin-right: 5px; } } + +.editor-post-locked-modal__avatar { + float: left; + margin: 5px; + margin-right: 15px; +} From 17803ec7783a84e516c8d8729a280e66508d4921 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 29 Aug 2018 12:35:33 +0100 Subject: [PATCH 68/86] Post Lock: Clarifying the lock state --- docs/data/data-core-editor.md | 27 +++-- edit-post/index.js | 2 +- lib/client-assets.php | 94 +++++++-------- .../src/components/post-locked-modal/index.js | 109 +++++++++--------- .../editor/src/components/provider/index.js | 5 +- packages/editor/src/store/actions.js | 14 +-- packages/editor/src/store/reducer.js | 13 +-- packages/editor/src/store/selectors.js | 23 +++- .../src/utils/heartbeat-post-locking.js | 67 ++++++----- 9 files changed, 186 insertions(+), 168 deletions(-) diff --git a/docs/data/data-core-editor.md b/docs/data/data-core-editor.md index b3bf79639b840..3ec860d4c0093 100644 --- a/docs/data/data-core-editor.md +++ b/docs/data/data-core-editor.md @@ -1042,9 +1042,9 @@ Returns whether the post is locked. Is locked. -### getLockDetails +### isPostLockTakeover -Returns details about the current post lock if available. +Returns whether the post is locked. *Parameters* @@ -1052,11 +1052,11 @@ Returns details about the current post lock if available. *Returns* -Post lock details. +Is locked. ### getPostLockUser -Returns the post lock user. +Returns details about the post lock user. *Parameters* @@ -1066,6 +1066,18 @@ Returns the post lock user. A user object. +### getActivePostLock + +Returns the active post lock. + +*Parameters* + + * state: Global application state. + +*Returns* + +The lock object. + ### canUserUseUnfilteredHTML Returns whether or not the user has the unfiltered_html capability. @@ -1089,7 +1101,6 @@ the specified post object and editor settings. * post: Post object. * autosaveStatus: The Post's autosave status. - * lockedUser: The Post's locked user, or false if not locked. ### resetPost @@ -1367,13 +1378,13 @@ Returns an action object used to remove a notice. * id: The notice id. -### lockPost +### updatePostLock Returns an action object used to lock the editor. *Parameters* - * locked: Whether the editor should be locked. + * lock: Details about the post lock status, user, and nonce. ### fetchReusableBlocks @@ -1467,4 +1478,4 @@ Returns an action object used in signalling that the editor settings have been u *Parameters* - * settings: Updated settings + * settings: Updated settings \ No newline at end of file diff --git a/edit-post/index.js b/edit-post/index.js index 86bdba36bbf54..7f32336823cfc 100644 --- a/edit-post/index.js +++ b/edit-post/index.js @@ -57,7 +57,7 @@ export function initializeEditor( id, postType, postId, settings, overridePost ) registerCoreBlocks(); // Set up heartbeat post locking. - hearthbeatPostLocking( postId, settings ); + hearthbeatPostLocking( settings ); dispatch( 'core/nux' ).triggerGuide( [ 'core/editor.inserter', diff --git a/lib/client-assets.php b/lib/client-assets.php index d376764a3ac30..c9688e537dad1 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1375,42 +1375,9 @@ function gutenberg_editor_scripts_and_styles( $hook ) { $max_upload_size = 0; } - $editor_settings = array( - 'alignWide' => $align_wide || ! empty( $gutenberg_theme_support[0]['wide-images'] ), // Backcompat. Use `align-wide` outside of `gutenberg` array. - 'availableTemplates' => $available_templates, - 'allowedBlockTypes' => $allowed_block_types, - 'disableCustomColors' => get_theme_support( 'disable-custom-colors' ), - 'disablePostFormats' => ! current_theme_supports( 'post-formats' ), - 'titlePlaceholder' => apply_filters( 'enter_title_here', __( 'Add title', 'gutenberg' ), $post ), - 'bodyPlaceholder' => apply_filters( 'write_your_story', __( 'Write your story', 'gutenberg' ), $post ), - 'isRTL' => is_rtl(), - 'autosaveInterval' => 10, - 'maxUploadFileSize' => $max_upload_size, - 'allowedMimeTypes' => get_allowed_mime_types(), - 'ajaxurl' => admin_url( 'admin-ajax.php' ), - ); - - $post_autosave = get_autosave_newer_than_post_save( $post ); - if ( $post_autosave ) { - $editor_settings['autosave'] = array( - 'editLink' => add_query_arg( 'gutenberg', true, get_edit_post_link( $post_autosave->ID ) ), - ); - } - - // Check to see if the post is locked. - $user = null; + // Lock settings $user_id = wp_check_post_lock( $post->ID ); if ( $user_id ) { - $user = get_userdata( $user_id ); - } else { - - // Lock the post. - $active_post_lock = wp_set_post_lock( $post->ID ); - $editor_settings['activePostLock'] = esc_attr( implode( ':', $active_post_lock ) ); - } - - if ( $user ) { - /** * Filters whether to show the post locked dialog. * @@ -1426,23 +1393,60 @@ function gutenberg_editor_scripts_and_styles( $hook ) { $locked = true; } - $avatar = get_avatar( $user->ID, 64 ); - if ( $avatar ) { - if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { - $user->avatar_src = $matches[1]; + $userDetails = null; + if ( $locked ) { + $user = get_userdata( $user_id ); + $userDetails = array( + 'name' => $user->display_name, + ); + $avatar = get_avatar( $user_id, 64 ); + if ( $avatar ) { + if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { + $userDetails[ 'avatar' ] = $matches[1]; + } } } - $editor_settings['lockedUser'] = $locked ? $user : false; - $editor_settings['lockNonce'] = wp_create_nonce( 'lock-post_' . $post->ID ); - + $lock_details = array( + 'isLocked' => $locked, + 'user' => $userDetails, + ); } else { - $locked = false; + // Lock the post + $active_post_lock = wp_set_post_lock( $post->ID ); + $lock_details = array( + 'isLocked' => false, + 'activePostLock' => esc_attr( implode( ':', $active_post_lock ) ) + ); } - $editor_settings['locked'] = $locked; - // Add a nonce for post unlocking on window unload. - $editor_settings['_wpnonce'] = wp_create_nonce( 'update-post_' . $post->ID ); + $editor_settings = array( + 'alignWide' => $align_wide || ! empty( $gutenberg_theme_support[0]['wide-images'] ), // Backcompat. Use `align-wide` outside of `gutenberg` array. + 'availableTemplates' => $available_templates, + 'allowedBlockTypes' => $allowed_block_types, + 'disableCustomColors' => get_theme_support( 'disable-custom-colors' ), + 'disablePostFormats' => ! current_theme_supports( 'post-formats' ), + 'titlePlaceholder' => apply_filters( 'enter_title_here', __( 'Add title', 'gutenberg' ), $post ), + 'bodyPlaceholder' => apply_filters( 'write_your_story', __( 'Write your story', 'gutenberg' ), $post ), + 'isRTL' => is_rtl(), + 'autosaveInterval' => 10, + 'maxUploadFileSize' => $max_upload_size, + 'allowedMimeTypes' => get_allowed_mime_types(), + 'postLock' => $lock_details, + + // Ideally, we'd remove this and rely on a REST API endpoint + 'postLockUtils' => array( + 'nonce' => wp_create_nonce( 'lock-post_' . $post->ID ), + 'ajaxUrl' => admin_url( 'admin-ajax.php' ), + ) + ); + + $post_autosave = get_autosave_newer_than_post_save( $post ); + if ( $post_autosave ) { + $editor_settings['autosave'] = array( + 'editLink' => add_query_arg( 'gutenberg', true, get_edit_post_link( $post_autosave->ID ) ), + ); + } if ( false !== $color_palette ) { $editor_settings['colors'] = $color_palette; diff --git a/packages/editor/src/components/post-locked-modal/index.js b/packages/editor/src/components/post-locked-modal/index.js index 8fb2b639ff92f..4b4e9d77b06da 100644 --- a/packages/editor/src/components/post-locked-modal/index.js +++ b/packages/editor/src/components/post-locked-modal/index.js @@ -3,7 +3,6 @@ */ import { __, sprintf } from '@wordpress/i18n'; import { Modal, Button } from '@wordpress/components'; -import { Fragment } from '@wordpress/element'; import { withSelect } from '@wordpress/data'; import { addQueryArgs } from '@wordpress/url'; @@ -13,80 +12,80 @@ import { addQueryArgs } from '@wordpress/url'; import { getWPAdminURL } from '../../utils/url'; import PostPreviewButton from '../post-preview-button'; -function PostLockedModal( { lockNonce, lockDetails, user, postId, isLocked } ) { +function PostLockedModal( { user, postId, isLocked, isTakeover, nonce } ) { if ( ! isLocked ) { return null; } - let modalText, avatar, takeover; - if ( lockDetails && lockDetails.text ) { - modalText = lockDetails.text; - avatar = lockDetails.avatar_src; - takeover = true; - } else { - const displayName = ( user && user.data ) ? user.data.display_name : __( 'Another user' ); - modalText = sprintf( __( '%s is already editing this post. Do you want to take over?' ), displayName ); - avatar = user.data.avatar_src; - } + const userDisplayName = user.name || __( 'Another user' ); + const userAvatar = user.avatar; const unlockUrl = addQueryArgs( 'post.php', { 'get-post-lock': '1', - _wpnonce: lockNonce, lockKey: true, post: postId, action: 'edit', + _wpnonce: nonce, } ); const allPosts = getWPAdminURL( 'edit.php' ); return ( - - - { !! avatar && ( - { - ) } + + { !! userAvatar && ( + { + ) } + { !! isTakeover && ( +
+

{ sprintf( __( '%s has taken over and is currently editing.' ), userDisplayName ) }

+

+ + { __( 'View all posts' ) } + +

+
+ ) } + { ! isTakeover && (
-
{ modalText }
- { !! takeover && ( -

- - { __( 'View all posts' ) } - -

- ) } - { ! takeover && -
- - - -
- } +

{ sprintf( __( '%s is already editing this post. Do you want to take over?' ), userDisplayName ) }

+
+ + + +
-
-
+ ) } + ); } export default withSelect( ( select ) => { + const { + getEditorSettings, + isPostLocked, + isPostLockTakeover, + getPostLockUser, + getCurrentPost, + } = select( 'core/editor' ); return { - isLocked: select( 'core/editor' ).isPostLocked(), - lockDetails: select( 'core/editor' ).getLockDetails(), - user: select( 'core/editor' ).getPostLockUser(), - postId: select( 'core/editor' ).getCurrentPost().id, - lockNonce: select( 'core/editor' ).getEditorSettings().lockNonce, + isLocked: isPostLocked(), + isTakeover: isPostLockTakeover(), + user: getPostLockUser(), + postId: getCurrentPost().id, + nonce: getEditorSettings().postLockUtils.nonce, }; } )( PostLockedModal ); diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 86f2e8153cf5f..850d085ee36d2 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -26,7 +26,8 @@ class EditorProvider extends Component { // Assume that we don't need to initialize in the case of an error recovery. if ( ! props.recovery ) { this.props.updateEditorSettings( props.settings ); - this.props.setupEditor( props.post, props.settings.autosave, props.settings.lockedUser ); + this.props.updatePostLock( props.settings.postLock ); + this.props.setupEditor( props.post, props.settings.autosave ); } } @@ -100,6 +101,7 @@ export default withDispatch( ( dispatch ) => { undo, redo, createUndoLevel, + updatePostLock, } = dispatch( 'core/editor' ); return { setupEditor, @@ -107,5 +109,6 @@ export default withDispatch( ( dispatch ) => { redo, createUndoLevel, updateEditorSettings, + updatePostLock, }; } )( EditorProvider ); diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index 3092554fbfc39..166cecf72058c 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -18,15 +18,13 @@ import { * * @param {Object} post Post object. * @param {Object} autosaveStatus The Post's autosave status. - * @param {Object} lockedUser The Post's locked user, or false if not locked. * * @return {Object} Action object. */ -export function setupEditor( post, autosaveStatus, lockedUser ) { +export function setupEditor( post, autosaveStatus ) { return { type: 'SETUP_EDITOR', autosave: autosaveStatus, - locked: lockedUser, post, }; } @@ -595,16 +593,14 @@ export function removeNotice( id ) { /** * Returns an action object used to lock the editor. * - * @param {boolean} locked Whether the editor should be locked. - * @param {Object} lockDetails Details about the lock user and their avatar. + * @param {Object} lock Details about the post lock status, user, and nonce. * * @return {Object} Action object. */ -export function lockPost( locked, lockDetails ) { +export function updatePostLock( lock ) { return { - type: 'LOCK_POST', - locked, - lockDetails, + type: 'UPDATE_POST_LOCK', + lock, }; } diff --git a/packages/editor/src/store/reducer.js b/packages/editor/src/store/reducer.js index 9d6e36d954d50..f862e85ddb419 100644 --- a/packages/editor/src/store/reducer.js +++ b/packages/editor/src/store/reducer.js @@ -876,15 +876,10 @@ export function notices( state = [], action ) { return state; } -export function locked( state = false, action ) { +export function postLock( state = { isLocked: false }, action ) { switch ( action.type ) { - case 'LOCK_POST': - case 'SETUP_EDITOR': - return { - ...state, - locked: action.locked, - lockDetails: action.lockDetails, - }; + case 'UPDATE_POST_LOCK': + return action.lock; } return state; @@ -1103,7 +1098,7 @@ export default optimist( combineReducers( { isInsertionPointVisible, preferences, saving, - locked, + postLock, notices, reusableBlocks, template, diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index ef3e622cffd81..7c909b2d2d3c0 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -1901,18 +1901,18 @@ export function getTokenSettings( state, name ) { * @return {boolean} Is locked. */ export function isPostLocked( state ) { - return !! state.locked.locked; + return state.postLock.isLocked; } /** - * Returns details about the current post lock if available. + * Returns whether the post is locked. * * @param {Object} state Global application state. * - * @return {Object} The lock details object. + * @return {boolean} Is locked. */ -export function getLockDetails( state ) { - return state.locked.lockDetails; +export function isPostLockTakeover( state ) { + return state.postLock.isTakeover; } /** @@ -1923,7 +1923,18 @@ export function getLockDetails( state ) { * @return {Object} A user object. */ export function getPostLockUser( state ) { - return state.locked.locked; + return state.postLock.user; +} + +/** + * Returns the active post lock. + * + * @param {Object} state Global application state. + * + * @return {Object} The lock object. + */ +export function getActivePostLock( state ) { + return state.postLock.activePostLock; } /** diff --git a/packages/editor/src/utils/heartbeat-post-locking.js b/packages/editor/src/utils/heartbeat-post-locking.js index 7eb43e47688e1..5f53d9d8577e7 100644 --- a/packages/editor/src/utils/heartbeat-post-locking.js +++ b/packages/editor/src/utils/heartbeat-post-locking.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import jQuery from 'jquery'; + /** * WordPress dependencies */ @@ -8,81 +13,75 @@ import { dispatch, select } from '@wordpress/data'; * * Used to lock editing of an object by only one user at a time. * - * @param {number} postId The post Id. * @param {Object} settings The editor settings. */ -const hearthbeatPostLocking = ( postId, settings ) => { - // Track the current post lock. - let activePostLock = settings.activePostLock; - +const hearthbeatPostLocking = ( settings ) => { /** * Keep the lock refreshed. * * When the user does not send a heartbeat in a heartbeat-tick * the user is no longer editing and another user can start editing. */ - jQuery( document ).on( 'heartbeat-send.refresh-lock', function( e, data ) { - const lock = activePostLock, - send = {}; - - if ( ! postId ) { - return; - } - + jQuery( document ).on( 'heartbeat-send.refresh-lock', ( e, data ) => { // Check if the post is already locked by another user. - const locked = select( 'core/editor' ).isPostLocked(); - if ( locked ) { + const isLocked = select( 'core/editor' ).isPostLocked(); + if ( isLocked ) { return; } - send.post_id = postId; - - if ( lock ) { - send.lock = lock; - } - - data[ 'wp-refresh-post-lock' ] = send; + data[ 'wp-refresh-post-lock' ] = { + lock: select( 'core/editor' ).getActivePostLock(), + post_id: select( 'core/editor' ).getCurrentPostId(), + }; } ) // Refresh post locks: update the lock string or show the dialog if somebody has taken over editing. - .on( 'heartbeat-tick.refresh-lock', function( e, data ) { + .on( 'heartbeat-tick.refresh-lock', ( e, data ) => { if ( data[ 'wp-refresh-post-lock' ] ) { const received = data[ 'wp-refresh-post-lock' ]; if ( received.lock_error ) { // Auto save and display the takeover modal. dispatch( 'core/editor' ).autosave(); - dispatch( 'core/editor' ).lockPost( true, received.lock_error ); + dispatch( 'core/editor' ).updatePostLock( { + isLocked: true, + isTakeover: true, + user: { + avatar: received.lock_error.avatar_src, + }, + } ); } else if ( received.new_lock ) { - activePostLock = received.new_lock; - dispatch( 'core/editor' ).lockPost( false ); + dispatch( 'core/editor' ).updatePostLock( { + isLocked: false, + activePostLock: received.new_lock, + } ); } } } ); // Unlock the post before the window is exited. - jQuery( window ).on( 'beforeunload.edit-post', function( event ) { - const postLock = activePostLock; - + jQuery( window ).on( 'beforeunload.edit-post', ( event ) => { // Make sure we process only the main document unload. if ( event.target && event.target.nodeName !== '#document' ) { return; } - if ( ! postId || ! postLock ) { + const isLocked = select( 'core/editor' ).isPostLocked(); + const postLock = select( 'core/editor' ).getActivePostLock(); + if ( isLocked || ! postLock ) { return; } const data = { action: 'wp-remove-post-lock', - _wpnonce: settings._wpnonce, - post_ID: postId, + _wpnonce: settings.postLockUtils.nonce, + post_ID: select( 'core/editor' ).getCurrentPostId(), active_post_lock: postLock, }; jQuery.post( { async: false, - data: data, - url: settings.ajaxurl, + url: settings.postLockUtils.ajaxUrl, + data, } ); } ); }; From 6f30da2351ed2a6f255e98f058c9892e931ebd21 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 29 Aug 2018 12:52:55 +0100 Subject: [PATCH 69/86] Move post locking setup to the post locked modal component --- edit-post/index.js | 4 - .../src/components/post-locked-modal/index.js | 270 +++++++++++++----- .../src/utils/heartbeat-post-locking.js | 90 ------ packages/editor/src/utils/index.js | 3 - 4 files changed, 197 insertions(+), 170 deletions(-) delete mode 100644 packages/editor/src/utils/heartbeat-post-locking.js diff --git a/edit-post/index.js b/edit-post/index.js index 7f32336823cfc..a5120e4d05b96 100644 --- a/edit-post/index.js +++ b/edit-post/index.js @@ -4,7 +4,6 @@ import { registerCoreBlocks } from '@wordpress/block-library'; import { render, unmountComponentAtNode } from '@wordpress/element'; import { dispatch } from '@wordpress/data'; -import { hearthbeatPostLocking } from '@wordpress/editor'; /** * Internal dependencies @@ -56,9 +55,6 @@ export function initializeEditor( id, postType, postId, settings, overridePost ) registerCoreBlocks(); - // Set up heartbeat post locking. - hearthbeatPostLocking( settings ); - dispatch( 'core/nux' ).triggerGuide( [ 'core/editor.inserter', 'core/editor.settings', diff --git a/packages/editor/src/components/post-locked-modal/index.js b/packages/editor/src/components/post-locked-modal/index.js index 4b4e9d77b06da..d80a9fd40dae7 100644 --- a/packages/editor/src/components/post-locked-modal/index.js +++ b/packages/editor/src/components/post-locked-modal/index.js @@ -1,10 +1,17 @@ +/** + * External dependencies + */ +import jQuery from 'jquery'; + /** * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; import { Modal, Button } from '@wordpress/components'; -import { withSelect } from '@wordpress/data'; +import { withSelect, withDispatch } from '@wordpress/data'; import { addQueryArgs } from '@wordpress/url'; +import { Component } from '@wordpress/element'; +import { compose } from '@wordpress/compose'; /** * Internal dependencies @@ -12,80 +19,197 @@ import { addQueryArgs } from '@wordpress/url'; import { getWPAdminURL } from '../../utils/url'; import PostPreviewButton from '../post-preview-button'; -function PostLockedModal( { user, postId, isLocked, isTakeover, nonce } ) { - if ( ! isLocked ) { - return null; +class PostLockedModal extends Component { + constructor() { + super( ...arguments ); + + this.sendPostLock = this.sendPostLock.bind( this ); + this.receivePostLock = this.receivePostLock.bind( this ); + this.releasePostLock = this.releasePostLock.bind( this ); + } + + componentDidMount() { + jQuery( document ) + .on( 'heartbeat-send.refresh-lock', this.sendPostLock ) + .on( 'heartbeat-tick.refresh-lock', this.receivePostLock ) + .on( 'beforeunload.edit-post', this.releasePostLock ); + } + + componentWillUnmount() { + jQuery( document ) + .off( 'heartbeat-send.refresh-lock', this.sendPostLock ) + .off( 'heartbeat-tick.refresh-lock', this.receivePostLock ) + .off( 'beforeunload.edit-post', this.releasePostLock ); + } + + /** + * Keep the lock refreshed. + * + * When the user does not send a heartbeat in a heartbeat-tick + * the user is no longer editing and another user can start editing. + * + * @param {Object} event Event. + * @param {Object} data Data to send in the heartbeat request. + */ + sendPostLock( event, data ) { + const { isLocked, activePostLock, postId } = this.props; + if ( isLocked ) { + return; + } + + data[ 'wp-refresh-post-lock' ] = { + lock: activePostLock, + post_id: postId, + }; + } + + /** + * Refresh post locks: update the lock string or show the dialog if somebody has taken over editing. + * + * @param {Object} event Event. + * @param {Object} data Data received in the heartbeat request + */ + receivePostLock( event, data ) { + if ( data[ 'wp-refresh-post-lock' ] ) { + const { autosave, updatePostLock } = this.props; + const received = data[ 'wp-refresh-post-lock' ]; + if ( received.lock_error ) { + // Auto save and display the takeover modal. + autosave(); + updatePostLock( { + isLocked: true, + isTakeover: true, + user: { + avatar: received.lock_error.avatar_src, + }, + } ); + } else if ( received.new_lock ) { + updatePostLock( { + isLocked: false, + activePostLock: received.new_lock, + } ); + } + } + } + + /** + * Unlock the post before the window is exited. + * + * @param {Object} event Event. + */ + releasePostLock( event ) { + // Make sure we process only the main document unload. + if ( event.target && event.target.nodeName !== '#document' ) { + return; + } + + const { isLocked, activePostLock, postLockUtils, postId } = this.props; + if ( isLocked || ! activePostLock ) { + return; + } + + const data = { + action: 'wp-remove-post-lock', + _wpnonce: postLockUtils.nonce, + post_ID: postId, + active_post_lock: activePostLock, + }; + + jQuery.post( { + async: false, + url: postLockUtils.ajaxUrl, + data, + } ); } - const userDisplayName = user.name || __( 'Another user' ); - const userAvatar = user.avatar; - - const unlockUrl = addQueryArgs( 'post.php', { - 'get-post-lock': '1', - lockKey: true, - post: postId, - action: 'edit', - _wpnonce: nonce, - } ); - const allPosts = getWPAdminURL( 'edit.php' ); - - return ( - - { !! userAvatar && ( - { - ) } - { !! isTakeover && ( -
-

{ sprintf( __( '%s has taken over and is currently editing.' ), userDisplayName ) }

-

- - { __( 'View all posts' ) } - -

-
- ) } - { ! isTakeover && ( -
-

{ sprintf( __( '%s is already editing this post. Do you want to take over?' ), userDisplayName ) }

-
- - - + render() { + const { user, postId, isLocked, isTakeover, postLockUtils } = this.props; + if ( ! isLocked ) { + return null; + } + + const userDisplayName = user.name || __( 'Another user' ); + const userAvatar = user.avatar; + + const unlockUrl = addQueryArgs( 'post.php', { + 'get-post-lock': '1', + lockKey: true, + post: postId, + action: 'edit', + _wpnonce: postLockUtils.nonce, + } ); + const allPosts = getWPAdminURL( 'edit.php' ); + + return ( + + { !! userAvatar && ( + { + ) } + { !! isTakeover && ( +
+

{ sprintf( __( '%s has taken over and is currently editing.' ), userDisplayName ) }

+

+ + { __( 'View all posts' ) } + +

-
- ) } - - ); + ) } + { ! isTakeover && ( +
+

{ sprintf( __( '%s is already editing this post. Do you want to take over?' ), userDisplayName ) }

+
+ + + +
+
+ ) } + + ); + } } -export default withSelect( ( select ) => { - const { - getEditorSettings, - isPostLocked, - isPostLockTakeover, - getPostLockUser, - getCurrentPost, - } = select( 'core/editor' ); - return { - isLocked: isPostLocked(), - isTakeover: isPostLockTakeover(), - user: getPostLockUser(), - postId: getCurrentPost().id, - nonce: getEditorSettings().postLockUtils.nonce, - }; -} )( PostLockedModal ); +export default compose( + withSelect( ( select ) => { + const { + getEditorSettings, + isPostLocked, + isPostLockTakeover, + getPostLockUser, + getCurrentPostId, + getActivePostLock, + } = select( 'core/editor' ); + return { + isLocked: isPostLocked(), + isTakeover: isPostLockTakeover(), + user: getPostLockUser(), + postId: getCurrentPostId(), + postLockUtils: getEditorSettings().postLockUtils, + activePostLock: getActivePostLock(), + + }; + } ), + withDispatch( ( dispatch ) => { + const { autosave, updatePostLock } = dispatch( 'core/editor' ); + return { + autosave, + updatePostLock, + }; + } ) +)( PostLockedModal ); diff --git a/packages/editor/src/utils/heartbeat-post-locking.js b/packages/editor/src/utils/heartbeat-post-locking.js deleted file mode 100644 index 5f53d9d8577e7..0000000000000 --- a/packages/editor/src/utils/heartbeat-post-locking.js +++ /dev/null @@ -1,90 +0,0 @@ -/** - * External dependencies - */ -import jQuery from 'jquery'; - -/** - * WordPress dependencies - */ -import { dispatch, select } from '@wordpress/data'; - -/** - * Configure Heartbeat post locks. - * - * Used to lock editing of an object by only one user at a time. - * - * @param {Object} settings The editor settings. - */ -const hearthbeatPostLocking = ( settings ) => { - /** - * Keep the lock refreshed. - * - * When the user does not send a heartbeat in a heartbeat-tick - * the user is no longer editing and another user can start editing. - */ - jQuery( document ).on( 'heartbeat-send.refresh-lock', ( e, data ) => { - // Check if the post is already locked by another user. - const isLocked = select( 'core/editor' ).isPostLocked(); - if ( isLocked ) { - return; - } - - data[ 'wp-refresh-post-lock' ] = { - lock: select( 'core/editor' ).getActivePostLock(), - post_id: select( 'core/editor' ).getCurrentPostId(), - }; - } ) - - // Refresh post locks: update the lock string or show the dialog if somebody has taken over editing. - .on( 'heartbeat-tick.refresh-lock', ( e, data ) => { - if ( data[ 'wp-refresh-post-lock' ] ) { - const received = data[ 'wp-refresh-post-lock' ]; - if ( received.lock_error ) { - // Auto save and display the takeover modal. - dispatch( 'core/editor' ).autosave(); - dispatch( 'core/editor' ).updatePostLock( { - isLocked: true, - isTakeover: true, - user: { - avatar: received.lock_error.avatar_src, - }, - } ); - } else if ( received.new_lock ) { - dispatch( 'core/editor' ).updatePostLock( { - isLocked: false, - activePostLock: received.new_lock, - } ); - } - } - } ); - - // Unlock the post before the window is exited. - jQuery( window ).on( 'beforeunload.edit-post', ( event ) => { - // Make sure we process only the main document unload. - if ( event.target && event.target.nodeName !== '#document' ) { - return; - } - - const isLocked = select( 'core/editor' ).isPostLocked(); - const postLock = select( 'core/editor' ).getActivePostLock(); - if ( isLocked || ! postLock ) { - return; - } - - const data = { - action: 'wp-remove-post-lock', - _wpnonce: settings.postLockUtils.nonce, - post_ID: select( 'core/editor' ).getCurrentPostId(), - active_post_lock: postLock, - }; - - jQuery.post( { - async: false, - url: settings.postLockUtils.ajaxUrl, - data, - } ); - } ); -}; - -export default hearthbeatPostLocking; - diff --git a/packages/editor/src/utils/index.js b/packages/editor/src/utils/index.js index 966568635c381..0f869651e96ae 100644 --- a/packages/editor/src/utils/index.js +++ b/packages/editor/src/utils/index.js @@ -4,8 +4,5 @@ import mediaUpload from './media-upload'; export { mediaUpload }; -import hearthbeatPostLocking from './heartbeat-post-locking'; -export { hearthbeatPostLocking }; - import { getWPAdminURL } from './url'; export { getWPAdminURL }; From 52cb1e69e3846d798603055b342d9aab6b42d8b8 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 29 Aug 2018 12:55:18 +0100 Subject: [PATCH 70/86] Remove unnecessary exposed function --- packages/editor/src/utils/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/editor/src/utils/index.js b/packages/editor/src/utils/index.js index 0f869651e96ae..3a49f66b86c90 100644 --- a/packages/editor/src/utils/index.js +++ b/packages/editor/src/utils/index.js @@ -2,7 +2,5 @@ * Internal dependencies */ import mediaUpload from './media-upload'; -export { mediaUpload }; -import { getWPAdminURL } from './url'; -export { getWPAdminURL }; +export { mediaUpload }; From e32ac81b8f56c6b3ca3c6752a1cf1bd719952019 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 5 Sep 2018 08:03:04 -0600 Subject: [PATCH 71/86] cleanup after merge --- lib/client-assets.php | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index 865db99afd0bd..4fbce7560240f 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1394,47 +1394,26 @@ function gutenberg_editor_scripts_and_styles( $hook ) { $styles = array( array( 'css' => file_get_contents( - * - * Returning a falsey value to the filter will short-circuit displaying the dialog. gutenberg_dir_path() . 'build/editor/editor-styles.css' - * @since 3.6.0 - * - * @param bool $display Whether to display the dialog. Default true. - * @param WP_Post $post Post object. - * @param WP_User|bool $user WP_User object on success, false otherwise. - */ - if ( apply_filters( 'show_post_locked_dialog', true, $post, $user ) ) { - $locked = true; - } - - $userDetails = null; ), ), - $userDetails = array( - 'name' => $user->display_name, - ); + ); if ( $editor_styles && current_theme_supports( 'editor-styles' ) ) { foreach ( $editor_styles as $style ) { if ( filter_var( $style, FILTER_VALIDATE_URL ) ) { - $userDetails[ 'avatar' ] = $matches[1]; - } - } - } - $styles[] = array( - 'isLocked' => $locked, 'css' => file_get_contents( $style ), - ); - } else { + ); + } else { $file = get_theme_file_path( $style ); - $active_post_lock = wp_set_post_lock( $post->ID ); $styles[] = array( 'css' => file_get_contents( get_theme_file_path( $style ) ), 'baseURL' => get_theme_file_uri( $style ), - ); + ); } } } + // Lock settings $user_id = wp_check_post_lock( $post->ID ); if ( $user_id ) { From 17a80e16e6ac6cab4103b3c09528ece7ea954b47 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 5 Sep 2018 22:39:01 -0600 Subject: [PATCH 72/86] fixes for phpcs --- lib/client-assets.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index 9e9923390e5b5..33c9b68f2d258 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1432,30 +1432,30 @@ function gutenberg_editor_scripts_and_styles( $hook ) { $locked = true; } - $userDetails = null; + $user_details = null; if ( $locked ) { $user = get_userdata( $user_id ); - $userDetails = array( + $user_details = array( 'name' => $user->display_name, ); $avatar = get_avatar( $user_id, 64 ); if ( $avatar ) { if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { - $userDetails[ 'avatar' ] = $matches[1]; + $user_details['avatar'] = $matches[1]; } } } $lock_details = array( 'isLocked' => $locked, - 'user' => $userDetails, + 'user' => $user_details, ); } else { // Lock the post $active_post_lock = wp_set_post_lock( $post->ID ); $lock_details = array( 'isLocked' => false, - 'activePostLock' => esc_attr( implode( ':', $active_post_lock ) ) + 'activePostLock' => esc_attr( implode( ':', $active_post_lock ) ), ); } @@ -1477,7 +1477,7 @@ function gutenberg_editor_scripts_and_styles( $hook ) { 'postLockUtils' => array( 'nonce' => wp_create_nonce( 'lock-post_' . $post->ID ), 'ajaxUrl' => admin_url( 'admin-ajax.php' ), - ) + ), ); $post_autosave = get_autosave_newer_than_post_save( $post ); From 9315785d63e6bb547abc48572d077a002793de73 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 5 Sep 2018 22:40:35 -0600 Subject: [PATCH 73/86] docs cleanup --- lib/client-assets.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index 33c9b68f2d258..69a26dbccd0e0 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1414,7 +1414,7 @@ function gutenberg_editor_scripts_and_styles( $hook ) { } } - // Lock settings + // Lock settings. $user_id = wp_check_post_lock( $post->ID ); if ( $user_id ) { /** @@ -1451,7 +1451,8 @@ function gutenberg_editor_scripts_and_styles( $hook ) { 'user' => $user_details, ); } else { - // Lock the post + + // Lock the post. $active_post_lock = wp_set_post_lock( $post->ID ); $lock_details = array( 'isLocked' => false, @@ -1473,7 +1474,7 @@ function gutenberg_editor_scripts_and_styles( $hook ) { 'allowedMimeTypes' => get_allowed_mime_types(), 'postLock' => $lock_details, - // Ideally, we'd remove this and rely on a REST API endpoint + // Ideally, we'd remove this and rely on a REST API endpoint. 'postLockUtils' => array( 'nonce' => wp_create_nonce( 'lock-post_' . $post->ID ), 'ajaxUrl' => admin_url( 'admin-ajax.php' ), From 6744619201db3363ee80b1115692f4f9eec4a867 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 5 Sep 2018 23:16:46 -0600 Subject: [PATCH 74/86] cleanup after merge --- lib/client-assets.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index 69a26dbccd0e0..2a28c1b979c43 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1426,9 +1426,9 @@ function gutenberg_editor_scripts_and_styles( $hook ) { * * @param bool $display Whether to display the dialog. Default true. * @param WP_Post $post Post object. - * @param WP_User|bool $user WP_User object on success, false otherwise. + * @param WP_User|bool $user The user id currently editing the post. */ - if ( apply_filters( 'show_post_locked_dialog', true, $post, $user ) ) { + if ( apply_filters( 'show_post_locked_dialog', true, $post, $user_id ) ) { $locked = true; } From 24d9aefe34cc6a476c2f9ad4881c9956abb6b06f Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 5 Sep 2018 23:18:51 -0600 Subject: [PATCH 75/86] Adjust the modal display with latest language, formatting and post type --- .../src/components/post-locked-modal/index.js | 17 +++++++++++------ .../src/components/post-locked-modal/style.scss | 1 + 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/editor/src/components/post-locked-modal/index.js b/packages/editor/src/components/post-locked-modal/index.js index d80a9fd40dae7..d9526c2c33acd 100644 --- a/packages/editor/src/components/post-locked-modal/index.js +++ b/packages/editor/src/components/post-locked-modal/index.js @@ -123,7 +123,7 @@ class PostLockedModal extends Component { } render() { - const { user, postId, isLocked, isTakeover, postLockUtils } = this.props; + const { user, postId, isLocked, isTakeover, postLockUtils, postType } = this.props; if ( ! isLocked ) { return null; } @@ -139,10 +139,9 @@ class PostLockedModal extends Component { _wpnonce: postLockUtils.nonce, } ); const allPosts = getWPAdminURL( 'edit.php' ); - return ( -

{ sprintf( __( '%s has taken over and is currently editing.' ), userDisplayName ) }

+
+ { userDisplayName } { sprintf( __( 'now has editing control of this %s. Don\'t worry, your changes up to this moment have been saved' ), postType ) } +

{ __( 'View all posts' ) } @@ -168,7 +169,10 @@ class PostLockedModal extends Component { ) } { ! isTakeover && (

-

{ sprintf( __( '%s is already editing this post. Do you want to take over?' ), userDisplayName ) }

+
+ { userDisplayName } { sprintf( __( 'is currently working on this %s, which means you cannot make changes, unless you take over.' ), postType ) } +
+
- + : null }
) ); @@ -77,15 +77,15 @@ If this property is added, it will be added to the modal content `div` as `aria- If this property is true, it will focus the first tabbable element rendered in the modal. -- Type: `bool` +- Type: `boolean` - Required: No - Default: true ### shouldCloseOnEsc -If this property is added, it will determine whether the modal requests to close when the escape key is pressed. +If this property is added, it will determine whether the modal requests to close when the escape key is pressed. -- Type: `bool` +- Type: `boolean` - Required: No - Default: true @@ -93,7 +93,7 @@ If this property is added, it will determine whether the modal requests to close If this property is added, it will determine whether the modal requests to close when a mouse click occurs outside of the modal content. -- Type: `bool` +- Type: `boolean` - Required: No - Default: true @@ -101,7 +101,7 @@ If this property is added, it will determine whether the modal requests to close If this property is set to false, the modal will not display a close icon and cannot be dismissed. -- Type: `bool` +- Type: `boolean` - Required: No - Default: true diff --git a/packages/editor/src/components/post-locked-modal/index.js b/packages/editor/src/components/post-locked-modal/index.js index df421ea1dacf2..03e2bc2125e98 100644 --- a/packages/editor/src/components/post-locked-modal/index.js +++ b/packages/editor/src/components/post-locked-modal/index.js @@ -96,8 +96,6 @@ class PostLockedModal extends Component { /** * Unlock the post before the window is exited. - * - * @param {Object} event Event. */ releasePostLock() { const { isLocked, activePostLock, postLockUtils, postId } = this.props; @@ -125,6 +123,7 @@ class PostLockedModal extends Component { return null; } + /* translators: Fallback user name for the post lock message. */ const userDisplayName = user.name || __( 'Another user' ); const userAvatar = user.avatar; @@ -222,9 +221,7 @@ export default compose( updatePostLock, }; } ), - withGlobalEvents( { beforeunload: 'releasePostLock', } ) - )( PostLockedModal ); diff --git a/packages/editor/src/store/reducer.js b/packages/editor/src/store/reducer.js index 378c088dcf300..1bcfae88dab7b 100644 --- a/packages/editor/src/store/reducer.js +++ b/packages/editor/src/store/reducer.js @@ -885,6 +885,25 @@ export function notices( state = [], action ) { return state; } +/** + * Post Lock State. + * + * @typedef {Object} PostLockState + * + * @property {boolean} isLocked Whether the post is locked. + * @property {?boolean} isTakeover Whether the post editing has been taken over. + * @property {?boolean} activePostLock Active post lock value. + * @property {?Object} user User that took over the post. + */ + +/** + * Reducer returning the post lock status. + * + * @param {PostLockState} state Current state. + * @param {Object} action Dispatched action. + * + * @return {PostLockState} Updated state. + */ export function postLock( state = { isLocked: false }, action ) { switch ( action.type ) { case 'UPDATE_POST_LOCK': From 719175b6d88e26951dbad80beaa660d0fe4fe0de Mon Sep 17 00:00:00 2001 From: Miguel Fonseca Date: Thu, 4 Oct 2018 12:29:13 -0400 Subject: [PATCH 85/86] i18n: Drop untranslatable `postType` interpolation. --- .../src/components/post-locked-modal/index.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/editor/src/components/post-locked-modal/index.js b/packages/editor/src/components/post-locked-modal/index.js index 03e2bc2125e98..88c7519301775 100644 --- a/packages/editor/src/components/post-locked-modal/index.js +++ b/packages/editor/src/components/post-locked-modal/index.js @@ -118,7 +118,7 @@ class PostLockedModal extends Component { } render() { - const { user, postId, isLocked, isTakeover, postLockUtils, postType } = this.props; + const { user, postId, isLocked, isTakeover, postLockUtils } = this.props; if ( ! isLocked ) { return null; } @@ -155,9 +155,9 @@ class PostLockedModal extends Component {
{ sprintf( - __( '%s now has editing control of this %s. Don\'t worry, your changes up to this moment have been saved' ), - userDisplayName, - postType + /* translators: 'post' is generic and may be of any type (post, page, etc.). */ + __( '%s now has editing control of this post. Don\'t worry, your changes up to this moment have been saved' ), + userDisplayName ) }

@@ -171,9 +171,9 @@ class PostLockedModal extends Component {

{ sprintf( - __( '%s is currently working on this %s, which means you cannot make changes, unless you take over.' ), - userDisplayName, - postType + /* translators: 'post' is generic and may be of any type (post, page, etc.). */ + __( '%s is currently working on this post, which means you cannot make changes, unless you take over.' ), + userDisplayName ) }
@@ -202,7 +202,6 @@ export default compose( getPostLockUser, getCurrentPostId, getActivePostLock, - getEditedPostAttribute, } = select( 'core/editor' ); return { isLocked: isPostLocked(), @@ -211,7 +210,6 @@ export default compose( postId: getCurrentPostId(), postLockUtils: getEditorSettings().postLockUtils, activePostLock: getActivePostLock(), - postType: getEditedPostAttribute( 'type' ), }; } ), withDispatch( ( dispatch ) => { From f89696ca3bc8e7e5e11f4e68123bd73f6c94ed95 Mon Sep 17 00:00:00 2001 From: Miguel Fonseca Date: Thu, 4 Oct 2018 12:35:40 -0400 Subject: [PATCH 86/86] i18n: Separate strings for more versatile translation --- .../src/components/post-locked-modal/index.js | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/editor/src/components/post-locked-modal/index.js b/packages/editor/src/components/post-locked-modal/index.js index 88c7519301775..112dca7689e55 100644 --- a/packages/editor/src/components/post-locked-modal/index.js +++ b/packages/editor/src/components/post-locked-modal/index.js @@ -123,8 +123,7 @@ class PostLockedModal extends Component { return null; } - /* translators: Fallback user name for the post lock message. */ - const userDisplayName = user.name || __( 'Another user' ); + const userDisplayName = user.name; const userAvatar = user.avatar; const unlockUrl = addQueryArgs( 'post.php', { @@ -154,11 +153,15 @@ class PostLockedModal extends Component { { !! isTakeover && (
- { sprintf( + { userDisplayName ? + sprintf( + /* translators: 'post' is generic and may be of any type (post, page, etc.). */ + __( '%s now has editing control of this post. Don\'t worry, your changes up to this moment have been saved' ), + userDisplayName + ) : /* translators: 'post' is generic and may be of any type (post, page, etc.). */ - __( '%s now has editing control of this post. Don\'t worry, your changes up to this moment have been saved' ), - userDisplayName - ) } + __( 'Another user now has editing control of this post. Don\'t worry, your changes up to this moment have been saved' ) + }

@@ -170,11 +173,15 @@ class PostLockedModal extends Component { { ! isTakeover && (