Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Post Editor: Update publish flow #60456

Merged
merged 3 commits into from
Apr 17, 2024
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
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
Loading