Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ const initializeMetaBoxes = jest.fn( () => ( {
type: 'META_BOXES_INITIALIZED',
} ) );

const updateEditorSettings = jest.fn( () => ( {
type: 'UPDATE_EDITOR_SETTINGS',
} ) );

function createMockStores( {
isEditorReady = true,
isCollaborationEnabled = true,
Expand All @@ -43,6 +47,10 @@ function createMockStores( {
return {
'core/editor': {
...storeConfig,
actions: {
...storeConfig.actions,
updateEditorSettings,
},
selectors: {
__unstableIsEditorReady: jest.fn( () => isEditorReady ),
isCollaborationEnabledForCurrentPost: jest.fn(
Expand Down Expand Up @@ -91,6 +99,7 @@ describe( 'useMetaBoxInitialization', () => {
afterEach( () => {
setCollaborationSupported.mockClear();
initializeMetaBoxes.mockClear();
updateEditorSettings.mockClear();
} );

it( 'disables collaboration when metaboxes are present', () => {
Expand Down Expand Up @@ -188,4 +197,26 @@ describe( 'useMetaBoxInitialization', () => {

expect( setCollaborationSupported ).not.toHaveBeenCalled();
} );

it( 'disables visual revisions when metaboxes are present', () => {
const mockStores = createMockStores( {
metaBoxes: [ { id: 'my-metabox', title: 'My Meta Box' } ],
} );
const registry = createRegistry( mockStores );

renderHook( registry );

expect( updateEditorSettings ).toHaveBeenCalledWith( {
disableVisualRevisions: true,
} );
} );

it( 'does not disable visual revisions when there are no metaboxes', () => {
const mockStores = createMockStores( { metaBoxes: [] } );
const registry = createRegistry( mockStores );

renderHook( registry );

expect( updateEditorSettings ).not.toHaveBeenCalled();
} );
} );
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const useMetaBoxInitialization = ( enabled ) => {
isEnabledAndEditorReady,
isCollaborationEnabled,
hasIncompatibleMetaBoxes,
hasActiveMetaBoxes,
} = useSelect(
( select ) => ( {
isEnabledAndEditorReady:
Expand All @@ -33,10 +34,13 @@ export const useMetaBoxInitialization = ( enabled ) => {
.getAllMetaBoxes()
.some( ( metaBox ) => ! metaBox.__rtc_compatible )
: false,
hasActiveMetaBoxes:
enabled && select( editPostStore ).hasMetaBoxes(),
} ),
[ enabled ]
);
const { setCollaborationSupported } = unlock( useDispatch( coreStore ) );
const { updateEditorSettings } = useDispatch( editorStore );
const { initializeMetaBoxes } = useDispatch( editPostStore );

// The effect has to rerun when the editor is ready because initializeMetaBoxes
Expand All @@ -49,12 +53,23 @@ export const useMetaBoxInitialization = ( enabled ) => {
if ( isCollaborationEnabled && hasIncompatibleMetaBoxes ) {
setCollaborationSupported( false );
}

// Classic meta box values are saved through a separate
// admin-ajax submission that the in-editor revisions restore
// does not drive, so visual revisions would silently leave
// them untouched. Fall back to the classic revision.php
// admin screen instead.
if ( hasActiveMetaBoxes ) {
updateEditorSettings( { disableVisualRevisions: true } );
}
}
}, [
isEnabledAndEditorReady,
initializeMetaBoxes,
isCollaborationEnabled,
setCollaborationSupported,
hasIncompatibleMetaBoxes,
hasActiveMetaBoxes,
updateEditorSettings,
] );
};
36 changes: 30 additions & 6 deletions packages/editor/src/components/post-last-revision/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { sprintf, __ } from '@wordpress/i18n';
import { Button } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { backup } from '@wordpress/icons';
import { addQueryArgs } from '@wordpress/url';

/**
* Internal dependencies
Expand All @@ -16,11 +17,16 @@ import { unlock } from '../../lock-unlock';

function usePostLastRevisionInfo() {
return useSelect( ( select ) => {
const { getCurrentPostLastRevisionId, getCurrentPostRevisionsCount } =
select( editorStore );
const {
getCurrentPostLastRevisionId,
getCurrentPostRevisionsCount,
getEditorSettings,
} = select( editorStore );
return {
lastRevisionId: getCurrentPostLastRevisionId(),
revisionsCount: getCurrentPostRevisionsCount(),
disableVisualRevisions:
!! getEditorSettings().disableVisualRevisions,
};
}, [] );
}
Expand All @@ -31,14 +37,23 @@ function usePostLastRevisionInfo() {
* @return {React.ReactNode} The rendered component.
*/
function PostLastRevision() {
const { lastRevisionId, revisionsCount } = usePostLastRevisionInfo();
const { lastRevisionId, revisionsCount, disableVisualRevisions } =
usePostLastRevisionInfo();
const { setCurrentRevisionId } = unlock( useDispatch( editorStore ) );

const buttonProps = disableVisualRevisions
? {
href: addQueryArgs( 'revision.php', {
revision: lastRevisionId,
} ),
}
: { onClick: () => setCurrentRevisionId( lastRevisionId ) };

return (
<PostLastRevisionCheck>
<Button
__next40pxDefaultSize
onClick={ () => setCurrentRevisionId( lastRevisionId ) }
{ ...buttonProps }
className="editor-post-last-revision__title"
icon={ backup }
iconPosition="right"
Expand All @@ -53,14 +68,23 @@ function PostLastRevision() {
}

export function PrivatePostLastRevision() {
const { lastRevisionId, revisionsCount } = usePostLastRevisionInfo();
const { lastRevisionId, revisionsCount, disableVisualRevisions } =
usePostLastRevisionInfo();
const { setCurrentRevisionId } = unlock( useDispatch( editorStore ) );

const buttonProps = disableVisualRevisions
? {
href: addQueryArgs( 'revision.php', {
revision: lastRevisionId,
} ),
}
: { onClick: () => setCurrentRevisionId( lastRevisionId ) };

return (
<PostLastRevisionCheck>
<PostPanelRow label={ __( 'Revisions' ) }>
<Button
onClick={ () => setCurrentRevisionId( lastRevisionId ) }
{ ...buttonProps }
className="editor-private-post-last-revision__button"
text={ revisionsCount }
aria-label={ sprintf(
Expand Down
3 changes: 0 additions & 3 deletions packages/editor/src/components/post-last-revision/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,3 @@
}
}

.editor-private-post-last-revision__button {
display: inline-block;
}
63 changes: 63 additions & 0 deletions test/e2e/specs/editor/various/revisions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,69 @@ test.describe( 'Post revisions', () => {
} );
} );

test.describe( 'Post revisions with classic meta boxes', () => {
test.beforeAll( async ( { requestUtils } ) => {
await requestUtils.activatePlugin( 'gutenberg-test-plugin-meta-box' );
} );

test.afterAll( async ( { requestUtils } ) => {
await requestUtils.deactivatePlugin( 'gutenberg-test-plugin-meta-box' );
} );

test( 'falls back to the classic revisions screen', async ( {
admin,
editor,
page,
} ) => {
await admin.createNewPost();

await editor.canvas
.getByRole( 'textbox', { name: 'Add title' } )
.fill( 'Revisions with meta box' );
await editor.canvas
.getByRole( 'button', { name: 'Add default block' } )
.click();
await page.keyboard.type( 'Original content' );
await editor.saveDraft();

await editor.canvas
.getByRole( 'document', { name: 'Block: Paragraph' } )
.click();
await page.keyboard.press( 'End' );
await page.keyboard.type( ' - Updated content' );
await editor.saveDraft();

await editor.openDocumentSettingsSidebar();
const settingsSidebar = page.getByRole( 'region', {
name: 'Editor settings',
} );
await settingsSidebar.getByRole( 'tab', { name: 'Post' } ).click();

// With classic meta boxes the Revisions control is rendered as a
// link to the classic admin screen, not a button that opens the
// in-editor visual revisions mode.
const revisionsLink = settingsSidebar.getByRole( 'link', {
name: 'Open revisions screen: 2 revisions',
} );
await expect( revisionsLink ).toBeVisible();
await expect( revisionsLink ).toHaveAttribute(
'href',
/revision\.php\?revision=\d+/
);

// The inline DataViews revisions panel is hidden (its PanelBody
// toggle would be the only element with accessible name exactly
// "Revisions"; substring matches like the slug field aria-label
// are excluded with exact: true).
await expect(
settingsSidebar.getByRole( 'button', {
name: 'Revisions',
exact: true,
} )
).toHaveCount( 0 );
} );
} );

test.describe( 'Post revisions slider pagination', () => {
test.afterEach( async ( { requestUtils } ) => {
await requestUtils.deleteAllPosts();
Expand Down
Loading