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

Pages: Add posts page option to Add New Page #67648

Closed
wants to merge 6 commits into from
Closed
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
39 changes: 32 additions & 7 deletions packages/edit-site/src/components/add-new-post/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Modal,
__experimentalHStack as HStack,
__experimentalVStack as VStack,
__experimentalText as Text,
TextControl,
} from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
Expand All @@ -16,13 +17,19 @@ import { store as noticesStore } from '@wordpress/notices';
import { decodeEntities } from '@wordpress/html-entities';
import { serialize, synchronizeBlocksWithTemplate } from '@wordpress/blocks';

export default function AddNewPostModal( { postType, onSave, onClose } ) {
export default function AddNewPostModal( {
postType,
typeOfPage,
onSave,
onClose,
} ) {
const labels = useSelect(
( select ) => select( coreStore ).getPostType( postType )?.labels,
[ postType ]
);
const [ isCreatingPost, setIsCreatingPost ] = useState( false );
const [ title, setTitle ] = useState( '' );
const pageForPosts = typeOfPage === 'pageForPosts';

const { saveEntityRecord } = useDispatch( coreStore );
const { createErrorNotice, createSuccessNotice } =
Expand All @@ -37,13 +44,14 @@ export default function AddNewPostModal( { postType, onSave, onClose } ) {
}
setIsCreatingPost( true );
try {
const status = pageForPosts ? 'publish' : 'draft';
const postTypeObject =
await resolveSelect( coreStore ).getPostType( postType );
const newPage = await saveEntityRecord(
'postType',
postType,
{
status: 'draft',
status,
title,
slug: title || __( 'No title' ),
content:
Expand All @@ -60,6 +68,12 @@ export default function AddNewPostModal( { postType, onSave, onClose } ) {
{ throwOnError: true }
);

if ( pageForPosts ) {
await saveEntityRecord( 'root', 'site', {
page_for_posts: newPage.id,
} );
}

onSave( newPage );

createSuccessNotice(
Expand All @@ -84,12 +98,20 @@ export default function AddNewPostModal( { postType, onSave, onClose } ) {
}
}

const modalTitle = pageForPosts
? __( 'Create new posts page' )
: // translators: %s: post type singular_name label e.g: "Page".
sprintf( __( 'Draft new: %s' ), labels?.singular_name );
const modalSubmitLabel = pageForPosts
? __( 'Publish page' )
: __( 'Create draft' );
const postsPageNote = __(
'Note: The posts page cannot be a draft, so it will be published immediately.'
);

return (
<Modal
title={
// translators: %s: post type singular_name label e.g: "Page".
sprintf( __( 'Draft new: %s' ), labels?.singular_name )
}
title={ modalTitle }
onRequestClose={ onClose }
focusOnMount="firstContentElement"
size="small"
Expand All @@ -104,6 +126,9 @@ export default function AddNewPostModal( { postType, onSave, onClose } ) {
placeholder={ __( 'No title' ) }
value={ title }
/>
{ pageForPosts && (
<Text variant="muted">{ postsPageNote }</Text>
) }
<HStack spacing={ 2 } justify="end">
<Button
__next40pxDefaultSize
Expand All @@ -119,7 +144,7 @@ export default function AddNewPostModal( { postType, onSave, onClose } ) {
isBusy={ isCreatingPost }
aria-disabled={ isCreatingPost }
>
{ __( 'Create draft' ) }
{ modalSubmitLabel }
</Button>
</HStack>
</VStack>
Expand Down
122 changes: 110 additions & 12 deletions packages/edit-site/src/components/post-list/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
/**
* WordPress dependencies
*/
import { Button } from '@wordpress/components';
import {
Button,
Dropdown,
__experimentalText as Text,
__experimentalDropdownContentWrapper as DropdownContentWrapper,
__experimentalVStack as VStack,
} from '@wordpress/components';
import {
store as coreStore,
privateApis as coreDataPrivateApis,
Expand Down Expand Up @@ -33,6 +39,7 @@ import {
import AddNewPostModal from '../add-new-post';
import { unlock } from '../../lock-unlock';
import { useEditPostAction } from '../dataviews-actions';
import { useIsSiteEditorLoading } from './../layout/hooks';

const { usePostActions, usePostFields } = unlock( editorPrivateApis );
const { useLocation, useHistory } = unlock( routerPrivateApis );
Expand Down Expand Up @@ -337,15 +344,26 @@ export default function PostList( { postType } ) {
[ totalItems, totalPages ]
);

const { labels, canCreateRecord } = useSelect(
const { labels, canCreateRecord, showPageForPostsOption } = useSelect(
( select ) => {
const { getPostType, canUser } = select( coreStore );
const { getPostType, canUser, getEntityRecord } =
select( coreStore );
const siteSettings = getEntityRecord( 'root', 'site' );
const isPagePostType = getPostType( postType )?.slug === 'page';
const isStaticHomepage = siteSettings?.show_on_front === 'page';
const isPageForPostsSet = getEntityRecord(
'postType',
'page',
siteSettings?.page_for_posts
);
return {
labels: getPostType( postType )?.labels,
canCreateRecord: canUser( 'create', {
kind: 'postType',
name: postType,
} ),
showPageForPostsOption:
isPagePostType && isStaticHomepage && ! isPageForPostsSet,
};
},
[ postType ]
Expand All @@ -362,31 +380,111 @@ export default function PostList( { postType } ) {
);

const [ showAddPostModal, setShowAddPostModal ] = useState( false );
const [ typeOfPageToCreate, setTypeOfPageToCreate ] = useState( '' );

const openModal = ( typeOfPage ) => {
setTypeOfPageToCreate( typeOfPage );
setShowAddPostModal( true );
};
const closeModal = () => {
setTypeOfPageToCreate( '' );
setShowAddPostModal( false );
};

const isEditorLoading = useIsSiteEditorLoading();

const NewPageDropdownButton = () => {
return (
<Dropdown
popoverProps={ { placement: 'bottom-end' } }
renderToggle={ ( { onToggle, isOpen } ) => {
const toggleProps = {
onClick: onToggle,
'aria-expanded': isOpen,
label: labels?.add_new_item,
};

return (
<Button
variant="primary"
__next40pxDefaultSize
disabled={ isEditorLoading }
accessibleWhenDisabled
{ ...toggleProps }
>
{ toggleProps.label }
</Button>
);
} }
renderContent={ () => (
<DropdownContentWrapper paddingSize="medium">
<VStack
className="dataviews-new-page-options"
spacing={ 1 }
style={ { minWidth: '250px' } }
>
<Button
__next40pxDefaultSize
onClick={ () => openModal() }
>
{ __( 'Regular page' ) }
</Button>
<Button
__next40pxDefaultSize
onClick={ () => openModal( 'pageForPosts' ) }
style={ {
flexDirection: 'column',
alignItems: 'flex-start',
height: '46px',
} }
>
{ __( 'Blog' ) }
<Text variant="muted" align="left">
{ __(
'Create a page to display latest posts'
) }
</Text>
</Button>
</VStack>
</DropdownContentWrapper>
) }
/>
);
};

const openModal = () => setShowAddPostModal( true );
const closeModal = () => setShowAddPostModal( false );
const handleNewPage = ( { type, id } ) => {
history.navigate( `/${ type }/${ id }?canvas=edit` );
closeModal();
};

const AddNewPageButton = () => {
if ( showPageForPostsOption ) {
return <NewPageDropdownButton />;
}

return (
<Button
variant="primary"
onClick={ openModal }
__next40pxDefaultSize
>
{ labels.add_new_item }
</Button>
);
};

return (
<Page
title={ labels?.name }
actions={
labels?.add_new_item &&
canCreateRecord && (
<>
<Button
variant="primary"
onClick={ openModal }
__next40pxDefaultSize
>
{ labels.add_new_item }
</Button>
<AddNewPageButton />
{ showAddPostModal && (
<AddNewPostModal
postType={ postType }
typeOfPage={ typeOfPageToCreate }
onSave={ handleNewPage }
onClose={ closeModal }
/>
Expand Down
Loading