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

Chrome: Add a publish dropdown v1 #2887

Merged
merged 3 commits into from
Oct 16, 2017
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 2 additions & 2 deletions editor/header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { IconButton } from '@wordpress/components';
*/
import './style.scss';
import SavedState from './saved-state';
import PublishButton from './publish-button';
import PublishWithDropdown from './publish-with-dropdown';
import PreviewButton from './preview-button';
import ModeSwitcher from './mode-switcher';
import Inserter from '../inserter';
Expand Down Expand Up @@ -87,7 +87,7 @@ function Header( {
<div className="editor-header__settings">
<SavedState />
<PreviewButton />
<PublishButton />
<PublishWithDropdown />
<IconButton
icon="admin-generic"
onClick={ toggleSidebar }
Expand Down
22 changes: 5 additions & 17 deletions editor/header/publish-button/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@
*/
import { connect } from 'react-redux';
import classnames from 'classnames';
import { flowRight } from 'lodash';
import { flowRight, noop } from 'lodash';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { Button, withAPIData } from '@wordpress/components';

/**
* Internal dependencies
*/
import './style.scss';
import PublishButtonLabel from './label';
import { editPost, savePost } from '../../actions';
import {
isSavingPost,
isCurrentPostPublished,
isEditedPostBeingScheduled,
getEditedPostVisibility,
isEditedPostSaveable,
Expand All @@ -27,29 +26,18 @@ import {

export function PublishButton( {
isSaving,
isPublished,
onStatusChange,
onSave,
isBeingScheduled,
visibility,
isPublishable,
isSaveable,
user,
onSubmit = noop,
} ) {
const isButtonEnabled = user.data && ! isSaving && isPublishable && isSaveable;
const isContributor = user.data && ! user.data.capabilities.publish_posts;

let buttonText;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An excellent idea to put this logic into its own component.

if ( isContributor ) {
buttonText = __( 'Submit for Review' );
} else if ( isPublished ) {
buttonText = __( 'Update' );
} else if ( isBeingScheduled ) {
buttonText = __( 'Schedule' );
} else {
buttonText = __( 'Publish' );
}

let publishStatus;
if ( isContributor ) {
publishStatus = 'pending';
Expand All @@ -66,6 +54,7 @@ export function PublishButton( {
} );

const onClick = () => {
onSubmit();
onStatusChange( publishStatus );
onSave();
};
Expand All @@ -78,15 +67,14 @@ export function PublishButton( {
disabled={ ! isButtonEnabled }
className={ className }
>
{ buttonText }
<PublishButtonLabel />
</Button>
);
}

const applyConnect = connect(
( state ) => ( {
isSaving: isSavingPost( state ),
isPublished: isCurrentPostPublished( state ),
isBeingScheduled: isEditedPostBeingScheduled( state ),
visibility: getEditedPostVisibility( state ),
isSaveable: isEditedPostSaveable( state ),
Expand Down
56 changes: 56 additions & 0 deletions editor/header/publish-button/label.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* External dependencies
*/
import { connect } from 'react-redux';
import { flowRight } from 'lodash';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { withAPIData } from '@wordpress/components';

/**
* Internal dependencies
*/
import './style.scss';
import {
isCurrentPostPublished,
isEditedPostBeingScheduled,
} from '../../selectors';

export function PublishButtonLabel( {
isPublished,
isBeingScheduled,
user,
} ) {
const isContributor = user.data && ! user.data.capabilities.publish_posts;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice idea to extract this logic in a variable 👍

Is there any plan to have a similar way to access API data as we have with Redux selectors? I can imagine we might want to use isContributor check in other places. At the moment we would have to duplicates what we have here. What I like the most about selectors is that they hide the structure of data representation. /cc @aduth

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably related to how with make withApiData state aware

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Selectors are just functions which happen to follow a particular first-argument convention. If it became a common pattern, I could see how it might be useful to create better organization around operating on API data. However, the implementation of withAPIData makes some compromises hinging on an assumption that its usage is very ad-hoc. To @youknowriad's point, if we were to make this more organized, we might similarly want to rethink how it works in the first place. One example might be to support a separate argument on the higher-order component akin to react-redux's mapStateToProps which helps provide a barrier between the component implementation and the underlying data structure.


if ( isContributor ) {
return __( 'Submit for Review' );
} else if ( isPublished ) {
return __( 'Update' );
} else if ( isBeingScheduled ) {
return __( 'Schedule' );
}

return __( 'Publish' );
}

const applyConnect = connect(
( state ) => ( {
isPublished: isCurrentPostPublished( state ),
isBeingScheduled: isEditedPostBeingScheduled( state ),
} )
);

const applyWithAPIData = withAPIData( () => {
return {
user: '/wp/v2/users/me?context=edit',
};
} );

export default flowRight( [
applyConnect,
applyWithAPIData,
] )( PublishButtonLabel );
5 changes: 0 additions & 5 deletions editor/header/publish-button/style.scss
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
// Needs specificity to override bleed
.wp-core-ui .button.button-large.editor-publish-button {
margin: 0 10px;
}

.editor-publish-button.is-saving,
.editor-publish-button.is-saving:disabled {
position: relative;
Expand Down
27 changes: 27 additions & 0 deletions editor/header/publish-dropdown/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* WordPress Dependencies
*/
import { __ } from '@wordpress/i18n';

/**
* Internal Dependencies
*/
import './style.scss';
import PostVisibility from '../../sidebar/post-visibility';
import PostSchedule from '../../sidebar/post-schedule';
import PublishButton from '../publish-button';

function PublishDropdown( { onSubmit } ) {
return (
<div className="editor-publish-dropdown">
<div><strong>{ __( 'All ready to go!' ) }</strong></div>
<PostVisibility />
<PostSchedule />
<div className="editor-publish-dropdown__publish-button-container">
<PublishButton onSubmit={ onSubmit } />
</div>
</div>
);
}

export default PublishDropdown;
8 changes: 8 additions & 0 deletions editor/header/publish-dropdown/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.editor-publish-dropdown {
padding: 15px;
}

.editor-publish-dropdown__publish-button-container {
margin-top: 20px;
text-align: right;
}
53 changes: 53 additions & 0 deletions editor/header/publish-with-dropdown/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* External Dependencies
*/
import { connect } from 'react-redux';

/**
* WordPress Dependencies
*/
import { Dropdown, Button, Dashicon } from '@wordpress/components';

/**
* Internal Dependencies
*/
import './style.scss';
import PublishDropdown from '../publish-dropdown';
import PublishButtonLabel from '../publish-button/label';
import {
isSavingPost,
isEditedPostSaveable,
isEditedPostPublishable,
} from '../../selectors';

function PublishWithDropdown( { isSaving, isPublishable, isSaveable } ) {
const isButtonEnabled = ! isSaving && isPublishable && isSaveable;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is possible to expose it from connect as one prop.


return (
<Dropdown
position="bottom left"
className="editor-publish-with-dropdown"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newbie question, file name is editor/header/publish-with-dropdown/index.js. A class name is combined from editor keyword and folder name. Is that a pattern we use and the reason that header subfolder is ignored?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's how we do it right now :)

renderToggle={ ( { isOpen, onToggle } ) => (
<Button
className="editor-publish-with-dropdown__button"
isPrimary
onClick={ onToggle }
aria-expanded={ isOpen }
disabled={ ! isButtonEnabled }
>
<PublishButtonLabel />
<Dashicon icon="arrow-down" />
</Button>
) }
renderContent={ ( { onClose } ) => <PublishDropdown onSubmit={ onClose } /> }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice way to close the dropdown on submit.

/>
);
}

export default connect(
( state ) => ( {
isSaving: isSavingPost( state ),
isSaveable: isEditedPostSaveable( state ),
isPublishable: isEditedPostPublishable( state ),
} ),
)( PublishWithDropdown );
8 changes: 8 additions & 0 deletions editor/header/publish-with-dropdown/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.editor-publish-with-dropdown {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It nicely replaces the existing override 👍

margin: 0 10px;
}

.wp-core-ui .editor-publish-with-dropdown__button {
display: inline-flex;
align-items: center;
}
6 changes: 1 addition & 5 deletions editor/header/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,6 @@
margin-left: $item-spacing;
}

.editor-header__left .components-button {
margin-right: $item-spacing;
}

.editor-header .components-button {
border-radius: 3px;

Expand All @@ -132,7 +128,7 @@
}

@include break-medium() {
&.editor-publish-button {
&.editor-publish-button, &.editor-publish-with-dropdown__button {
height: 33px;
line-height: 32px;
}
Expand Down