Skip to content

Commit

Permalink
Post Editor: Update publish flow
Browse files Browse the repository at this point in the history
  • Loading branch information
ntsekouras committed Apr 16, 2024
1 parent 06b3537 commit 52536a6
Show file tree
Hide file tree
Showing 28 changed files with 637 additions and 277 deletions.
18 changes: 14 additions & 4 deletions packages/e2e-test-utils-playwright/src/editor/publish-post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,21 @@ import type { Editor } from './index';
* @param this
*/
export async function publishPost( this: Editor ) {
await this.page.click( 'role=button[name="Publish"i]' );
const entitiesSaveButton = this.page.locator(
'role=region[name="Editor publish"i] >> role=button[name="Save"i]'
);
// If we have changes in other entities, the label is `Save` instead of `Publish`.
const saveButton = this.page
.getByRole( 'region', { name: 'Editor top bar' } )
.getByRole( 'button', { name: 'Save', exact: true } );
const publishButton = this.page
.getByRole( 'region', { name: 'Editor top bar' } )
.getByRole( 'button', { name: 'Publish' } );
const buttonToClick = ( await saveButton.isVisible() )
? saveButton
: publishButton;
await buttonToClick.click();

const entitiesSaveButton = this.page
.getByRole( 'region', { name: 'Editor publish' } )
.getByRole( 'button', { name: 'Save', exact: true } );
const isEntitiesSavePanelVisible = await entitiesSaveButton.isVisible();

// Save any entities.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export function PostPublishButtonOrToggle( {
isScheduled,
togglePublishSidebar,
setEntitiesSavedStatesCallback,
postStatusHasChanged,
postStatus,
} ) {
const IS_TOGGLE = 'toggle';
const IS_BUTTON = 'button';
Expand All @@ -29,6 +31,7 @@ export function PostPublishButtonOrToggle( {
* for a particular role (see https://wordpress.org/documentation/article/post-status/):
*
* - is published
* - post status has changed explicitely to something different than 'future' or 'publish'
* - is scheduled to be published
* - is pending and can't be published (but only for viewports >= medium).
* Originally, we considered showing a button for pending posts that couldn't be published
Expand All @@ -46,13 +49,13 @@ export function PostPublishButtonOrToggle( {
*/
if (
isPublished ||
( postStatusHasChanged &&
! [ 'future', 'publish' ].includes( postStatus ) ) ||
( isScheduled && isBeingScheduled ) ||
( isPending && ! hasPublishAction && ! isSmallerThanMediumViewport )
) {
component = IS_BUTTON;
} else if ( isSmallerThanMediumViewport ) {
component = IS_TOGGLE;
} else if ( isPublishSidebarEnabled ) {
} else if ( isSmallerThanMediumViewport || isPublishSidebarEnabled ) {
component = IS_TOGGLE;
} else {
component = IS_BUTTON;
Expand Down Expand Up @@ -82,6 +85,8 @@ export default compose(
select( editorStore ).isPublishSidebarEnabled(),
isPublishSidebarOpened: select( editorStore ).isPublishSidebarOpened(),
isScheduled: select( editorStore ).isCurrentPostScheduled(),
postStatus: select( editorStore ).getEditedPostAttribute( 'status' ),
postStatusHasChanged: select( editorStore ).getPostEdits()?.status,
} ) ),
withDispatch( ( dispatch ) => {
const { togglePublishSidebar } = dispatch( editorStore );
Expand Down
14 changes: 13 additions & 1 deletion packages/edit-post/src/components/header/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,23 @@
*/
import { render, screen } from '@testing-library/react';

/**
* WordPress dependencies
*/
import { useViewportMatch } from '@wordpress/compose';

/**
* Internal dependencies
*/
import { PostPublishButtonOrToggle } from '../post-publish-button-or-toggle';

jest.mock( '@wordpress/compose/src/hooks/use-viewport-match' );

describe( 'PostPublishButtonOrToggle should render a', () => {
afterEach( () => {
useViewportMatch.mockRestore();
} );

it( 'button when the post is published (1)', () => {
render( <PostPublishButtonOrToggle isPublished /> );
expect(
Expand All @@ -33,7 +44,8 @@ describe( 'PostPublishButtonOrToggle should render a', () => {
).toBeVisible();
} );

it( 'toggle when post is not (1), (2), (3), the viewport is >= medium, and the publish sidebar is enabled', () => {
it( 'toggle when post is not (1), (2), (3), the viewport is <= medium, and the publish sidebar is enabled', () => {
useViewportMatch.mockReturnValue( true );
render( <PostPublishButtonOrToggle isPublishSidebarEnabled /> );
expect(
screen.getByRole( 'button', { name: 'Publish' } )
Expand Down
13 changes: 5 additions & 8 deletions packages/edit-post/src/components/sidebar/post-status/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,25 @@ import { useDispatch, useSelect } from '@wordpress/data';
import {
PostAuthorPanel,
PostSchedulePanel,
PostSwitchToDraftButton,
PostSyncStatus,
PostURLPanel,
PostTemplatePanel,
PostFeaturedImagePanel,
store as editorStore,
privateApis as editorPrivateApis,
} from '@wordpress/editor';

/**
* Internal dependencies
*/
import PostVisibility from '../post-visibility';
import PostTrash from '../post-trash';
import PostSticky from '../post-sticky';
import PostSlug from '../post-slug';
import PostFormat from '../post-format';
import PostPendingStatus from '../post-pending-status';
import PluginPostStatusInfo from '../plugin-post-status-info';
import { unlock } from '../../../lock-unlock';

const { PostStatus: PostStatusPanel } = unlock( editorPrivateApis );

/**
* Module Constants
Expand Down Expand Up @@ -61,14 +62,13 @@ export default function PostStatus() {
<PluginPostStatusInfo.Slot>
{ ( fills ) => (
<>
<PostStatusPanel />
<PostFeaturedImagePanel withPanelBody={ false } />
<PostVisibility />
<PostSchedulePanel />
<PostTemplatePanel />
<PostURLPanel />
<PostSyncStatus />
<PostSticky />
<PostPendingStatus />
<PostFormat />
<PostSlug />
<PostAuthorPanel />
Expand All @@ -77,10 +77,7 @@ export default function PostStatus() {
style={ {
marginTop: '16px',
} }
spacing={ 4 }
wrap
>
<PostSwitchToDraftButton />
<PostTrash />
</HStack>
</>
Expand Down
59 changes: 23 additions & 36 deletions packages/editor/src/components/post-publish-button/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { Button } from '@wordpress/components';
import { Component, createRef } from '@wordpress/element';
import { withSelect, withDispatch } from '@wordpress/data';
import { compose } from '@wordpress/compose';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
Expand Down Expand Up @@ -112,13 +106,14 @@ export class PostPublishButton extends Component {
isSaving,
isAutoSaving,
isToggle,
onSave,
onStatusChange,
savePostStatus,
onSubmit = noop,
onToggle,
visibility,
hasNonPostEntityChanges,
isSavingNonPostEntityChanges,
postStatus,
postStatusHasChanged,
} = this.props;

const isButtonDisabled =
Expand All @@ -135,26 +130,30 @@ export class PostPublishButton extends Component {
( ! isPublishable && ! forceIsDirty ) ) &&
( ! hasNonPostEntityChanges || isSavingNonPostEntityChanges );

let publishStatus;
if ( ! hasPublishAction ) {
// If the new status has not changed explicitely, we derive it from
// other factors, like having a publish action, etc.. We need to preserve
// this because it affects when to show the pre and post publish panels.
// If it has changed though explicitely, we need to respect that.
let publishStatus = 'publish';
if ( postStatusHasChanged ) {
publishStatus = postStatus;
} else if ( ! hasPublishAction ) {
publishStatus = 'pending';
} else if ( visibility === 'private' ) {
publishStatus = 'private';
} else if ( isBeingScheduled ) {
publishStatus = 'future';
} else {
publishStatus = 'publish';
}

const onClickButton = () => {
if ( isButtonDisabled ) {
return;
}
onSubmit();
onStatusChange( publishStatus );
onSave();
savePostStatus( publishStatus );
};

// Callback to open the publish panel.
const onClickToggle = () => {
if ( isToggleDisabled ) {
return;
Expand All @@ -179,33 +178,16 @@ export class PostPublishButton extends Component {
size: 'compact',
onClick: this.createOnClick( onClickToggle ),
};

const toggleChildren = isBeingScheduled
? __( 'Schedule…' )
: __( 'Publish' );
const buttonChildren = (
<PublishButtonLabel
hasNonPostEntityChanges={ hasNonPostEntityChanges }
/>
);

const componentProps = isToggle ? toggleProps : buttonProps;
const componentChildren = isToggle ? toggleChildren : buttonChildren;
return (
<>
<Button
ref={ this.buttonNode }
{ ...componentProps }
className={ classnames(
componentProps.className,
'editor-post-publish-button__button',
{
'has-changes-dot': hasNonPostEntityChanges,
}
) }
className={ `${ componentProps.className } editor-post-publish-button__button` }
size="compact"
>
{ componentChildren }
<PublishButtonLabel />
</Button>
</>
);
Expand All @@ -228,6 +210,8 @@ export default compose( [
getCurrentPostId,
hasNonPostEntityChanges,
isSavingNonPostEntityChanges,
getEditedPostAttribute,
getPostEdits,
} = select( editorStore );
return {
isSaving: isSavingPost(),
Expand All @@ -242,16 +226,19 @@ export default compose( [
getCurrentPost()._links?.[ 'wp:action-publish' ] ?? false,
postType: getCurrentPostType(),
postId: getCurrentPostId(),
postStatus: getEditedPostAttribute( 'status' ),
postStatusHasChanged: getPostEdits()?.status,
hasNonPostEntityChanges: hasNonPostEntityChanges(),
isSavingNonPostEntityChanges: isSavingNonPostEntityChanges(),
};
} ),
withDispatch( ( dispatch ) => {
const { editPost, savePost } = dispatch( editorStore );
return {
onStatusChange: ( status ) =>
editPost( { status }, { undoIgnore: true } ),
onSave: savePost,
savePostStatus: ( status ) => {
editPost( { status }, { undoIgnore: true } );
savePost();
},
};
} ),
] )( PostPublishButton );
Loading

0 comments on commit 52536a6

Please sign in to comment.