Skip to content

Commit

Permalink
Fix schedule and then publish flow (#11013)
Browse files Browse the repository at this point in the history
* Use props instead of derived state to render the component.

There was a bug that happened when:

- a post was scheduled for a future date from now
- then the data changed to a past date from now

At this point, the post couldn't be published directly
by clicking the "Publish" button. This component
would show the post-publish panel with a "Post scheduled" status.

* Test: check that pre-publish panel is shown

* Test: check that post-publish panel is shown if post is published

* Test: check that post-publish panel is shown if post is scheduled

* Test: isScheduled is true, but isBeingScheduled false

Although the post status is 'future', the data is before now,
so we should show the pre-publish panel with the Publish button.

* Fix isSaving logic

* Update snapshots

* Test: check that spinner is shown if post is being saved

* Remove unused prop

* Name spinner component so snapshot test is more semantic

* Fix typo

* Update snapshot
  • Loading branch information
nosolosw authored Oct 25, 2018
1 parent ff781f2 commit 09a9f8e
Show file tree
Hide file tree
Showing 4 changed files with 281 additions and 42 deletions.
4 changes: 3 additions & 1 deletion packages/components/src/spinner/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export default () => <span className="components-spinner" />;
export default function Spinner() {
return <span className="components-spinner" />;
}
74 changes: 33 additions & 41 deletions packages/editor/src/components/post-publish-panel/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { get } from 'lodash';
import { get, omit } from 'lodash';

/**
* WordPress dependencies
Expand All @@ -19,29 +19,10 @@ import PostPublishButton from '../post-publish-button';
import PostPublishPanelPrepublish from './prepublish';
import PostPublishPanelPostpublish from './postpublish';

class PostPublishPanel extends Component {
export class PostPublishPanel extends Component {
constructor() {
super( ...arguments );
this.onSubmit = this.onSubmit.bind( this );
this.state = {
loading: false,
submitted: false,
};
}

static getDerivedStateFromProps( props, state ) {
if (
state.submitted ||
props.isSaving ||
( ! props.isPublished && ! props.isScheduled )
) {
return null;
}

return {
submitted: true,
loading: false,
};
}

componentDidUpdate( prevProps ) {
Expand All @@ -56,28 +37,39 @@ class PostPublishPanel extends Component {
const { onClose, hasPublishAction } = this.props;
if ( ! hasPublishAction ) {
onClose();
return;
}
this.setState( { loading: true } );
}

render() {
const { isScheduled, isPublishSidebarEnabled, onClose, onTogglePublishSidebar, forceIsDirty, forceIsSaving, PrePublishExtension, PostPublishExtension, ...additionalProps } = this.props;
const { loading, submitted } = this.state;
const {
forceIsDirty,
forceIsSaving,
isBeingScheduled,
isPublished,
isPublishSidebarEnabled,
isScheduled,
isSaving,
onClose,
onTogglePublishSidebar,
PostPublishExtension,
PrePublishExtension,
...additionalProps
} = this.props;
const isPublishedOrScheduled = isPublished || ( isScheduled && isBeingScheduled );
const propsForPanel = omit( additionalProps, [ 'hasPublishAction' ] );
return (
<div className="editor-post-publish-panel" { ...additionalProps }>
<div className="editor-post-publish-panel" { ...propsForPanel }>
<div className="editor-post-publish-panel__header">
{ ! submitted && (
{ isPublishedOrScheduled && ! isSaving ? (
<div className="editor-post-publish-panel__header-published">
{ isScheduled ? __( 'Scheduled' ) : __( 'Published' ) }
</div>
) : (
<div className="editor-post-publish-panel__header-publish-button">
<PostPublishButton focusOnMount={ true } onSubmit={ this.onSubmit } forceIsDirty={ forceIsDirty } forceIsSaving={ forceIsSaving } />
<span className="editor-post-publish-panel__spacer"></span>
</div>
) }
{ submitted && (
<div className="editor-post-publish-panel__header-published">
{ isScheduled ? __( 'Scheduled' ) : __( 'Published' ) }
</div>
) }
<IconButton
aria-expanded={ true }
onClick={ onClose }
Expand All @@ -86,17 +78,17 @@ class PostPublishPanel extends Component {
/>
</div>
<div className="editor-post-publish-panel__content">
{ ! loading && ! submitted && (
{ ! isSaving && ! isPublishedOrScheduled && (
<PostPublishPanelPrepublish>
{ PrePublishExtension && <PrePublishExtension /> }
</PostPublishPanelPrepublish>
) }
{ loading && ! submitted && <Spinner /> }
{ submitted && (
{ ! isSaving && isPublishedOrScheduled && (
<PostPublishPanelPostpublish>
{ PostPublishExtension && <PostPublishExtension /> }
</PostPublishPanelPostpublish>
) }
{ isSaving && ( <Spinner /> ) }
</div>
<div className="editor-post-publish-panel__footer">
<CheckboxControl
Expand All @@ -114,21 +106,21 @@ export default compose( [
withSelect( ( select ) => {
const {
getCurrentPost,
getCurrentPostType,
isCurrentPostPublished,
isCurrentPostScheduled,
isSavingPost,
isEditedPostBeingScheduled,
isEditedPostDirty,
isSavingPost,
} = select( 'core/editor' );
const { isPublishSidebarEnabled } = select( 'core/editor' );
return {
postType: getCurrentPostType(),
hasPublishAction: get( getCurrentPost(), [ '_links', 'wp:action-publish' ], false ),
isPublished: isCurrentPostPublished(),
isScheduled: isCurrentPostScheduled(),
isSaving: isSavingPost(),
isBeingScheduled: isEditedPostBeingScheduled(),
isDirty: isEditedPostDirty(),
isPublished: isCurrentPostPublished(),
isPublishSidebarEnabled: isPublishSidebarEnabled(),
isSaving: isSavingPost(),
isScheduled: isCurrentPostScheduled(),
};
} ),
withDispatch( ( dispatch, { isPublishSidebarEnabled } ) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`PostPublishPanel should render the post-publish panel if the post is published 1`] = `
<div
className="editor-post-publish-panel"
>
<div
className="editor-post-publish-panel__header"
>
<div
className="editor-post-publish-panel__header-published"
>
Published
</div>
<IconButton
aria-expanded={true}
icon="no-alt"
label="Close panel"
/>
</div>
<div
className="editor-post-publish-panel__content"
>
<WithSelect(PostPublishPanelPostpublish) />
</div>
<div
className="editor-post-publish-panel__footer"
>
<WithInstanceId(CheckboxControl)
label="Always show pre-publish checks."
/>
</div>
</div>
`;

exports[`PostPublishPanel should render the post-publish panel if the post is scheduled 1`] = `
<div
className="editor-post-publish-panel"
>
<div
className="editor-post-publish-panel__header"
>
<div
className="editor-post-publish-panel__header-published"
>
Scheduled
</div>
<IconButton
aria-expanded={true}
icon="no-alt"
label="Close panel"
/>
</div>
<div
className="editor-post-publish-panel__content"
>
<WithSelect(PostPublishPanelPostpublish) />
</div>
<div
className="editor-post-publish-panel__footer"
>
<WithInstanceId(CheckboxControl)
label="Always show pre-publish checks."
/>
</div>
</div>
`;

exports[`PostPublishPanel should render the pre-publish panel if post status is scheduled but date is before now 1`] = `
<div
className="editor-post-publish-panel"
>
<div
className="editor-post-publish-panel__header"
>
<div
className="editor-post-publish-panel__header-publish-button"
>
<WithSelect(WithDispatch(PostPublishButton))
focusOnMount={true}
onSubmit={[Function]}
/>
<span
className="editor-post-publish-panel__spacer"
/>
</div>
<IconButton
aria-expanded={true}
icon="no-alt"
label="Close panel"
/>
</div>
<div
className="editor-post-publish-panel__content"
>
<WithSelect(PostPublishPanelPrepublish) />
</div>
<div
className="editor-post-publish-panel__footer"
>
<WithInstanceId(CheckboxControl)
label="Always show pre-publish checks."
/>
</div>
</div>
`;

exports[`PostPublishPanel should render the pre-publish panel if the post is not saving, published or scheduled 1`] = `
<div
className="editor-post-publish-panel"
>
<div
className="editor-post-publish-panel__header"
>
<div
className="editor-post-publish-panel__header-publish-button"
>
<WithSelect(WithDispatch(PostPublishButton))
focusOnMount={true}
onSubmit={[Function]}
/>
<span
className="editor-post-publish-panel__spacer"
/>
</div>
<IconButton
aria-expanded={true}
icon="no-alt"
label="Close panel"
/>
</div>
<div
className="editor-post-publish-panel__content"
>
<WithSelect(PostPublishPanelPrepublish) />
</div>
<div
className="editor-post-publish-panel__footer"
>
<WithInstanceId(CheckboxControl)
label="Always show pre-publish checks."
/>
</div>
</div>
`;

exports[`PostPublishPanel should render the spinner if the post is being saved 1`] = `
<div
className="editor-post-publish-panel"
>
<div
className="editor-post-publish-panel__header"
>
<div
className="editor-post-publish-panel__header-publish-button"
>
<WithSelect(WithDispatch(PostPublishButton))
focusOnMount={true}
onSubmit={[Function]}
/>
<span
className="editor-post-publish-panel__spacer"
/>
</div>
<IconButton
aria-expanded={true}
icon="no-alt"
label="Close panel"
/>
</div>
<div
className="editor-post-publish-panel__content"
>
<Spinner />
</div>
<div
className="editor-post-publish-panel__footer"
>
<WithInstanceId(CheckboxControl)
label="Always show pre-publish checks."
/>
</div>
</div>
`;
61 changes: 61 additions & 0 deletions packages/editor/src/components/post-publish-panel/test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* External dependencies
*/
import { shallow } from 'enzyme';

/**
* Internal dependencies
*/
import { PostPublishPanel } from '../index';

describe( 'PostPublishPanel', () => {
it( 'should render the pre-publish panel if the post is not saving, published or scheduled', () => {
const wrapper = shallow(
<PostPublishPanel
isPublished={ false }
isScheduled={ false }
isSaving={ false }
/>
);
expect( wrapper ).toMatchSnapshot();
} );

it( 'should render the pre-publish panel if post status is scheduled but date is before now', () => {
const wrapper = shallow(
<PostPublishPanel
isScheduled={ true }
isBeingScheduled={ false }
/>
);

expect( wrapper ).toMatchSnapshot();
} );

it( 'should render the spinner if the post is being saved', () => {
const wrapper = shallow(
<PostPublishPanel
isSaving={ true }
/>
);
expect( wrapper ).toMatchSnapshot();
} );

it( 'should render the post-publish panel if the post is published', () => {
const wrapper = shallow(
<PostPublishPanel
isPublished={ true }
/>
);
expect( wrapper ).toMatchSnapshot();
} );

it( 'should render the post-publish panel if the post is scheduled', () => {
const wrapper = shallow(
<PostPublishPanel
isScheduled={ true }
isBeingScheduled={ true }
/>
);
expect( wrapper ).toMatchSnapshot();
} );
} );

0 comments on commit 09a9f8e

Please sign in to comment.