From c7101cf53b107b8c686647e5d1bc756a5da5146c Mon Sep 17 00:00:00 2001 From: Grant Kinney Date: Mon, 16 Sep 2024 09:53:22 -0500 Subject: [PATCH 01/87] Adds basic action and modal to set page as homepage --- .../src/dataviews/store/private-actions.ts | 2 + packages/editor/src/store/constants.ts | 1 + packages/fields/src/actions/index.ts | 1 + .../fields/src/actions/set-as-homepage.tsx | 99 +++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 packages/fields/src/actions/set-as-homepage.tsx diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 10f2b9ce872d5a..3afdea289d316d 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -20,6 +20,7 @@ import { exportPattern, permanentlyDeletePost, restorePost, + setAsHomepage, trashPost, renamePost, resetPost, @@ -117,6 +118,7 @@ export const registerPostTypeActions = ? reorderPage : undefined, postTypeConfig.slug === 'wp_block' ? exportPattern : undefined, + postTypeConfig.slug === 'page' ? setAsHomepage : undefined, restorePost, resetPost, deletePost, diff --git a/packages/editor/src/store/constants.ts b/packages/editor/src/store/constants.ts index 78708f00cc9eb7..f609797dd53464 100644 --- a/packages/editor/src/store/constants.ts +++ b/packages/editor/src/store/constants.ts @@ -23,6 +23,7 @@ export const TEMPLATE_POST_TYPE = 'wp_template'; export const TEMPLATE_PART_POST_TYPE = 'wp_template_part'; export const PATTERN_POST_TYPE = 'wp_block'; export const NAVIGATION_POST_TYPE = 'wp_navigation'; +export const PAGE_POST_TYPE = 'page'; export const TEMPLATE_ORIGINS = { custom: 'custom', theme: 'theme', diff --git a/packages/fields/src/actions/index.ts b/packages/fields/src/actions/index.ts index 08e22836e68fd1..c533ca6802f1ef 100644 --- a/packages/fields/src/actions/index.ts +++ b/packages/fields/src/actions/index.ts @@ -13,3 +13,4 @@ export { default as permanentlyDeletePost } from './permanently-delete-post'; export { default as restorePost } from './restore-post'; export { default as trashPost } from './trash-post'; export { default as deletePost } from './delete-post'; +export { default as setAsHomepage } from './set-as-homepage'; diff --git a/packages/fields/src/actions/set-as-homepage.tsx b/packages/fields/src/actions/set-as-homepage.tsx new file mode 100644 index 00000000000000..adc894f5238cf5 --- /dev/null +++ b/packages/fields/src/actions/set-as-homepage.tsx @@ -0,0 +1,99 @@ +/** + * WordPress dependencies + */ +import { useDispatch } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { __ } from '@wordpress/i18n'; +import { useState } from '@wordpress/element'; +import { + Button, + __experimentalText as Text, + __experimentalHStack as HStack, + __experimentalVStack as VStack, +} from '@wordpress/components'; +import type { Action } from '@wordpress/dataviews'; +import { store as noticesStore } from '@wordpress/notices'; + +/** + * Internal dependencies + */ +import { getItemTitle } from './utils'; +import type { CoreDataError, PostWithPermissions } from '../types'; + +const PAGE_POST_TYPE = 'page'; + +const renamePost: Action< PostWithPermissions > = { + id: 'set-as-homepage', + label: __( 'Set as homepage' ), + isEligible( post ) { + if ( post.status === 'trash' ) { + return false; + } + + // TODO: add user permissions check. + return post.type === PAGE_POST_TYPE; + }, + RenderModal: ( { items, closeModal, onActionPerformed } ) => { + const [ item ] = items; + const [ title ] = useState( () => getItemTitle( item ) ); + const { editEntityRecord, saveEditedEntityRecord } = + useDispatch( coreStore ); + const { createSuccessNotice, createErrorNotice } = + useDispatch( noticesStore ); + + async function onSetAsHomepage( event: React.FormEvent ) { + event.preventDefault(); + try { + await editEntityRecord( 'root', 'site', undefined, { + page_on_front: item.id, + } ); + closeModal?.(); + // Persist edited entity. + await saveEditedEntityRecord( 'root', 'site', undefined, { + page_on_front: item.id, + } ); + createSuccessNotice( __( 'This page set as homepage' ), { + type: 'snackbar', + } ); + onActionPerformed?.( items ); + } catch ( error ) { + const typedError = error as CoreDataError; + const errorMessage = + typedError.message && typedError.code !== 'unknown_error' + ? typedError.message + : __( + 'An error occurred while setting this page as homepage' + ); + createErrorNotice( errorMessage, { type: 'snackbar' } ); + } + } + + return ( +
+ + { title } + + + + + +
+ ); + }, +}; + +export default renamePost; From 585ef017f17e60116788fd0e937b844ee43ba743 Mon Sep 17 00:00:00 2001 From: Grant Kinney Date: Mon, 16 Sep 2024 11:10:57 -0500 Subject: [PATCH 02/87] Adds permissions and settings checks to set as homepage action --- .../src/dataviews/store/private-actions.ts | 12 +++++++++++- packages/fields/src/actions/set-as-homepage.tsx | 17 ++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 3afdea289d316d..2425340687c9b6 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -88,6 +88,14 @@ export const registerPostTypeActions = kind: 'postType', name: postType, } ); + + const canManageOptions = await registry + .resolveSelect( coreStore ) + .canUser( 'update', { + kind: 'root', + name: 'site', + } ); + const currentTheme = await registry .resolveSelect( coreStore ) .getCurrentTheme(); @@ -118,7 +126,9 @@ export const registerPostTypeActions = ? reorderPage : undefined, postTypeConfig.slug === 'wp_block' ? exportPattern : undefined, - postTypeConfig.slug === 'page' ? setAsHomepage : undefined, + canManageOptions && postTypeConfig.slug === 'page' + ? setAsHomepage + : undefined, restorePost, resetPost, deletePost, diff --git a/packages/fields/src/actions/set-as-homepage.tsx b/packages/fields/src/actions/set-as-homepage.tsx index adc894f5238cf5..e6e326c18e2574 100644 --- a/packages/fields/src/actions/set-as-homepage.tsx +++ b/packages/fields/src/actions/set-as-homepage.tsx @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useDispatch } from '@wordpress/data'; +import { select, useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { __ } from '@wordpress/i18n'; import { useState } from '@wordpress/element'; @@ -30,8 +30,17 @@ const renamePost: Action< PostWithPermissions > = { return false; } - // TODO: add user permissions check. - return post.type === PAGE_POST_TYPE; + if ( post.type !== PAGE_POST_TYPE ) { + return false; + } + + // @ts-ignore + const { page_on_front: pageOnFront } = select( + coreStore + // @ts-ignore + ).getEntityRecord( 'root', 'site' ); + + return pageOnFront !== post.id; }, RenderModal: ( { items, closeModal, onActionPerformed } ) => { const [ item ] = items; @@ -44,11 +53,13 @@ const renamePost: Action< PostWithPermissions > = { async function onSetAsHomepage( event: React.FormEvent ) { event.preventDefault(); try { + // @ts-ignore await editEntityRecord( 'root', 'site', undefined, { page_on_front: item.id, } ); closeModal?.(); // Persist edited entity. + // @ts-ignore await saveEditedEntityRecord( 'root', 'site', undefined, { page_on_front: item.id, } ); From 41474da6426f440f4afb748b0f5d595f3742632a Mon Sep 17 00:00:00 2001 From: Grant Kinney Date: Tue, 17 Sep 2024 16:43:28 -0700 Subject: [PATCH 03/87] Adds proper description and handles unpublished pages --- packages/editor/src/dataviews/types.ts | 2 +- .../fields/src/actions/set-as-homepage.tsx | 86 ++++++++++++++++--- 2 files changed, 75 insertions(+), 13 deletions(-) diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts index 664c2dd417201c..4d27fc7dc4139d 100644 --- a/packages/editor/src/dataviews/types.ts +++ b/packages/editor/src/dataviews/types.ts @@ -1,5 +1,5 @@ type PostStatus = - | 'published' + | 'publish' | 'draft' | 'pending' | 'private' diff --git a/packages/fields/src/actions/set-as-homepage.tsx b/packages/fields/src/actions/set-as-homepage.tsx index e6e326c18e2574..ffd370547adfa8 100644 --- a/packages/fields/src/actions/set-as-homepage.tsx +++ b/packages/fields/src/actions/set-as-homepage.tsx @@ -1,9 +1,9 @@ /** * WordPress dependencies */ -import { select, useDispatch } from '@wordpress/data'; +import { select, useDispatch, useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -import { __ } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; import { useState } from '@wordpress/element'; import { Button, @@ -34,17 +34,47 @@ const renamePost: Action< PostWithPermissions > = { return false; } - // @ts-ignore - const { page_on_front: pageOnFront } = select( + const pageOnFront = select( coreStore // @ts-ignore - ).getEntityRecord( 'root', 'site' ); + ).getEntityRecord( 'root', 'site' )?.page_on_front; - return pageOnFront !== post.id; + if ( pageOnFront === post.id ) { + return false; + } + + return true; }, RenderModal: ( { items, closeModal, onActionPerformed } ) => { const [ item ] = items; const [ title ] = useState( () => getItemTitle( item ) ); + const { currentHomePage, pageForPosts, pageOnFront, showOnFront } = + // @ts-ignore + useSelect( ( _select ) => { + // @ts-ignore + const siteSettings = _select( coreStore ).getEntityRecord( + 'root', + 'site' + ); + // @ts-ignore + const _pageOnFront = siteSettings?.page_on_front || null; + const _currentHomePage = + _pageOnFront && + _select( coreStore ).getEntityRecord( + 'postType', + 'page', + _pageOnFront + ); + + return { + currentHomePage: _currentHomePage, + // @ts-ignore + pageForPosts: siteSettings?.page_for_posts, + pageOnFront: _pageOnFront, + // @ts-ignore + showOnFront: siteSettings?.showOnFront, + }; + } ); const { editEntityRecord, saveEditedEntityRecord } = useDispatch( coreStore ); const { createSuccessNotice, createErrorNotice } = @@ -52,13 +82,30 @@ const renamePost: Action< PostWithPermissions > = { async function onSetAsHomepage( event: React.FormEvent ) { event.preventDefault(); + let publishItem = false; try { + if ( 'publish' !== item.status ) { + await editEntityRecord( 'postType', item.type, item.id, { + status: 'publish', + } ); + publishItem = true; + } // @ts-ignore await editEntityRecord( 'root', 'site', undefined, { page_on_front: item.id, } ); closeModal?.(); - // Persist edited entity. + // Persist edited entities. + if ( publishItem ) { + await saveEditedEntityRecord( + 'postType', + item.type, + item.id, + { + status: 'publish', + } + ); + } // @ts-ignore await saveEditedEntityRecord( 'root', 'site', undefined, { page_on_front: item.id, @@ -72,17 +119,32 @@ const renamePost: Action< PostWithPermissions > = { const errorMessage = typedError.message && typedError.code !== 'unknown_error' ? typedError.message - : __( - 'An error occurred while setting this page as homepage' - ); + : __( 'An error occurred while setting the homepage' ); createErrorNotice( errorMessage, { type: 'snackbar' } ); } } + const modalTranslatedString = + 'publish' !== item.status + ? // translators: %1$s: title of a unpublished page to be set as the home page. %2$s: title of the current home page. + __( + 'The page "%1$s" is not published. Set it as the site homepage? This will publish the page and replace the current homepage: "%2$s"' + ) + : // translators: %1$s: title of page to be set as the home page. %2$s: title of the current home page. + __( + 'Set "%1$s" as the site homepage? This will replace the current homepage: "%2$s"' + ); + + const modalDescription = sprintf( + modalTranslatedString, + title, + getItemTitle( currentHomePage ) + ); + return (
- { title } + { modalDescription } From 921d0f4eedaa2638f20c0a707e7bf6a070735ed7 Mon Sep 17 00:00:00 2001 From: Grant Kinney Date: Tue, 17 Sep 2024 17:06:33 -0700 Subject: [PATCH 04/87] Adds action to set homepage to show latest posts --- .../fields/src/actions/set-as-homepage.tsx | 84 +++++++++++++++---- 1 file changed, 67 insertions(+), 17 deletions(-) diff --git a/packages/fields/src/actions/set-as-homepage.tsx b/packages/fields/src/actions/set-as-homepage.tsx index ffd370547adfa8..17c6a6bab2fb91 100644 --- a/packages/fields/src/actions/set-as-homepage.tsx +++ b/packages/fields/src/actions/set-as-homepage.tsx @@ -124,25 +124,75 @@ const renamePost: Action< PostWithPermissions > = { } } - const modalTranslatedString = - 'publish' !== item.status - ? // translators: %1$s: title of a unpublished page to be set as the home page. %2$s: title of the current home page. - __( - 'The page "%1$s" is not published. Set it as the site homepage? This will publish the page and replace the current homepage: "%2$s"' - ) - : // translators: %1$s: title of page to be set as the home page. %2$s: title of the current home page. - __( - 'Set "%1$s" as the site homepage? This will replace the current homepage: "%2$s"' - ); - - const modalDescription = sprintf( - modalTranslatedString, - title, - getItemTitle( currentHomePage ) - ); + async function onSetLatestPostsHomepage( event: React.FormEvent ) { + event.preventDefault(); + + try { + // @ts-ignore + await editEntityRecord( 'root', 'site', undefined, { + show_on_front: 'posts', + } ); + + closeModal?.(); + + await saveEditedEntityRecord( 'root', 'site', undefined, { + show_on_front: 'posts', + } ); + + createSuccessNotice( + __( 'Homepage set to display latest posts' ), + { + type: 'snackbar', + } + ); + onActionPerformed?.( items ); + } catch ( error ) { + const typedError = error as CoreDataError; + const errorMessage = + typedError.message && typedError.code !== 'unknown_error' + ? typedError.message + : __( + 'An error occurred while setting the homepage to display latest posts' + ); + createErrorNotice( errorMessage, { type: 'snackbar' } ); + } + } + const currentHomePageTitle = getItemTitle( currentHomePage ); + + let modalDescription; + let submitAction; + + if ( item.id === pageForPosts ) { + modalDescription = sprintf( + // translators: %s: title of the current home page. + __( + 'Set the homepage to display the latest posts? This will replace the current home page: "%s"' + ), + currentHomePageTitle + ); + submitAction = onSetLatestPostsHomepage; + } else { + const modalTranslatedString = + 'publish' !== item.status + ? // translators: %1$s: title of a unpublished page to be set as the home page. %2$s: title of the current home page. + __( + 'The page "%1$s" is not published. Set it as the site homepage? This will publish the page and replace the current homepage: "%2$s"' + ) + : // translators: %1$s: title of page to be set as the home page. %2$s: title of the current home page. + __( + 'Set "%1$s" as the site homepage? This will replace the current homepage: "%2$s"' + ); + + modalDescription = sprintf( + modalTranslatedString, + title, + currentHomePageTitle + ); + submitAction = onSetAsHomepage; + } return ( - + { modalDescription } From 23cefbd64adacd8120d2b914a76e7fc793184e48 Mon Sep 17 00:00:00 2001 From: Grant Kinney Date: Thu, 19 Sep 2024 13:58:16 -0700 Subject: [PATCH 05/87] Doesn't show action if there's a front-page template --- packages/editor/src/dataviews/store/private-actions.ts | 3 +++ packages/fields/src/actions/set-as-homepage.tsx | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 2425340687c9b6..a2c090aa099ac5 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -122,6 +122,9 @@ export const registerPostTypeActions = ? duplicatePattern : undefined, postTypeConfig.supports?.title ? renamePost : undefined, + canManageOptions && postTypeConfig.slug === 'page' + ? setAsHomepage + : undefined, postTypeConfig?.supports?.[ 'page-attributes' ] ? reorderPage : undefined, diff --git a/packages/fields/src/actions/set-as-homepage.tsx b/packages/fields/src/actions/set-as-homepage.tsx index 17c6a6bab2fb91..ac6755604a19ff 100644 --- a/packages/fields/src/actions/set-as-homepage.tsx +++ b/packages/fields/src/actions/set-as-homepage.tsx @@ -34,6 +34,15 @@ const renamePost: Action< PostWithPermissions > = { return false; } + // A front-page tempalte overrides homepage settings, so don't show the action if it's present. + const homepageTemplateSlug = + select( coreStore ).__experimentalGetTemplateForLink( '/' )?.slug; + + if ( 'front-page' === homepageTemplateSlug ) { + return false; + } + + // Don't show the action if the page is already set as the homepage. const pageOnFront = select( coreStore // @ts-ignore From fb35be06d187bbe9557d2dfc61c681aa6cf23085 Mon Sep 17 00:00:00 2001 From: Grant Kinney Date: Thu, 19 Sep 2024 16:34:57 -0700 Subject: [PATCH 06/87] Creates page for posts, when specified --- .../editor/src/dataviews/actions/utils.ts | 4 + .../fields/src/actions/set-as-homepage.tsx | 136 ++++++++++++++---- 2 files changed, 111 insertions(+), 29 deletions(-) diff --git a/packages/editor/src/dataviews/actions/utils.ts b/packages/editor/src/dataviews/actions/utils.ts index 33a2be16397f3f..4680e196258431 100644 --- a/packages/editor/src/dataviews/actions/utils.ts +++ b/packages/editor/src/dataviews/actions/utils.ts @@ -29,6 +29,10 @@ export function isTemplateOrTemplatePart( } export function getItemTitle( item: Post ) { + if ( ! item ) { + return ''; + } + if ( typeof item.title === 'string' ) { return decodeEntities( item.title ); } diff --git a/packages/fields/src/actions/set-as-homepage.tsx b/packages/fields/src/actions/set-as-homepage.tsx index ac6755604a19ff..435488d25a4e65 100644 --- a/packages/fields/src/actions/set-as-homepage.tsx +++ b/packages/fields/src/actions/set-as-homepage.tsx @@ -10,6 +10,8 @@ import { __experimentalText as Text, __experimentalHStack as HStack, __experimentalVStack as VStack, + CheckboxControl, + TextControl, } from '@wordpress/components'; import type { Action } from '@wordpress/dataviews'; import { store as noticesStore } from '@wordpress/notices'; @@ -22,7 +24,7 @@ import type { CoreDataError, PostWithPermissions } from '../types'; const PAGE_POST_TYPE = 'page'; -const renamePost: Action< PostWithPermissions > = { +const setAsHomepage: Action< PostWithPermissions > = { id: 'set-as-homepage', label: __( 'Set as homepage' ), isEligible( post ) { @@ -35,10 +37,10 @@ const renamePost: Action< PostWithPermissions > = { } // A front-page tempalte overrides homepage settings, so don't show the action if it's present. - const homepageTemplateSlug = - select( coreStore ).__experimentalGetTemplateForLink( '/' )?.slug; + const homepageTemplate = + select( coreStore ).__experimentalGetTemplateForLink( '/' ); - if ( 'front-page' === homepageTemplateSlug ) { + if ( homepageTemplate && 'front-page' === homepageTemplate.slug ) { return false; } @@ -56,8 +58,10 @@ const renamePost: Action< PostWithPermissions > = { }, RenderModal: ( { items, closeModal, onActionPerformed } ) => { const [ item ] = items; - const [ title ] = useState( () => getItemTitle( item ) ); - const { currentHomePage, pageForPosts, pageOnFront, showOnFront } = + const pageTitle = getItemTitle( item ); + const [ createPageForPosts, setCreatePageForPosts ] = useState( false ); + const [ postsPageTitle, setPostsPageTitle ] = useState( '' ); + const { currentHomePage, pageForPosts, showOnFront } = // @ts-ignore useSelect( ( _select ) => { // @ts-ignore @@ -79,32 +83,51 @@ const renamePost: Action< PostWithPermissions > = { currentHomePage: _currentHomePage, // @ts-ignore pageForPosts: siteSettings?.page_for_posts, - pageOnFront: _pageOnFront, // @ts-ignore - showOnFront: siteSettings?.showOnFront, + showOnFront: siteSettings?.show_on_front, }; } ); - const { editEntityRecord, saveEditedEntityRecord } = + const currentHomePageTitle = getItemTitle( currentHomePage ); + + const { editEntityRecord, saveEditedEntityRecord, saveEntityRecord } = useDispatch( coreStore ); const { createSuccessNotice, createErrorNotice } = useDispatch( noticesStore ); - async function onSetAsHomepage( event: React.FormEvent ) { + async function onSetPageAsHomepage( event: React.FormEvent ) { event.preventDefault(); + let publishItem = false; + let newPage; + try { + // Create a new page for posts, if that action was selected. + if ( createPageForPosts ) { + newPage = await saveEntityRecord( 'postType', 'page', { + title: postsPageTitle, + status: 'publish', + } ); + } + + // Publish the page to become the homepage, if needed. if ( 'publish' !== item.status ) { await editEntityRecord( 'postType', item.type, item.id, { status: 'publish', } ); publishItem = true; } + + // Save new home page settings. // @ts-ignore await editEntityRecord( 'root', 'site', undefined, { + page_for_posts: newPage?.id, page_on_front: item.id, + show_on_front: 'page', } ); + closeModal?.(); - // Persist edited entities. + + // Persist changes. if ( publishItem ) { await saveEditedEntityRecord( 'postType', @@ -115,13 +138,18 @@ const renamePost: Action< PostWithPermissions > = { } ); } + // @ts-ignore await saveEditedEntityRecord( 'root', 'site', undefined, { + page_for_posts: newPage?.id, page_on_front: item.id, + show_on_front: 'page', } ); - createSuccessNotice( __( 'This page set as homepage' ), { + + createSuccessNotice( __( 'Page set as homepage' ), { type: 'snackbar', } ); + onActionPerformed?.( items ); } catch ( error ) { const typedError = error as CoreDataError; @@ -166,18 +194,61 @@ const renamePost: Action< PostWithPermissions > = { createErrorNotice( errorMessage, { type: 'snackbar' } ); } } - const currentHomePageTitle = getItemTitle( currentHomePage ); - let modalDescription; + let modalBody; let submitAction; - if ( item.id === pageForPosts ) { - modalDescription = sprintf( - // translators: %s: title of the current home page. - __( - 'Set the homepage to display the latest posts? This will replace the current home page: "%s"' - ), - currentHomePageTitle + if ( 'posts' === showOnFront ) { + modalBody = ( + <> + + { sprintf( + // translators: %s: title of the page to be set as the homepage. + __( + 'Set "%s" as the site homepage? This will replace the current homepage which is set to display the latest posts.' + ), + pageTitle + ) } + + { ! pageForPosts && ( + <> + + setCreatePageForPosts( value ) + } + /> + { createPageForPosts && ( + + setPostsPageTitle( value ) + } + /> + ) } + + ) } + + ); + submitAction = onSetPageAsHomepage; + } else if ( item.id === pageForPosts ) { + modalBody = ( + + { sprintf( + // translators: %s: title of the current home page. + __( + 'Set the homepage to display the latest posts? This will replace the current home page: "%s"' + ), + currentHomePageTitle + ) }{ ' ' } + ); submitAction = onSetLatestPostsHomepage; } else { @@ -192,18 +263,22 @@ const renamePost: Action< PostWithPermissions > = { 'Set "%1$s" as the site homepage? This will replace the current homepage: "%2$s"' ); - modalDescription = sprintf( - modalTranslatedString, - title, - currentHomePageTitle + modalBody = ( + + { sprintf( + modalTranslatedString, + pageTitle, + currentHomePageTitle + ) }{ ' ' } + ); - submitAction = onSetAsHomepage; + submitAction = onSetPageAsHomepage; } return ( - { modalDescription } + { modalBody } @@ -228,4 +306,4 @@ const renamePost: Action< PostWithPermissions > = { }, }; -export default renamePost; +export default setAsHomepage; From 5de983c466b2883047401d6d8a53cbe17da8c652 Mon Sep 17 00:00:00 2001 From: Grant Kinney Date: Mon, 30 Sep 2024 16:32:26 -0500 Subject: [PATCH 07/87] Refactors modal component --- packages/data/README.md | 2 +- .../data/src/components/use-select/index.js | 2 +- .../fields/src/actions/set-as-homepage.tsx | 231 +++++++++--------- 3 files changed, 121 insertions(+), 114 deletions(-) diff --git a/packages/data/README.md b/packages/data/README.md index 25dd75820fb5db..158c0b1723296a 100644 --- a/packages/data/README.md +++ b/packages/data/README.md @@ -851,7 +851,7 @@ function Paste( { children } ) { _Parameters_ - _mapSelect_ `T`: Function called on every state change. The returned value is exposed to the component implementing this hook. The function receives the `registry.select` method on the first argument and the `registry` on the second argument. When a store key is passed, all selectors for the store will be returned. This is only meant for usage of these selectors in event callbacks, not for data needed to create the element tree. -- _deps_ `unknown[]`: If provided, this memoizes the mapSelect so the same `mapSelect` is invoked on every state change unless the dependencies change. +- _deps_ `[unknown[]]`: If provided, this memoizes the mapSelect so the same `mapSelect` is invoked on every state change unless the dependencies change. _Returns_ diff --git a/packages/data/src/components/use-select/index.js b/packages/data/src/components/use-select/index.js index a0073d7e847fc2..9f209b03d646e9 100644 --- a/packages/data/src/components/use-select/index.js +++ b/packages/data/src/components/use-select/index.js @@ -245,7 +245,7 @@ function useMappingSelect( suspense, mapSelect, deps ) { * When a store key is passed, all selectors for the store will be * returned. This is only meant for usage of these selectors in event * callbacks, not for data needed to create the element tree. - * @param {unknown[]} deps If provided, this memoizes the mapSelect so the same `mapSelect` is + * @param {unknown[]} [deps] If provided, this memoizes the mapSelect so the same `mapSelect` is * invoked on every state change unless the dependencies change. * * @example diff --git a/packages/fields/src/actions/set-as-homepage.tsx b/packages/fields/src/actions/set-as-homepage.tsx index 435488d25a4e65..ee77c9e27e2e52 100644 --- a/packages/fields/src/actions/set-as-homepage.tsx +++ b/packages/fields/src/actions/set-as-homepage.tsx @@ -13,7 +13,7 @@ import { CheckboxControl, TextControl, } from '@wordpress/components'; -import type { Action } from '@wordpress/dataviews'; +import type { Action, ActionModal } from '@wordpress/dataviews'; import { store as noticesStore } from '@wordpress/notices'; /** @@ -24,69 +24,41 @@ import type { CoreDataError, PostWithPermissions } from '../types'; const PAGE_POST_TYPE = 'page'; -const setAsHomepage: Action< PostWithPermissions > = { - id: 'set-as-homepage', - label: __( 'Set as homepage' ), - isEligible( post ) { - if ( post.status === 'trash' ) { - return false; - } - - if ( post.type !== PAGE_POST_TYPE ) { - return false; - } - - // A front-page tempalte overrides homepage settings, so don't show the action if it's present. - const homepageTemplate = - select( coreStore ).__experimentalGetTemplateForLink( '/' ); - - if ( homepageTemplate && 'front-page' === homepageTemplate.slug ) { - return false; - } +const useSiteSettings = () => + useSelect( ( _select ) => { + // @ts-ignore + const siteSettings = _select( coreStore ).getEntityRecord( + 'root', + 'site' + ); + // @ts-ignore + const _pageOnFront = siteSettings?.page_on_front || null; + const _currentHomePage = + _pageOnFront && + _select( coreStore ).getEntityRecord( + 'postType', + 'page', + _pageOnFront + ); - // Don't show the action if the page is already set as the homepage. - const pageOnFront = select( - coreStore + return { + currentHomePage: _currentHomePage, // @ts-ignore - ).getEntityRecord( 'root', 'site' )?.page_on_front; - - if ( pageOnFront === post.id ) { - return false; - } + pageForPosts: siteSettings?.page_for_posts, + // @ts-ignore + showOnFront: siteSettings?.show_on_front, + }; + } ); - return true; - }, - RenderModal: ( { items, closeModal, onActionPerformed } ) => { +const SetAsHomepageModal: ActionModal< PostWithPermissions >[ 'RenderModal' ] = + ( { items, closeModal, onActionPerformed } ) => { const [ item ] = items; const pageTitle = getItemTitle( item ); const [ createPageForPosts, setCreatePageForPosts ] = useState( false ); const [ postsPageTitle, setPostsPageTitle ] = useState( '' ); + // @ts-ignore const { currentHomePage, pageForPosts, showOnFront } = - // @ts-ignore - useSelect( ( _select ) => { - // @ts-ignore - const siteSettings = _select( coreStore ).getEntityRecord( - 'root', - 'site' - ); - // @ts-ignore - const _pageOnFront = siteSettings?.page_on_front || null; - const _currentHomePage = - _pageOnFront && - _select( coreStore ).getEntityRecord( - 'postType', - 'page', - _pageOnFront - ); - - return { - currentHomePage: _currentHomePage, - // @ts-ignore - pageForPosts: siteSettings?.page_for_posts, - // @ts-ignore - showOnFront: siteSettings?.show_on_front, - }; - } ); + useSiteSettings(); const currentHomePageTitle = getItemTitle( currentHomePage ); const { editEntityRecord, saveEditedEntityRecord, saveEntityRecord } = @@ -195,63 +167,60 @@ const setAsHomepage: Action< PostWithPermissions > = { } } - let modalBody; - let submitAction; - - if ( 'posts' === showOnFront ) { - modalBody = ( - <> + const renderModalBody = () => { + if ( 'posts' === showOnFront ) { + return ( + <> + + { sprintf( + // translators: %s: title of the page to be set as the homepage. + __( + 'Set "%s" as the site homepage? This will replace the current homepage which is set to display latest posts.' + ), + pageTitle + ) } + + { ! pageForPosts && ( + <> + + setCreatePageForPosts( value ) + } + /> + { createPageForPosts && ( + + setPostsPageTitle( value ) + } + /> + ) } + + ) } + + ); + } else if ( item.id === pageForPosts ) { + return ( { sprintf( - // translators: %s: title of the page to be set as the homepage. + // translators: %s: title of the current home page. __( - 'Set "%s" as the site homepage? This will replace the current homepage which is set to display the latest posts.' + 'Set the homepage to display latest posts? This will replace the current home page: "%s"' ), - pageTitle - ) } + currentHomePageTitle + ) }{ ' ' } - { ! pageForPosts && ( - <> - - setCreatePageForPosts( value ) - } - /> - { createPageForPosts && ( - - setPostsPageTitle( value ) - } - /> - ) } - - ) } - - ); - submitAction = onSetPageAsHomepage; - } else if ( item.id === pageForPosts ) { - modalBody = ( - - { sprintf( - // translators: %s: title of the current home page. - __( - 'Set the homepage to display the latest posts? This will replace the current home page: "%s"' - ), - currentHomePageTitle - ) }{ ' ' } - - ); - submitAction = onSetLatestPostsHomepage; - } else { + ); + } + const modalTranslatedString = 'publish' !== item.status ? // translators: %1$s: title of a unpublished page to be set as the home page. %2$s: title of the current home page. @@ -263,7 +232,7 @@ const setAsHomepage: Action< PostWithPermissions > = { 'Set "%1$s" as the site homepage? This will replace the current homepage: "%2$s"' ); - modalBody = ( + return ( { sprintf( modalTranslatedString, @@ -272,13 +241,17 @@ const setAsHomepage: Action< PostWithPermissions > = { ) }{ ' ' } ); - submitAction = onSetPageAsHomepage; - } + }; + + const submitAction = + showOnFront === 'posts' || item.id !== pageForPosts + ? onSetPageAsHomepage + : onSetLatestPostsHomepage; return ( - { modalBody } + { renderModalBody() } + + + + + ); +}; + +export const useSetAsHomepageAction = () => { + const { + canManageOptions, + hasFrontPageTemplate, + pageOnFront, + pageForPosts, + } = useSelect( ( select ) => { + const { getEntityRecord, getEntityRecords } = select( coreStore ); + const siteSettings = getEntityRecord( 'root', 'site' ); + const templates = getEntityRecords( 'postType', 'wp_template', { + per_page: -1, + } ); + + return { + pageOnFront: siteSettings?.page_on_front, + pageForPosts: siteSettings?.page_for_posts, + canManageOptions: select( coreStore ).canUser( 'update', { + kind: 'root', + name: 'site', + } ), + hasFrontPageTemplate: !! templates?.find( + ( template ) => + 'slug' in template && template.slug === 'front-page' + ), + }; + } ); + + return useMemo( + () => ( { + id: 'set-as-homepage', + label: __( 'Set as homepage' ), + isEligible( post ) { + if ( post.status === 'trash' ) { + return false; + } + + if ( post.type !== PAGE_POST_TYPE ) { + return false; + } + + // Don't show the action if the page is already set as the homepage. + if ( pageOnFront === post.id ) { + return false; + } + + // Don't show the action if the page is already set as the page for posts. + if ( pageForPosts === post.id ) { + return false; + } + + // Don't show the action if the user can't manage site options. + if ( ! canManageOptions ) { + return false; + } + + // A front-page template overrides homepage settings, + // so don't show the setAsHomepage action if it's present. + if ( hasFrontPageTemplate ) { + return false; + } + + return true; + }, + RenderModal: SetAsHomepageModal, + } ), + [ canManageOptions, hasFrontPageTemplate, pageForPosts, pageOnFront ] + ); +}; diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index b02d47c86555cf..2ae0efd859810c 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -30,7 +30,10 @@ import { import AddNewPostModal from '../add-new-post'; import { unlock } from '../../lock-unlock'; -import { useEditPostAction } from '../dataviews-actions'; +import { + useEditPostAction, + useSetAsHomepageAction, +} from '../dataviews-actions'; import { usePrevious } from '@wordpress/compose'; const { usePostActions, usePostFields } = unlock( editorPrivateApis ); @@ -291,14 +294,6 @@ export default function PostList( { postType } ) { totalPages, } = useEntityRecordsWithPermissions( 'postType', postType, queryArgs ); - const siteSettings = useSelect( ( select ) => { - const site = select( coreStore ).getEntityRecord( 'root', 'site' ); - return { - pageOnFront: site?.page_on_front, - pageForPosts: site?.page_for_posts, - }; - } ); - // The REST API sort the authors by ID, but we want to sort them by name. const data = useMemo( () => { if ( ! isLoadingFields && view?.sort?.field === 'author' ) { @@ -309,12 +304,8 @@ export default function PostList( { postType } ) { ).data; } - records.forEach( ( record ) => { - record.siteSettings = siteSettings; - } ); - return records; - }, [ isLoadingFields, view.sort, records, fields, siteSettings ] ); + }, [ isLoadingFields, view.sort, records, fields ] ); const ids = data?.map( ( record ) => getItemId( record ) ) ?? []; const prevIds = usePrevious( ids ) ?? []; @@ -357,9 +348,11 @@ export default function PostList( { postType } ) { context: 'list', } ); const editAction = useEditPostAction(); + const setAsHomepageAction = useSetAsHomepageAction(); + const actions = useMemo( - () => [ editAction, ...postTypeActions ], - [ postTypeActions, editAction ] + () => [ editAction, setAsHomepageAction, ...postTypeActions ], + [ postTypeActions, editAction, setAsHomepageAction ] ); const [ showAddPostModal, setShowAddPostModal ] = useState( false ); diff --git a/packages/editor/src/components/post-actions/index.js b/packages/editor/src/components/post-actions/index.js index 7f77f59e6da072..ab11b5e318b5a6 100644 --- a/packages/editor/src/components/post-actions/index.js +++ b/packages/editor/src/components/post-actions/index.js @@ -22,16 +22,10 @@ const { Menu, kebabCase } = unlock( componentsPrivateApis ); export default function PostActions( { postType, postId, onActionPerformed } ) { const [ isActionsMenuOpen, setIsActionsMenuOpen ] = useState( false ); - const { item, permissions, siteSettings } = useSelect( + const { item, permissions } = useSelect( ( select ) => { - const { - getEditedEntityRecord, - getEntityRecordPermissions, - getEntityRecord, - } = unlock( select( coreStore ) ); - const site = getEntityRecord( 'root', 'site' ); - const pageOnFront = site?.page_on_front; - const pageForPosts = site?.page_for_posts; + const { getEditedEntityRecord, getEntityRecordPermissions } = + unlock( select( coreStore ) ); return { item: getEditedEntityRecord( 'postType', postType, postId ), permissions: getEntityRecordPermissions( @@ -39,10 +33,6 @@ export default function PostActions( { postType, postId, onActionPerformed } ) { postType, postId ), - siteSettings: { - pageOnFront, - pageForPosts, - }, }; }, [ postId, postType ] @@ -51,9 +41,8 @@ export default function PostActions( { postType, postId, onActionPerformed } ) { return { ...item, permissions, - siteSettings, }; - }, [ item, permissions, siteSettings ] ); + }, [ item, permissions ] ); const allActions = usePostActions( { postType, onActionPerformed } ); const actions = useMemo( () => { diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index abe2fa1e8e44c6..06a936f9a331ad 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -20,7 +20,6 @@ import { exportPattern, permanentlyDeletePost, restorePost, - setAsHomepage, trashPost, renamePost, resetPost, @@ -89,27 +88,10 @@ export const registerPostTypeActions = name: postType, } ); - const canManageOptions = await registry - .resolveSelect( coreStore ) - .canUser( 'update', { - kind: 'root', - name: 'site', - } ); - const currentTheme = await registry .resolveSelect( coreStore ) .getCurrentTheme(); - // A front-page template overrides homepage settings, - // so don't show the setAsHomepage action if it's present. - const templates = await registry - .resolveSelect( coreStore ) - .getEntityRecords( 'postType', 'wp_template', { per_page: -1 } ); - const hasFrontPageTemplate = !! templates?.find( - ( template: { slug: string } ) => - 'slug' in template && template.slug === 'front-page' - ); - const actions = [ postTypeConfig.viewable ? viewPost : undefined, !! postTypeConfig?.supports?.revisions @@ -132,11 +114,6 @@ export const registerPostTypeActions = ? duplicatePattern : undefined, postTypeConfig.supports?.title ? renamePost : undefined, - canManageOptions && - ! hasFrontPageTemplate && - postTypeConfig.slug === 'page' - ? setAsHomepage - : undefined, postTypeConfig?.supports?.[ 'page-attributes' ] ? reorderPage : undefined, diff --git a/packages/fields/README.md b/packages/fields/README.md index a1b0112c329b49..e6cf6d3007ed97 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -90,10 +90,6 @@ Undocumented declaration. Undocumented declaration. -### setAsHomepage - -This action is used to set a page as the homepage. - ### slugField Undocumented declaration. diff --git a/packages/fields/src/actions/index.ts b/packages/fields/src/actions/index.ts index c533ca6802f1ef..08e22836e68fd1 100644 --- a/packages/fields/src/actions/index.ts +++ b/packages/fields/src/actions/index.ts @@ -13,4 +13,3 @@ export { default as permanentlyDeletePost } from './permanently-delete-post'; export { default as restorePost } from './restore-post'; export { default as trashPost } from './trash-post'; export { default as deletePost } from './delete-post'; -export { default as setAsHomepage } from './set-as-homepage'; diff --git a/packages/fields/src/actions/set-as-homepage.tsx b/packages/fields/src/actions/set-as-homepage.tsx deleted file mode 100644 index 00e5ed846959a0..00000000000000 --- a/packages/fields/src/actions/set-as-homepage.tsx +++ /dev/null @@ -1,192 +0,0 @@ -/** - * WordPress dependencies - */ -import { useDispatch, useSelect } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; -import type { Settings } from '@wordpress/core-data'; -import { __, sprintf } from '@wordpress/i18n'; -import { - Button, - __experimentalText as Text, - __experimentalHStack as HStack, - __experimentalVStack as VStack, -} from '@wordpress/components'; -import type { Action, ActionModal } from '@wordpress/dataviews'; -import { store as noticesStore } from '@wordpress/notices'; - -/** - * Internal dependencies - */ -import { getItemTitle } from './utils'; -import type { - CoreDataError, - PostWithPermissionsAndContext, - Post, -} from '../types'; - -const PAGE_POST_TYPE = 'page'; - -const SetAsHomepageModal: ActionModal< PostWithPermissionsAndContext >[ 'RenderModal' ] = - ( { items, closeModal, onActionPerformed } ) => { - const [ item ] = items; - const pageTitle = getItemTitle( item ); - const { currentHomePage, showOnFront } = useSelect( ( select ) => { - const { getEntityRecord } = select( coreStore ); - const siteSettings: Settings | undefined = getEntityRecord( - 'root', - 'site' - ); - const pageOnFront = siteSettings?.page_on_front; - return { - currentHomePage: getEntityRecord( - 'postType', - 'page', - pageOnFront - ), - showOnFront: siteSettings?.show_on_front, - }; - } ); - const currentHomePageTitle = getItemTitle( currentHomePage as Post ); - - const { saveEditedEntityRecord, saveEntityRecord } = - useDispatch( coreStore ); - const { createSuccessNotice, createErrorNotice } = - useDispatch( noticesStore ); - - async function onSetPageAsHomepage( event: React.FormEvent ) { - event.preventDefault(); - - try { - // If selected page is set to draft, publish the page. - if ( item.status === 'draft' ) { - await saveEntityRecord( 'postType', 'page', { - ...item, - status: 'publish', - } ); - } - - // Save new home page settings. - await saveEntityRecord( 'root', 'site', { - page_on_front: item.id, - show_on_front: 'page', - } ); - - closeModal?.(); - - await saveEditedEntityRecord( 'root', 'site', undefined, { - page_on_front: item.id, - show_on_front: 'page', - } ); - - createSuccessNotice( __( 'Homepage updated' ), { - type: 'snackbar', - } ); - - onActionPerformed?.( items ); - } catch ( error ) { - const typedError = error as CoreDataError; - const errorMessage = - typedError.message && typedError.code !== 'unknown_error' - ? typedError.message - : __( 'An error occurred while setting the homepage' ); - createErrorNotice( errorMessage, { type: 'snackbar' } ); - } - } - - const renderModalBody = () => { - if ( 'posts' === showOnFront ) { - return ( - <> - - { sprintf( - // translators: %s: title of the page to be set as the homepage. - __( - 'Set "%s" as the site homepage? This will replace the current homepage which is set to display latest posts.' - ), - pageTitle - ) } - - - ); - } - - const modalTranslatedString = - // translators: %1$s: title of page to be set as the home page. %2$s: title of the current home page. - __( - 'Set "%1$s" as the site homepage? This will replace the current homepage: "%2$s"' - ); - - return ( - - { sprintf( - modalTranslatedString, - pageTitle, - currentHomePageTitle - ) }{ ' ' } - - ); - }; - - return ( -
- - { renderModalBody() } - - - - - -
- ); - }; - -const setAsHomepage: Action< PostWithPermissionsAndContext > = { - id: 'set-as-homepage', - label: __( 'Set as homepage' ), - isEligible( post ) { - const { pageOnFront, pageForPosts } = post.siteSettings; - - if ( post.status === 'trash' ) { - return false; - } - - if ( post.type !== PAGE_POST_TYPE ) { - return false; - } - - // Don't show the action if the page is already set as the homepage. - if ( pageOnFront === post.id ) { - return false; - } - - // Don't show the action if the page is already set as the page for posts. - if ( pageForPosts === post.id ) { - return false; - } - - return true; - }, - RenderModal: SetAsHomepageModal, -}; - -/** - * This action is used to set a page as the homepage. - */ -export default setAsHomepage; diff --git a/packages/fields/src/types.ts b/packages/fields/src/types.ts index 840ff9bc5c0029..e457ec699554cd 100644 --- a/packages/fields/src/types.ts +++ b/packages/fields/src/types.ts @@ -90,13 +90,6 @@ export type PostWithPermissions = Post & { }; }; -export type PostWithPermissionsAndContext = PostWithPermissions & { - siteSettings: { - pageOnFront?: number; - pageForPosts?: number; - }; -}; - export interface PostType { slug: string; viewable: boolean; From 969ed4a180c3a2a935294d7afb441ef943c82a58 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 15 Nov 2024 16:02:48 +0000 Subject: [PATCH 54/87] Revert unnecessary changes --- docs/reference-guides/data/data-core.md | 4 ++-- packages/core-data/README.md | 4 ++-- packages/core-data/src/actions.js | 14 +++++++------- packages/data/README.md | 2 +- packages/data/src/components/use-select/index.js | 2 +- .../edit-site/src/components/post-list/index.js | 2 +- .../editor/src/dataviews/store/private-actions.ts | 1 - 7 files changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md index 5d2f5a0e74518a..474207aa20460f 100644 --- a/docs/reference-guides/data/data-core.md +++ b/docs/reference-guides/data/data-core.md @@ -786,7 +786,7 @@ _Parameters_ - _kind_ `string`: Kind of the edited entity record. - _name_ `string`: Name of the edited entity record. -- _recordId_ `number|string=`: Record ID of the edited entity record. +- _recordId_ `number|string`: Record ID of the edited entity record. - _edits_ `Object`: The edits. - _options_ `Object`: Options for the edit. - _options.undoIgnore_ `[boolean]`: Whether to ignore the edit in undo history or not. @@ -888,7 +888,7 @@ _Parameters_ - _kind_ `string`: Kind of the entity. - _name_ `string`: Name of the entity. -- _recordId_ `Object=`: ID of the record. +- _recordId_ `Object`: ID of the record. - _options_ `Object=`: Saving options. ### saveEntityRecord diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 04c067dc3fe340..079f95ddbfc7a6 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -196,7 +196,7 @@ _Parameters_ - _kind_ `string`: Kind of the edited entity record. - _name_ `string`: Name of the edited entity record. -- _recordId_ `number|string=`: Record ID of the edited entity record. +- _recordId_ `number|string`: Record ID of the edited entity record. - _edits_ `Object`: The edits. - _options_ `Object`: Options for the edit. - _options.undoIgnore_ `[boolean]`: Whether to ignore the edit in undo history or not. @@ -298,7 +298,7 @@ _Parameters_ - _kind_ `string`: Kind of the entity. - _name_ `string`: Name of the entity. -- _recordId_ `Object=`: ID of the record. +- _recordId_ `Object`: ID of the record. - _options_ `Object=`: Saving options. ### saveEntityRecord diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 4a81372ec727a5..13cbba39e11765 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -351,12 +351,12 @@ export const deleteEntityRecord = * Returns an action object that triggers an * edit to an entity record. * - * @param {string} kind Kind of the edited entity record. - * @param {string} name Name of the edited entity record. - * @param {number|string=} recordId Record ID of the edited entity record. - * @param {Object} edits The edits. - * @param {Object} options Options for the edit. - * @param {boolean} [options.undoIgnore] Whether to ignore the edit in undo history or not. + * @param {string} kind Kind of the edited entity record. + * @param {string} name Name of the edited entity record. + * @param {number|string} recordId Record ID of the edited entity record. + * @param {Object} edits The edits. + * @param {Object} options Options for the edit. + * @param {boolean} [options.undoIgnore] Whether to ignore the edit in undo history or not. * * @return {Object} Action object. */ @@ -775,7 +775,7 @@ export const __experimentalBatch = * * @param {string} kind Kind of the entity. * @param {string} name Name of the entity. - * @param {Object=} recordId ID of the record. + * @param {Object} recordId ID of the record. * @param {Object=} options Saving options. */ export const saveEditedEntityRecord = diff --git a/packages/data/README.md b/packages/data/README.md index 158c0b1723296a..25dd75820fb5db 100644 --- a/packages/data/README.md +++ b/packages/data/README.md @@ -851,7 +851,7 @@ function Paste( { children } ) { _Parameters_ - _mapSelect_ `T`: Function called on every state change. The returned value is exposed to the component implementing this hook. The function receives the `registry.select` method on the first argument and the `registry` on the second argument. When a store key is passed, all selectors for the store will be returned. This is only meant for usage of these selectors in event callbacks, not for data needed to create the element tree. -- _deps_ `[unknown[]]`: If provided, this memoizes the mapSelect so the same `mapSelect` is invoked on every state change unless the dependencies change. +- _deps_ `unknown[]`: If provided, this memoizes the mapSelect so the same `mapSelect` is invoked on every state change unless the dependencies change. _Returns_ diff --git a/packages/data/src/components/use-select/index.js b/packages/data/src/components/use-select/index.js index b55158fab6b1de..15a3c88d2d5543 100644 --- a/packages/data/src/components/use-select/index.js +++ b/packages/data/src/components/use-select/index.js @@ -244,7 +244,7 @@ function _useMappingSelect( suspense, mapSelect, deps ) { * When a store key is passed, all selectors for the store will be * returned. This is only meant for usage of these selectors in event * callbacks, not for data needed to create the element tree. - * @param {unknown[]} [deps] If provided, this memoizes the mapSelect so the same `mapSelect` is + * @param {unknown[]} deps If provided, this memoizes the mapSelect so the same `mapSelect` is * invoked on every state change unless the dependencies change. * * @example diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 2ae0efd859810c..4ab68304e2a679 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -305,7 +305,7 @@ export default function PostList( { postType } ) { } return records; - }, [ isLoadingFields, view.sort, records, fields ] ); + }, [ records, fields, isLoadingFields, view?.sort ] ); const ids = data?.map( ( record ) => getItemId( record ) ) ?? []; const prevIds = usePrevious( ids ) ?? []; diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts index 06a936f9a331ad..10f2b9ce872d5a 100644 --- a/packages/editor/src/dataviews/store/private-actions.ts +++ b/packages/editor/src/dataviews/store/private-actions.ts @@ -87,7 +87,6 @@ export const registerPostTypeActions = kind: 'postType', name: postType, } ); - const currentTheme = await registry .resolveSelect( coreStore ) .getCurrentTheme(); From 259a476aa280eb3280b1f48933b3929b6790d89a Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 15 Nov 2024 16:19:44 +0000 Subject: [PATCH 55/87] Move getItemTitle to edit-site utils --- .../dataviews-actions/set-as-homepage.js | 20 +++++-------------- packages/edit-site/src/utils/constants.js | 2 ++ .../edit-site/src/utils/get-item-title.js | 20 +++++++++++++++++++ 3 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 packages/edit-site/src/utils/get-item-title.js diff --git a/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js b/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js index fa8a22e4a43242..108cac1decd10b 100644 --- a/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js +++ b/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js @@ -12,22 +12,12 @@ import { import { useDispatch, useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { store as noticesStore } from '@wordpress/notices'; -import { decodeEntities } from '@wordpress/html-entities'; -const PAGE_POST_TYPE = 'page'; - -const getItemTitle = ( item ) => { - if ( typeof item.title === 'string' ) { - return decodeEntities( item.title ); - } - if ( item.title && 'rendered' in item.title ) { - return decodeEntities( item.title.rendered ); - } - if ( item.title && 'raw' in item.title ) { - return decodeEntities( item.title.raw ); - } - return ''; -}; +/** + * Internal dependencies + */ +import { PAGE_POST_TYPE } from '../../utils/constants'; +import { getItemTitle } from '../../utils/get-item-title'; const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { const [ item ] = items; diff --git a/packages/edit-site/src/utils/constants.js b/packages/edit-site/src/utils/constants.js index 657fc8f34d2f48..74d643978b845e 100644 --- a/packages/edit-site/src/utils/constants.js +++ b/packages/edit-site/src/utils/constants.js @@ -55,3 +55,5 @@ export const OPERATOR_IS = 'is'; export const OPERATOR_IS_NOT = 'isNot'; export const OPERATOR_IS_ANY = 'isAny'; export const OPERATOR_IS_NONE = 'isNone'; + +export const PAGE_POST_TYPE = 'page'; diff --git a/packages/edit-site/src/utils/get-item-title.js b/packages/edit-site/src/utils/get-item-title.js new file mode 100644 index 00000000000000..34e083da77cd75 --- /dev/null +++ b/packages/edit-site/src/utils/get-item-title.js @@ -0,0 +1,20 @@ +/** + * WordPress dependencies + */ +import { decodeEntities } from '@wordpress/html-entities'; + +// TODO: This function is duplicated in packages/editor/src/dataviews/actions/utils.ts, +// so they should be consolidated. + +export function getItemTitle( item ) { + if ( typeof item.title === 'string' ) { + return decodeEntities( item.title ); + } + if ( item.title && 'rendered' in item.title ) { + return decodeEntities( item.title.rendered ); + } + if ( item.title && 'raw' in item.title ) { + return decodeEntities( item.title.raw ); + } + return ''; +} From efbf96c8249ffd82b3c17c3cb444bca1ae4563b4 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 15 Nov 2024 16:21:13 +0000 Subject: [PATCH 56/87] Allow undefined on GetEntityRecord key --- packages/core-data/src/selectors.ts | 4 ++-- .../src/components/dataviews-actions/set-as-homepage.js | 4 ++-- packages/fields/src/fields/title/title-view.tsx | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index 4f8d5dec32af16..97b46ca9c318a1 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -310,7 +310,7 @@ export interface GetEntityRecord { state: State, kind: string, name: string, - key?: EntityRecordKey, + key: EntityRecordKey | undefined, query?: GetRecordsHttpQuery ): EntityRecord | undefined; @@ -321,7 +321,7 @@ export interface GetEntityRecord { >( kind: string, name: string, - key?: EntityRecordKey, + key: EntityRecordKey | undefined, query?: GetRecordsHttpQuery ) => EntityRecord | undefined; __unstableNormalizeArgs?: ( args: EntityRecordArgs ) => EntityRecordArgs; diff --git a/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js b/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js index 108cac1decd10b..bbd27ec9203b05 100644 --- a/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js +++ b/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js @@ -24,7 +24,7 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { const pageTitle = getItemTitle( item ); const { currentHomePage, showOnFront } = useSelect( ( select ) => { const { getEntityRecord } = select( coreStore ); - const siteSettings = getEntityRecord( 'root', 'site' ); + const siteSettings = getEntityRecord( 'root', 'site', undefined ); const pageOnFront = siteSettings?.page_on_front; return { currentHomePage: getEntityRecord( 'postType', 'page', pageOnFront ), @@ -149,7 +149,7 @@ export const useSetAsHomepageAction = () => { pageForPosts, } = useSelect( ( select ) => { const { getEntityRecord, getEntityRecords } = select( coreStore ); - const siteSettings = getEntityRecord( 'root', 'site' ); + const siteSettings = getEntityRecord( 'root', 'site', undefined ); const templates = getEntityRecords( 'postType', 'wp_template', { per_page: -1, } ); diff --git a/packages/fields/src/fields/title/title-view.tsx b/packages/fields/src/fields/title/title-view.tsx index 0a7c2983a1ced2..6a829d7491c601 100644 --- a/packages/fields/src/fields/title/title-view.tsx +++ b/packages/fields/src/fields/title/title-view.tsx @@ -19,7 +19,8 @@ const TitleView = ( { item }: { item: BasePost } ) => { const { getEntityRecord } = select( coreStore ); const siteSettings: Settings | undefined = getEntityRecord( 'root', - 'site' + 'site', + undefined ); return { frontPageId: siteSettings?.page_on_front, From 9de4488cabd8cfdb0c4e97c7f151a79148c540b0 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 15 Nov 2024 17:18:33 +0000 Subject: [PATCH 57/87] Make it more clear that draft page will be published --- .../dataviews-actions/set-as-homepage.js | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js b/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js index bbd27ec9203b05..5d7f047713013f 100644 --- a/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js +++ b/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js @@ -36,13 +36,14 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { useDispatch( coreStore ); const { createSuccessNotice, createErrorNotice } = useDispatch( noticesStore ); + const pageIsDraft = item.status === 'draft'; async function onSetPageAsHomepage( event ) { event.preventDefault(); try { // If selected page is set to draft, publish the page. - if ( item.status === 'draft' ) { + if ( pageIsDraft ) { await saveEntityRecord( 'postType', 'page', { ...item, status: 'publish', @@ -94,6 +95,22 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { ); } + if ( pageIsDraft ) { + return ( + <> + + { sprintf( + // translators: %s: title of the page to be set as the homepage. + __( + '"%s" is a draft and will be published automatically if set as the homepage. Set as the site homepage and publish?' + ), + pageTitle + ) } + + + ); + } + const modalTranslatedString = // translators: %1$s: title of page to be set as the home page. %2$s: title of the current home page. __( @@ -132,7 +149,9 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { > { // translators: Button to confirm setting the specified page as the homepage. - __( 'Set homepage' ) + pageIsDraft + ? __( 'Publish and set homepage' ) + : __( 'Set homepage' ) }
From 5cbe7b41e852d687f10636a1d33bc611380ee5c3 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 18 Nov 2024 11:59:22 +0000 Subject: [PATCH 58/87] Update draft page wording --- .../components/dataviews-actions/set-as-homepage.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js b/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js index 5d7f047713013f..2add779b086d58 100644 --- a/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js +++ b/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js @@ -36,14 +36,14 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { useDispatch( coreStore ); const { createSuccessNotice, createErrorNotice } = useDispatch( noticesStore ); - const pageIsDraft = item.status === 'draft'; + const isPageDraft = item.status === 'draft'; async function onSetPageAsHomepage( event ) { event.preventDefault(); try { // If selected page is set to draft, publish the page. - if ( pageIsDraft ) { + if ( isPageDraft ) { await saveEntityRecord( 'postType', 'page', { ...item, status: 'publish', @@ -95,14 +95,14 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { ); } - if ( pageIsDraft ) { + if ( isPageDraft ) { return ( <> { sprintf( // translators: %s: title of the page to be set as the homepage. __( - '"%s" is a draft and will be published automatically if set as the homepage. Set as the site homepage and publish?' + '"%s" is a draft and will be published automatically if set as the homepage. Publish page and set as the site homepage?' ), pageTitle ) } @@ -149,7 +149,7 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { > { // translators: Button to confirm setting the specified page as the homepage. - pageIsDraft + isPageDraft ? __( 'Publish and set homepage' ) : __( 'Set homepage' ) } From 7a2960a713cb01258a26eba1a0620a6e2c14edf2 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 18 Nov 2024 12:35:08 +0000 Subject: [PATCH 59/87] Add set homepage action to post editor --- .../src/components/post-actions/actions.js | 12 +- .../post-actions/set-as-homepage.js | 232 ++++++++++++++++++ 2 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 packages/editor/src/components/post-actions/set-as-homepage.js diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index e1c0ed1558193d..3a2a64e13218f2 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -9,6 +9,7 @@ import { useMemo, useEffect } from '@wordpress/element'; */ import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; +import { useSetAsHomepageAction } from './set-as-homepage'; export function usePostActions( { postType, onActionPerformed, context } ) { const { defaultActions } = useSelect( @@ -21,6 +22,13 @@ export function usePostActions( { postType, onActionPerformed, context } ) { [ postType ] ); + const setAsHomepageAction = useSetAsHomepageAction(); + + const allActions = useMemo( + () => [ setAsHomepageAction, ...defaultActions ], + [ defaultActions, setAsHomepageAction ] + ); + const { registerPostTypeActions } = unlock( useDispatch( editorStore ) ); useEffect( () => { registerPostTypeActions( postType ); @@ -33,7 +41,7 @@ export function usePostActions( { postType, onActionPerformed, context } ) { // Actions should also provide the `context` they support, if it's specific, to // compare with the provided context to get all the actions. // Right now the only supported context is `list`. - const actions = defaultActions.filter( ( action ) => { + const actions = allActions.filter( ( action ) => { if ( ! action.context ) { return true; } @@ -88,5 +96,5 @@ export function usePostActions( { postType, onActionPerformed, context } ) { } return actions; - }, [ defaultActions, onActionPerformed, context ] ); + }, [ allActions, onActionPerformed, context ] ); } diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js new file mode 100644 index 00000000000000..d9cfb23f3ced99 --- /dev/null +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -0,0 +1,232 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; +import { useMemo } from '@wordpress/element'; +import { + Button, + __experimentalText as Text, + __experimentalHStack as HStack, + __experimentalVStack as VStack, +} from '@wordpress/components'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { store as noticesStore } from '@wordpress/notices'; + +/** + * Internal dependencies + */ +import { PAGE_POST_TYPE } from '../../../../../packages/edit-site/src/utils/constants'; +import { getItemTitle } from '../../../../../packages/edit-site/src/utils/get-item-title'; + +// This action is duplicated and copied from packages/edit-site/src/components/dataviews-actions/set-as-homepage.js + +const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { + const [ item ] = items; + const pageTitle = getItemTitle( item ); + const { currentHomePage, showOnFront } = useSelect( ( select ) => { + const { getEntityRecord } = select( coreStore ); + const siteSettings = getEntityRecord( 'root', 'site', undefined ); + const pageOnFront = siteSettings?.page_on_front; + return { + currentHomePage: getEntityRecord( 'postType', 'page', pageOnFront ), + showOnFront: siteSettings?.show_on_front, + }; + } ); + + const { saveEditedEntityRecord, saveEntityRecord } = + useDispatch( coreStore ); + const { createSuccessNotice, createErrorNotice } = + useDispatch( noticesStore ); + const isPageDraft = item.status === 'draft'; + + async function onSetPageAsHomepage( event ) { + event.preventDefault(); + + try { + // If selected page is set to draft, publish the page. + if ( isPageDraft ) { + await saveEntityRecord( 'postType', 'page', { + ...item, + status: 'publish', + } ); + } + + // Save new home page settings. + await saveEntityRecord( 'root', 'site', { + page_on_front: item.id, + show_on_front: 'page', + } ); + + closeModal?.(); + + await saveEditedEntityRecord( 'root', 'site', undefined, { + page_on_front: item.id, + show_on_front: 'page', + } ); + + createSuccessNotice( __( 'Homepage updated' ), { + type: 'snackbar', + } ); + + onActionPerformed?.( items ); + } catch ( error ) { + const typedError = error; + const errorMessage = + typedError.message && typedError.code !== 'unknown_error' + ? typedError.message + : __( 'An error occurred while setting the homepage' ); + createErrorNotice( errorMessage, { type: 'snackbar' } ); + } + } + + const renderModalBody = () => { + if ( 'posts' === showOnFront ) { + return ( + <> + + { sprintf( + // translators: %s: title of the page to be set as the homepage. + __( + 'Set "%s" as the site homepage? This will replace the current homepage which is set to display latest posts.' + ), + pageTitle + ) } + + + ); + } + + if ( isPageDraft ) { + return ( + <> + + { sprintf( + // translators: %s: title of the page to be set as the homepage. + __( + '"%s" is a draft and will be published automatically if set as the homepage. Publish page and set as the site homepage?' + ), + pageTitle + ) } + + + ); + } + + const modalTranslatedString = + // translators: %1$s: title of page to be set as the home page. %2$s: title of the current home page. + __( + 'Set "%1$s" as the site homepage? This will replace the current homepage: "%2$s"' + ); + + return ( + + { sprintf( + modalTranslatedString, + pageTitle, + getItemTitle( currentHomePage ) + ) }{ ' ' } + + ); + }; + + return ( +
+ + { renderModalBody() } + + + + + +
+ ); +}; + +export const useSetAsHomepageAction = () => { + const { + canManageOptions, + hasFrontPageTemplate, + pageOnFront, + pageForPosts, + } = useSelect( ( select ) => { + const { getEntityRecord, getEntityRecords } = select( coreStore ); + const siteSettings = getEntityRecord( 'root', 'site', undefined ); + const templates = getEntityRecords( 'postType', 'wp_template', { + per_page: -1, + } ); + + return { + pageOnFront: siteSettings?.page_on_front, + pageForPosts: siteSettings?.page_for_posts, + canManageOptions: select( coreStore ).canUser( 'update', { + kind: 'root', + name: 'site', + } ), + hasFrontPageTemplate: !! templates?.find( + ( template ) => + 'slug' in template && template.slug === 'front-page' + ), + }; + } ); + + return useMemo( + () => ( { + id: 'set-as-homepage', + label: __( 'Set as homepage' ), + isEligible( post ) { + if ( post.status === 'trash' ) { + return false; + } + + if ( post.type !== PAGE_POST_TYPE ) { + return false; + } + + // Don't show the action if the page is already set as the homepage. + if ( pageOnFront === post.id ) { + return false; + } + + // Don't show the action if the page is already set as the page for posts. + if ( pageForPosts === post.id ) { + return false; + } + + // Don't show the action if the user can't manage site options. + if ( ! canManageOptions ) { + return false; + } + + // A front-page template overrides homepage settings, + // so don't show the setAsHomepage action if it's present. + if ( hasFrontPageTemplate ) { + return false; + } + + return true; + }, + RenderModal: SetAsHomepageModal, + } ), + [ canManageOptions, hasFrontPageTemplate, pageForPosts, pageOnFront ] + ); +}; From fb2ea4ccd468bf35641d1b90230582f4748560d6 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 18 Nov 2024 13:36:11 +0000 Subject: [PATCH 60/87] Attempt to fix build error --- .../src/components/dataviews-actions/set-as-homepage.js | 3 +-- packages/edit-site/src/utils/constants.js | 2 -- packages/edit-site/src/utils/get-item-title.d.ts | 2 ++ packages/edit-site/src/utils/get-item-title.d.ts.map | 1 + packages/editor/src/components/post-actions/set-as-homepage.js | 3 +-- 5 files changed, 5 insertions(+), 6 deletions(-) create mode 100644 packages/edit-site/src/utils/get-item-title.d.ts create mode 100644 packages/edit-site/src/utils/get-item-title.d.ts.map diff --git a/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js b/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js index 2add779b086d58..4b1e4f3a9edfb4 100644 --- a/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js +++ b/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js @@ -16,7 +16,6 @@ import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies */ -import { PAGE_POST_TYPE } from '../../utils/constants'; import { getItemTitle } from '../../utils/get-item-title'; const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { @@ -196,7 +195,7 @@ export const useSetAsHomepageAction = () => { return false; } - if ( post.type !== PAGE_POST_TYPE ) { + if ( post.type !== 'page' ) { return false; } diff --git a/packages/edit-site/src/utils/constants.js b/packages/edit-site/src/utils/constants.js index 74d643978b845e..657fc8f34d2f48 100644 --- a/packages/edit-site/src/utils/constants.js +++ b/packages/edit-site/src/utils/constants.js @@ -55,5 +55,3 @@ export const OPERATOR_IS = 'is'; export const OPERATOR_IS_NOT = 'isNot'; export const OPERATOR_IS_ANY = 'isAny'; export const OPERATOR_IS_NONE = 'isNone'; - -export const PAGE_POST_TYPE = 'page'; diff --git a/packages/edit-site/src/utils/get-item-title.d.ts b/packages/edit-site/src/utils/get-item-title.d.ts new file mode 100644 index 00000000000000..736d68c98f5f0e --- /dev/null +++ b/packages/edit-site/src/utils/get-item-title.d.ts @@ -0,0 +1,2 @@ +export function getItemTitle( item: any ): string; +//# sourceMappingURL=get-item-title.d.ts.map diff --git a/packages/edit-site/src/utils/get-item-title.d.ts.map b/packages/edit-site/src/utils/get-item-title.d.ts.map new file mode 100644 index 00000000000000..76a514bc9b97f3 --- /dev/null +++ b/packages/edit-site/src/utils/get-item-title.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"get-item-title.d.ts","sourceRoot":"","sources":["get-item-title.js"],"names":[],"mappings":"AAQA,gDAWC"} \ No newline at end of file diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index d9cfb23f3ced99..073f1f7408b268 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -16,7 +16,6 @@ import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies */ -import { PAGE_POST_TYPE } from '../../../../../packages/edit-site/src/utils/constants'; import { getItemTitle } from '../../../../../packages/edit-site/src/utils/get-item-title'; // This action is duplicated and copied from packages/edit-site/src/components/dataviews-actions/set-as-homepage.js @@ -198,7 +197,7 @@ export const useSetAsHomepageAction = () => { return false; } - if ( post.type !== PAGE_POST_TYPE ) { + if ( post.type !== 'page' ) { return false; } From 1a1f682df8f5fa50c90a2e7882dbdb27c8afddac Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 18 Nov 2024 14:16:51 +0000 Subject: [PATCH 61/87] Remove homepage action from edit-site --- .../src/components/dataviews-actions/index.js | 3 - .../dataviews-actions/set-as-homepage.js | 229 ------------------ .../src/components/post-list/index.js | 10 +- .../edit-site/src/utils/get-item-title.d.ts | 2 - .../src/utils/get-item-title.d.ts.map | 1 - .../post-actions/set-as-homepage.js | 4 +- .../src/utils/get-item-title.js | 3 +- 7 files changed, 5 insertions(+), 247 deletions(-) delete mode 100644 packages/edit-site/src/components/dataviews-actions/set-as-homepage.js delete mode 100644 packages/edit-site/src/utils/get-item-title.d.ts delete mode 100644 packages/edit-site/src/utils/get-item-title.d.ts.map rename packages/{edit-site => editor}/src/utils/get-item-title.js (77%) diff --git a/packages/edit-site/src/components/dataviews-actions/index.js b/packages/edit-site/src/components/dataviews-actions/index.js index 01a42ffab2e304..09b7597c6cb341 100644 --- a/packages/edit-site/src/components/dataviews-actions/index.js +++ b/packages/edit-site/src/components/dataviews-actions/index.js @@ -11,7 +11,6 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; */ import { PATTERN_TYPES } from '../../utils/constants'; import { unlock } from '../../lock-unlock'; -import { useSetAsHomepageAction } from './set-as-homepage'; const { useHistory } = unlock( routerPrivateApis ); @@ -42,5 +41,3 @@ export const useEditPostAction = () => { [ history ] ); }; - -export { useSetAsHomepageAction }; diff --git a/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js b/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js deleted file mode 100644 index 4b1e4f3a9edfb4..00000000000000 --- a/packages/edit-site/src/components/dataviews-actions/set-as-homepage.js +++ /dev/null @@ -1,229 +0,0 @@ -/** - * WordPress dependencies - */ -import { __, sprintf } from '@wordpress/i18n'; -import { useMemo } from '@wordpress/element'; -import { - Button, - __experimentalText as Text, - __experimentalHStack as HStack, - __experimentalVStack as VStack, -} from '@wordpress/components'; -import { useDispatch, useSelect } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; -import { store as noticesStore } from '@wordpress/notices'; - -/** - * Internal dependencies - */ -import { getItemTitle } from '../../utils/get-item-title'; - -const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { - const [ item ] = items; - const pageTitle = getItemTitle( item ); - const { currentHomePage, showOnFront } = useSelect( ( select ) => { - const { getEntityRecord } = select( coreStore ); - const siteSettings = getEntityRecord( 'root', 'site', undefined ); - const pageOnFront = siteSettings?.page_on_front; - return { - currentHomePage: getEntityRecord( 'postType', 'page', pageOnFront ), - showOnFront: siteSettings?.show_on_front, - }; - } ); - - const { saveEditedEntityRecord, saveEntityRecord } = - useDispatch( coreStore ); - const { createSuccessNotice, createErrorNotice } = - useDispatch( noticesStore ); - const isPageDraft = item.status === 'draft'; - - async function onSetPageAsHomepage( event ) { - event.preventDefault(); - - try { - // If selected page is set to draft, publish the page. - if ( isPageDraft ) { - await saveEntityRecord( 'postType', 'page', { - ...item, - status: 'publish', - } ); - } - - // Save new home page settings. - await saveEntityRecord( 'root', 'site', { - page_on_front: item.id, - show_on_front: 'page', - } ); - - closeModal?.(); - - await saveEditedEntityRecord( 'root', 'site', undefined, { - page_on_front: item.id, - show_on_front: 'page', - } ); - - createSuccessNotice( __( 'Homepage updated' ), { - type: 'snackbar', - } ); - - onActionPerformed?.( items ); - } catch ( error ) { - const typedError = error; - const errorMessage = - typedError.message && typedError.code !== 'unknown_error' - ? typedError.message - : __( 'An error occurred while setting the homepage' ); - createErrorNotice( errorMessage, { type: 'snackbar' } ); - } - } - - const renderModalBody = () => { - if ( 'posts' === showOnFront ) { - return ( - <> - - { sprintf( - // translators: %s: title of the page to be set as the homepage. - __( - 'Set "%s" as the site homepage? This will replace the current homepage which is set to display latest posts.' - ), - pageTitle - ) } - - - ); - } - - if ( isPageDraft ) { - return ( - <> - - { sprintf( - // translators: %s: title of the page to be set as the homepage. - __( - '"%s" is a draft and will be published automatically if set as the homepage. Publish page and set as the site homepage?' - ), - pageTitle - ) } - - - ); - } - - const modalTranslatedString = - // translators: %1$s: title of page to be set as the home page. %2$s: title of the current home page. - __( - 'Set "%1$s" as the site homepage? This will replace the current homepage: "%2$s"' - ); - - return ( - - { sprintf( - modalTranslatedString, - pageTitle, - getItemTitle( currentHomePage ) - ) }{ ' ' } - - ); - }; - - return ( -
- - { renderModalBody() } - - - - - -
- ); -}; - -export const useSetAsHomepageAction = () => { - const { - canManageOptions, - hasFrontPageTemplate, - pageOnFront, - pageForPosts, - } = useSelect( ( select ) => { - const { getEntityRecord, getEntityRecords } = select( coreStore ); - const siteSettings = getEntityRecord( 'root', 'site', undefined ); - const templates = getEntityRecords( 'postType', 'wp_template', { - per_page: -1, - } ); - - return { - pageOnFront: siteSettings?.page_on_front, - pageForPosts: siteSettings?.page_for_posts, - canManageOptions: select( coreStore ).canUser( 'update', { - kind: 'root', - name: 'site', - } ), - hasFrontPageTemplate: !! templates?.find( - ( template ) => - 'slug' in template && template.slug === 'front-page' - ), - }; - } ); - - return useMemo( - () => ( { - id: 'set-as-homepage', - label: __( 'Set as homepage' ), - isEligible( post ) { - if ( post.status === 'trash' ) { - return false; - } - - if ( post.type !== 'page' ) { - return false; - } - - // Don't show the action if the page is already set as the homepage. - if ( pageOnFront === post.id ) { - return false; - } - - // Don't show the action if the page is already set as the page for posts. - if ( pageForPosts === post.id ) { - return false; - } - - // Don't show the action if the user can't manage site options. - if ( ! canManageOptions ) { - return false; - } - - // A front-page template overrides homepage settings, - // so don't show the setAsHomepage action if it's present. - if ( hasFrontPageTemplate ) { - return false; - } - - return true; - }, - RenderModal: SetAsHomepageModal, - } ), - [ canManageOptions, hasFrontPageTemplate, pageForPosts, pageOnFront ] - ); -}; diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 4ab68304e2a679..b87af54361f659 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -30,10 +30,7 @@ import { import AddNewPostModal from '../add-new-post'; import { unlock } from '../../lock-unlock'; -import { - useEditPostAction, - useSetAsHomepageAction, -} from '../dataviews-actions'; +import { useEditPostAction } from '../dataviews-actions'; import { usePrevious } from '@wordpress/compose'; const { usePostActions, usePostFields } = unlock( editorPrivateApis ); @@ -348,11 +345,10 @@ export default function PostList( { postType } ) { context: 'list', } ); const editAction = useEditPostAction(); - const setAsHomepageAction = useSetAsHomepageAction(); const actions = useMemo( - () => [ editAction, setAsHomepageAction, ...postTypeActions ], - [ postTypeActions, editAction, setAsHomepageAction ] + () => [ editAction, ...postTypeActions ], + [ postTypeActions, editAction ] ); const [ showAddPostModal, setShowAddPostModal ] = useState( false ); diff --git a/packages/edit-site/src/utils/get-item-title.d.ts b/packages/edit-site/src/utils/get-item-title.d.ts deleted file mode 100644 index 736d68c98f5f0e..00000000000000 --- a/packages/edit-site/src/utils/get-item-title.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export function getItemTitle( item: any ): string; -//# sourceMappingURL=get-item-title.d.ts.map diff --git a/packages/edit-site/src/utils/get-item-title.d.ts.map b/packages/edit-site/src/utils/get-item-title.d.ts.map deleted file mode 100644 index 76a514bc9b97f3..00000000000000 --- a/packages/edit-site/src/utils/get-item-title.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"get-item-title.d.ts","sourceRoot":"","sources":["get-item-title.js"],"names":[],"mappings":"AAQA,gDAWC"} \ No newline at end of file diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index 073f1f7408b268..4b1e4f3a9edfb4 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -16,9 +16,7 @@ import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies */ -import { getItemTitle } from '../../../../../packages/edit-site/src/utils/get-item-title'; - -// This action is duplicated and copied from packages/edit-site/src/components/dataviews-actions/set-as-homepage.js +import { getItemTitle } from '../../utils/get-item-title'; const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { const [ item ] = items; diff --git a/packages/edit-site/src/utils/get-item-title.js b/packages/editor/src/utils/get-item-title.js similarity index 77% rename from packages/edit-site/src/utils/get-item-title.js rename to packages/editor/src/utils/get-item-title.js index 34e083da77cd75..b98160cbde3dcc 100644 --- a/packages/edit-site/src/utils/get-item-title.js +++ b/packages/editor/src/utils/get-item-title.js @@ -3,8 +3,7 @@ */ import { decodeEntities } from '@wordpress/html-entities'; -// TODO: This function is duplicated in packages/editor/src/dataviews/actions/utils.ts, -// so they should be consolidated. +// This function is copied from packages/editor/src/dataviews/actions/utils.ts. export function getItemTitle( item ) { if ( typeof item.title === 'string' ) { From c10846ba915a7335c7845dee663873e3da28201d Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 18 Nov 2024 14:24:09 +0000 Subject: [PATCH 62/87] Remove extra line --- packages/edit-site/src/components/post-list/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index b87af54361f659..975809b2ad6106 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -345,7 +345,6 @@ export default function PostList( { postType } ) { context: 'list', } ); const editAction = useEditPostAction(); - const actions = useMemo( () => [ editAction, ...postTypeActions ], [ postTypeActions, editAction ] From 5e5cf0c5d7d792eb0de4fe4ffb440c0caf1a3536 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 18 Nov 2024 17:50:10 +0000 Subject: [PATCH 63/87] Fix getting current homepage title --- .../post-actions/set-as-homepage.js | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index 4b1e4f3a9edfb4..efd6383a32aad9 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -2,14 +2,14 @@ * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { useMemo } from '@wordpress/element'; +import { useEffect, useMemo, useState } from '@wordpress/element'; import { Button, __experimentalText as Text, __experimentalHStack as HStack, __experimentalVStack as VStack, } from '@wordpress/components'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useDispatch, useSelect, resolveSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { store as noticesStore } from '@wordpress/notices'; @@ -21,21 +21,37 @@ import { getItemTitle } from '../../utils/get-item-title'; const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { const [ item ] = items; const pageTitle = getItemTitle( item ); - const { currentHomePage, showOnFront } = useSelect( ( select ) => { + const { showOnFront, pageOnFront } = useSelect( ( select ) => { const { getEntityRecord } = select( coreStore ); const siteSettings = getEntityRecord( 'root', 'site', undefined ); - const pageOnFront = siteSettings?.page_on_front; return { - currentHomePage: getEntityRecord( 'postType', 'page', pageOnFront ), showOnFront: siteSettings?.show_on_front, + pageOnFront: siteSettings?.page_on_front, }; } ); + const [ currentHomePageTitle, setCurrentHomePageTitle ] = useState( null ); + const isPageDraft = item.status === 'draft'; + const { getEntityRecord } = resolveSelect( coreStore ); const { saveEditedEntityRecord, saveEntityRecord } = useDispatch( coreStore ); const { createSuccessNotice, createErrorNotice } = useDispatch( noticesStore ); - const isPageDraft = item.status === 'draft'; + + useEffect( () => { + const handleGetCurrentHomepage = async () => { + const currentHomePage = await getEntityRecord( + 'postType', + 'page', + pageOnFront + ); + + if ( currentHomePage ) { + setCurrentHomePageTitle( getItemTitle( currentHomePage ) ); + } + }; + handleGetCurrentHomepage(); + }, [ getEntityRecord, pageOnFront ] ); async function onSetPageAsHomepage( event ) { event.preventDefault(); @@ -121,7 +137,7 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { { sprintf( modalTranslatedString, pageTitle, - getItemTitle( currentHomePage ) + currentHomePageTitle ) }{ ' ' }
); From 2b37368a6ea0bae038fee28899e03e42371016ce Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 18 Nov 2024 17:51:37 +0000 Subject: [PATCH 64/87] Make key in getEntityRecord optional --- packages/core-data/src/selectors.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index 97b46ca9c318a1..581a4e91945a58 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -350,7 +350,7 @@ export const getEntityRecord = createSelector( state: State, kind: string, name: string, - key: EntityRecordKey, + key?: EntityRecordKey, query?: GetRecordsHttpQuery ): EntityRecord | undefined => { const queriedState = From 43dd85f0f4bafeb1ec7a275024787d14b3d86caa Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 18 Nov 2024 18:24:49 +0000 Subject: [PATCH 65/87] Use getHomePage selector --- .../post-actions/set-as-homepage.js | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index efd6383a32aad9..f8ee68df4cbf83 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -17,19 +17,22 @@ import { store as noticesStore } from '@wordpress/notices'; * Internal dependencies */ import { getItemTitle } from '../../utils/get-item-title'; +import { unlock } from '../../lock-unlock'; const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { const [ item ] = items; const pageTitle = getItemTitle( item ); - const { showOnFront, pageOnFront } = useSelect( ( select ) => { + const { showOnFront, currentHomePage } = useSelect( ( select ) => { const { getEntityRecord } = select( coreStore ); + const { getHomePage } = unlock( select( coreStore ) ); const siteSettings = getEntityRecord( 'root', 'site', undefined ); + const homePage = getHomePage(); return { showOnFront: siteSettings?.show_on_front, - pageOnFront: siteSettings?.page_on_front, + currentHomePage: homePage.postId, }; } ); - const [ currentHomePageTitle, setCurrentHomePageTitle ] = useState( null ); + const [ currentHomePageTitle, setCurrentHomePageTitle ] = useState( '' ); const isPageDraft = item.status === 'draft'; const { getEntityRecord } = resolveSelect( coreStore ); @@ -40,18 +43,15 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { useEffect( () => { const handleGetCurrentHomepage = async () => { - const currentHomePage = await getEntityRecord( + const currentHomePageItem = await getEntityRecord( 'postType', 'page', - pageOnFront + currentHomePage ); - - if ( currentHomePage ) { - setCurrentHomePageTitle( getItemTitle( currentHomePage ) ); - } + setCurrentHomePageTitle( getItemTitle( currentHomePageItem ) ); }; handleGetCurrentHomepage(); - }, [ getEntityRecord, pageOnFront ] ); + }, [ currentHomePage, getEntityRecord ] ); async function onSetPageAsHomepage( event ) { event.preventDefault(); From 4cd6988031abb6806396b493eac13c6a62d987d6 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 18 Nov 2024 18:43:02 +0000 Subject: [PATCH 66/87] Move canManageOptions and hasFrontPageTemplate to actions.js --- .../src/components/post-actions/actions.js | 40 ++++++++++++++++--- .../post-actions/set-as-homepage.js | 34 ++-------------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 3a2a64e13218f2..ec2dbaf761daba 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -3,6 +3,7 @@ */ import { useDispatch, useSelect } from '@wordpress/data'; import { useMemo, useEffect } from '@wordpress/element'; +import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies @@ -22,26 +23,47 @@ export function usePostActions( { postType, onActionPerformed, context } ) { [ postType ] ); - const setAsHomepageAction = useSetAsHomepageAction(); + const { canManageOptions, hasFrontPageTemplate } = useSelect( + ( select ) => { + const { getEntityRecords } = select( coreStore ); + const templates = getEntityRecords( 'postType', 'wp_template', { + per_page: -1, + } ); - const allActions = useMemo( - () => [ setAsHomepageAction, ...defaultActions ], - [ defaultActions, setAsHomepageAction ] + return { + canManageOptions: select( coreStore ).canUser( 'update', { + kind: 'root', + name: 'site', + } ), + hasFrontPageTemplate: !! templates?.find( + ( template ) => + 'slug' in template && template.slug === 'front-page' + ), + }; + } ); + const setAsHomepageAction = useSetAsHomepageAction(); + const shouldShowSetAsHomepageAction = + canManageOptions || ! hasFrontPageTemplate; + const { registerPostTypeActions } = unlock( useDispatch( editorStore ) ); useEffect( () => { registerPostTypeActions( postType ); }, [ registerPostTypeActions, postType ] ); return useMemo( () => { + let actions = [ + shouldShowSetAsHomepageAction ? setAsHomepageAction : [], + ...defaultActions, + ]; // Filter actions based on provided context. If not provided // all actions are returned. We'll have a single entry for getting the actions // and the consumer should provide the context to filter the actions, if needed. // Actions should also provide the `context` they support, if it's specific, to // compare with the provided context to get all the actions. // Right now the only supported context is `list`. - const actions = allActions.filter( ( action ) => { + actions = actions.filter( ( action ) => { if ( ! action.context ) { return true; } @@ -96,5 +118,11 @@ export function usePostActions( { postType, onActionPerformed, context } ) { } return actions; - }, [ allActions, onActionPerformed, context ] ); + }, [ + context, + defaultActions, + onActionPerformed, + setAsHomepageAction, + shouldShowSetAsHomepageAction, + ] ); } diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index f8ee68df4cbf83..15da488296690c 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -176,29 +176,12 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { }; export const useSetAsHomepageAction = () => { - const { - canManageOptions, - hasFrontPageTemplate, - pageOnFront, - pageForPosts, - } = useSelect( ( select ) => { - const { getEntityRecord, getEntityRecords } = select( coreStore ); + const { pageOnFront, pageForPosts } = useSelect( ( select ) => { + const { getEntityRecord } = select( coreStore ); const siteSettings = getEntityRecord( 'root', 'site', undefined ); - const templates = getEntityRecords( 'postType', 'wp_template', { - per_page: -1, - } ); - return { pageOnFront: siteSettings?.page_on_front, pageForPosts: siteSettings?.page_for_posts, - canManageOptions: select( coreStore ).canUser( 'update', { - kind: 'root', - name: 'site', - } ), - hasFrontPageTemplate: !! templates?.find( - ( template ) => - 'slug' in template && template.slug === 'front-page' - ), }; } ); @@ -225,21 +208,10 @@ export const useSetAsHomepageAction = () => { return false; } - // Don't show the action if the user can't manage site options. - if ( ! canManageOptions ) { - return false; - } - - // A front-page template overrides homepage settings, - // so don't show the setAsHomepage action if it's present. - if ( hasFrontPageTemplate ) { - return false; - } - return true; }, RenderModal: SetAsHomepageModal, } ), - [ canManageOptions, hasFrontPageTemplate, pageForPosts, pageOnFront ] + [ pageForPosts, pageOnFront ] ); }; From b2e88eb33715f590693a9211623e3c0117815443 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Tue, 19 Nov 2024 10:56:31 +0000 Subject: [PATCH 67/87] Make key optional in EntityRecordKey --- packages/core-data/src/private-selectors.ts | 1 - packages/core-data/src/selectors.ts | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/core-data/src/private-selectors.ts b/packages/core-data/src/private-selectors.ts index 02fe152ed0abb6..77790512653065 100644 --- a/packages/core-data/src/private-selectors.ts +++ b/packages/core-data/src/private-selectors.ts @@ -151,7 +151,6 @@ export const getHomePage = createRegistrySelector( ( select ) => return { postType: 'wp_template', postId: frontPageTemplateId }; }, ( state ) => [ - // @ts-expect-error getEntityRecord( state, 'root', 'site' ), getDefaultTemplateId( state, { slug: 'front-page', diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index 581a4e91945a58..1d745cbde698cb 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -310,7 +310,7 @@ export interface GetEntityRecord { state: State, kind: string, name: string, - key: EntityRecordKey | undefined, + key?: EntityRecordKey, query?: GetRecordsHttpQuery ): EntityRecord | undefined; @@ -321,7 +321,7 @@ export interface GetEntityRecord { >( kind: string, name: string, - key: EntityRecordKey | undefined, + key?: EntityRecordKey, query?: GetRecordsHttpQuery ) => EntityRecord | undefined; __unstableNormalizeArgs?: ( args: EntityRecordArgs ) => EntityRecordArgs; From 953e99952bfb8508f83401429703682941fa7c2e Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Tue, 19 Nov 2024 11:35:28 +0000 Subject: [PATCH 68/87] Remove undefined from getEntityRecord calls --- .../editor/src/components/post-actions/set-as-homepage.js | 4 ++-- packages/fields/src/fields/title/title-view.tsx | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index 15da488296690c..e3c8b4b4425578 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -25,7 +25,7 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { const { showOnFront, currentHomePage } = useSelect( ( select ) => { const { getEntityRecord } = select( coreStore ); const { getHomePage } = unlock( select( coreStore ) ); - const siteSettings = getEntityRecord( 'root', 'site', undefined ); + const siteSettings = getEntityRecord( 'root', 'site' ); const homePage = getHomePage(); return { showOnFront: siteSettings?.show_on_front, @@ -178,7 +178,7 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { export const useSetAsHomepageAction = () => { const { pageOnFront, pageForPosts } = useSelect( ( select ) => { const { getEntityRecord } = select( coreStore ); - const siteSettings = getEntityRecord( 'root', 'site', undefined ); + const siteSettings = getEntityRecord( 'root', 'site' ); return { pageOnFront: siteSettings?.page_on_front, pageForPosts: siteSettings?.page_for_posts, diff --git a/packages/fields/src/fields/title/title-view.tsx b/packages/fields/src/fields/title/title-view.tsx index 6a829d7491c601..f6bf5fb1817d93 100644 --- a/packages/fields/src/fields/title/title-view.tsx +++ b/packages/fields/src/fields/title/title-view.tsx @@ -17,11 +17,10 @@ import { getItemTitle } from '../../actions/utils'; const TitleView = ( { item }: { item: BasePost } ) => { const { frontPageId, postsPageId } = useSelect( ( select ) => { const { getEntityRecord } = select( coreStore ); - const siteSettings: Settings | undefined = getEntityRecord( + const siteSettings = getEntityRecord( 'root', - 'site', - undefined - ); + 'site' + ) as Partial< Settings >; return { frontPageId: siteSettings?.page_on_front, postsPageId: siteSettings?.page_for_posts, From f01d347a97c5e403eca4d280d15161b5f4145c37 Mon Sep 17 00:00:00 2001 From: Sarah Norris <1645628+mikachan@users.noreply.github.com> Date: Wed, 20 Nov 2024 11:30:57 +0000 Subject: [PATCH 69/87] Update packages/editor/src/components/post-actions/actions.js Co-authored-by: Dave Smith --- packages/editor/src/components/post-actions/actions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index ec2dbaf761daba..aa013c59a61fbe 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -37,7 +37,7 @@ export function usePostActions( { postType, onActionPerformed, context } ) { } ), hasFrontPageTemplate: !! templates?.find( ( template ) => - 'slug' in template && template.slug === 'front-page' + template?.slug === 'front-page' ), }; } From d96e90e614d502362cf6f61d721b49e7281a5247 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Wed, 20 Nov 2024 11:26:51 +0000 Subject: [PATCH 70/87] Update getEntityRecord key docs --- docs/reference-guides/data/data-core.md | 2 +- packages/core-data/README.md | 2 +- packages/core-data/src/selectors.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md index 474207aa20460f..199c29cd67dd2e 100644 --- a/docs/reference-guides/data/data-core.md +++ b/docs/reference-guides/data/data-core.md @@ -359,7 +359,7 @@ _Parameters_ - _state_ `State`: State tree - _kind_ `string`: Entity kind. - _name_ `string`: Entity name. -- _key_ `EntityRecordKey`: Record's key +- _key_ `EntityRecordKey`: Optional record's key. If requesting a global record (e.g. site settings), the key can be omitted. If requesting a specific item, the key must always be included. - _query_ `GetRecordsHttpQuery`: Optional query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available "Retrieve a [Entity kind]". _Returns_ diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 079f95ddbfc7a6..b2144f1d9594dc 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -581,7 +581,7 @@ _Parameters_ - _state_ `State`: State tree - _kind_ `string`: Entity kind. - _name_ `string`: Entity name. -- _key_ `EntityRecordKey`: Record's key +- _key_ `EntityRecordKey`: Optional record's key. If requesting a global record (e.g. site settings), the key can be omitted. If requesting a specific item, the key must always be included. - _query_ `GetRecordsHttpQuery`: Optional query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available "Retrieve a [Entity kind]". _Returns_ diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index 1d745cbde698cb..7f4b0d38846468 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -335,7 +335,7 @@ export interface GetEntityRecord { * @param state State tree * @param kind Entity kind. * @param name Entity name. - * @param key Record's key + * @param key Optional record's key. If requesting a global record (e.g. site settings), the key can be omitted. If requesting a specific item, the key must always be included. * @param query Optional query. If requesting specific * fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available "Retrieve a [Entity kind]". * From 9685c3a7e877a5d3f408d4ec03004376154b192f Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Wed, 20 Nov 2024 11:31:37 +0000 Subject: [PATCH 71/87] Refactor fetching currentHomePage --- .../post-actions/set-as-homepage.js | 31 +++++++------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index e3c8b4b4425578..edf3097e171e22 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -2,14 +2,14 @@ * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { useEffect, useMemo, useState } from '@wordpress/element'; +import { useMemo } from '@wordpress/element'; import { Button, __experimentalText as Text, __experimentalHStack as HStack, __experimentalVStack as VStack, } from '@wordpress/components'; -import { useDispatch, useSelect, resolveSelect } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { store as noticesStore } from '@wordpress/notices'; @@ -17,42 +17,33 @@ import { store as noticesStore } from '@wordpress/notices'; * Internal dependencies */ import { getItemTitle } from '../../utils/get-item-title'; -import { unlock } from '../../lock-unlock'; const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { const [ item ] = items; const pageTitle = getItemTitle( item ); const { showOnFront, currentHomePage } = useSelect( ( select ) => { const { getEntityRecord } = select( coreStore ); - const { getHomePage } = unlock( select( coreStore ) ); const siteSettings = getEntityRecord( 'root', 'site' ); - const homePage = getHomePage(); + const currentHomePageItem = getEntityRecord( + 'postType', + 'page', + siteSettings?.page_on_front + ); return { showOnFront: siteSettings?.show_on_front, - currentHomePage: homePage.postId, + currentHomePage: currentHomePageItem, }; } ); - const [ currentHomePageTitle, setCurrentHomePageTitle ] = useState( '' ); const isPageDraft = item.status === 'draft'; + const currentHomePageTitle = currentHomePage + ? getItemTitle( currentHomePage ) + : ''; - const { getEntityRecord } = resolveSelect( coreStore ); const { saveEditedEntityRecord, saveEntityRecord } = useDispatch( coreStore ); const { createSuccessNotice, createErrorNotice } = useDispatch( noticesStore ); - useEffect( () => { - const handleGetCurrentHomepage = async () => { - const currentHomePageItem = await getEntityRecord( - 'postType', - 'page', - currentHomePage - ); - setCurrentHomePageTitle( getItemTitle( currentHomePageItem ) ); - }; - handleGetCurrentHomepage(); - }, [ currentHomePage, getEntityRecord ] ); - async function onSetPageAsHomepage( event ) { event.preventDefault(); From b0297944108936df021a72d80508d4272268caea Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Wed, 20 Nov 2024 11:55:31 +0000 Subject: [PATCH 72/87] Disable modal buttons if saving --- .../post-actions/set-as-homepage.js | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index edf3097e171e22..9204c0cb3e6726 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -21,19 +21,23 @@ import { getItemTitle } from '../../utils/get-item-title'; const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { const [ item ] = items; const pageTitle = getItemTitle( item ); - const { showOnFront, currentHomePage } = useSelect( ( select ) => { - const { getEntityRecord } = select( coreStore ); - const siteSettings = getEntityRecord( 'root', 'site' ); - const currentHomePageItem = getEntityRecord( - 'postType', - 'page', - siteSettings?.page_on_front - ); - return { - showOnFront: siteSettings?.show_on_front, - currentHomePage: currentHomePageItem, - }; - } ); + const { showOnFront, currentHomePage, isSavingSiteSettings } = useSelect( + ( select ) => { + const { getEntityRecord, isSavingEntityRecord } = + select( coreStore ); + const siteSettings = getEntityRecord( 'root', 'site' ); + const currentHomePageItem = getEntityRecord( + 'postType', + 'page', + siteSettings?.page_on_front + ); + return { + showOnFront: siteSettings?.show_on_front, + currentHomePage: currentHomePageItem, + isSavingSiteSettings: isSavingEntityRecord( 'root', 'site' ), + }; + } + ); const isPageDraft = item.status === 'draft'; const currentHomePageTitle = currentHomePage ? getItemTitle( currentHomePage ) @@ -134,6 +138,12 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { ); }; + // translators: Button label to confirm setting the specified page as the homepage. + let modalButtonLabel = __( 'Set homepage' ); + if ( isPageDraft ) { + modalButtonLabel = __( 'Publish and set homepage' ); + } + return (
@@ -145,6 +155,8 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { onClick={ () => { closeModal?.(); } } + disabled={ isSavingSiteSettings } + accessibleWhenDisabled > { __( 'Cancel' ) } @@ -152,13 +164,10 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { __next40pxDefaultSize variant="primary" type="submit" + disabled={ isSavingSiteSettings } + accessibleWhenDisabled > - { - // translators: Button to confirm setting the specified page as the homepage. - isPageDraft - ? __( 'Publish and set homepage' ) - : __( 'Set homepage' ) - } + { modalButtonLabel } From a9ea2686762c28a6dbdf2b470d9176a0aeba2672 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Wed, 20 Nov 2024 12:04:46 +0000 Subject: [PATCH 73/87] Store isPageDraft in useRef --- .../editor/src/components/post-actions/set-as-homepage.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index 9204c0cb3e6726..85efe0ab00b774 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { useMemo } from '@wordpress/element'; +import { useMemo, useRef } from '@wordpress/element'; import { Button, __experimentalText as Text, @@ -38,7 +38,8 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { }; } ); - const isPageDraft = item.status === 'draft'; + const isPageDraftRef = useRef( item.status === 'draft' ); + const isPageDraft = isPageDraftRef.current; const currentHomePageTitle = currentHomePage ? getItemTitle( currentHomePage ) : ''; From e438496b506d1008e80c36f78831cbcf4fadb749 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Wed, 20 Nov 2024 12:14:42 +0000 Subject: [PATCH 74/87] Fix lint error --- packages/editor/src/components/post-actions/actions.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index aa013c59a61fbe..ef4ee992a15610 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -36,8 +36,7 @@ export function usePostActions( { postType, onActionPerformed, context } ) { name: 'site', } ), hasFrontPageTemplate: !! templates?.find( - ( template ) => - template?.slug === 'front-page' + ( template ) => template?.slug === 'front-page' ), }; } From 04a7ba4fb68e4b584037fa9d0f5978fdbb3649e7 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Wed, 20 Nov 2024 12:16:25 +0000 Subject: [PATCH 75/87] Remove onActionPerformed --- .../editor/src/components/post-actions/set-as-homepage.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index 85efe0ab00b774..f47674a6254261 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -18,7 +18,7 @@ import { store as noticesStore } from '@wordpress/notices'; */ import { getItemTitle } from '../../utils/get-item-title'; -const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { +const SetAsHomepageModal = ( { items, closeModal } ) => { const [ item ] = items; const pageTitle = getItemTitle( item ); const { showOnFront, currentHomePage, isSavingSiteSettings } = useSelect( @@ -77,8 +77,6 @@ const SetAsHomepageModal = ( { items, closeModal, onActionPerformed } ) => { createSuccessNotice( __( 'Homepage updated' ), { type: 'snackbar', } ); - - onActionPerformed?.( items ); } catch ( error ) { const typedError = error; const errorMessage = From c97a17dbfb842ccc2b67d9b84a1b0b954a73d5d6 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Wed, 20 Nov 2024 12:51:58 +0000 Subject: [PATCH 76/87] Fix current homepage test --- test/e2e/specs/site-editor/homepage-settings.spec.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/e2e/specs/site-editor/homepage-settings.spec.js b/test/e2e/specs/site-editor/homepage-settings.spec.js index 92c4fd22e65409..aac2eafbc4392b 100644 --- a/test/e2e/specs/site-editor/homepage-settings.spec.js +++ b/test/e2e/specs/site-editor/homepage-settings.spec.js @@ -72,7 +72,7 @@ test.describe( 'Homepage Settings via Editor', () => { ).toBeVisible(); } ); - test.skip( 'should not show "Set as homepage" action on current homepage', async ( { + test( 'should not show "Set as homepage" action on current homepage', async ( { page, } ) => { const samplePage = page @@ -88,8 +88,9 @@ test.describe( 'Homepage Settings via Editor', () => { } ) .click(); await page.getByRole( 'menuitem', { name: 'Set as homepage' } ).click(); + await page.getByRole( 'button', { name: 'Set homepage' } ).click(); await expect( - page.getByRole( 'button', { name: 'Homepage updated' } ) - ).toBeVisible( { timeout: 10000 } ); + page.getByRole( 'menuitem', { name: 'Set as homepage' } ) + ).toBeHidden(); } ); } ); From 0b8c27ee475b62714b9e84a00efa00016880d109 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Thu, 21 Nov 2024 14:09:46 +0000 Subject: [PATCH 77/87] Remove duplicate getItemTitle function --- .../post-actions/set-as-homepage.js | 2 +- packages/editor/src/utils/get-item-title.js | 19 ------------------- 2 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 packages/editor/src/utils/get-item-title.js diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index f47674a6254261..6cd45e7c3cfe6e 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -16,7 +16,7 @@ import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies */ -import { getItemTitle } from '../../utils/get-item-title'; +import { getItemTitle } from '../../dataviews/actions/utils'; const SetAsHomepageModal = ( { items, closeModal } ) => { const [ item ] = items; diff --git a/packages/editor/src/utils/get-item-title.js b/packages/editor/src/utils/get-item-title.js deleted file mode 100644 index b98160cbde3dcc..00000000000000 --- a/packages/editor/src/utils/get-item-title.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * WordPress dependencies - */ -import { decodeEntities } from '@wordpress/html-entities'; - -// This function is copied from packages/editor/src/dataviews/actions/utils.ts. - -export function getItemTitle( item ) { - if ( typeof item.title === 'string' ) { - return decodeEntities( item.title ); - } - if ( item.title && 'rendered' in item.title ) { - return decodeEntities( item.title.rendered ); - } - if ( item.title && 'raw' in item.title ) { - return decodeEntities( item.title.raw ); - } - return ''; -} From a175adc9d98c99c3d6e1088ce73c926cdaf34ead Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 22 Nov 2024 16:24:05 +0000 Subject: [PATCH 78/87] Update logic for shouldShowSetAsHomepageAction --- packages/editor/src/components/post-actions/actions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index ef4ee992a15610..c44b4af279578c 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -44,7 +44,7 @@ export function usePostActions( { postType, onActionPerformed, context } ) { const setAsHomepageAction = useSetAsHomepageAction(); const shouldShowSetAsHomepageAction = - canManageOptions || ! hasFrontPageTemplate; + canManageOptions && ! hasFrontPageTemplate; const { registerPostTypeActions } = unlock( useDispatch( editorStore ) ); useEffect( () => { From 86af09abd2d5726caecaa69522c67fb16e4258b6 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 22 Nov 2024 16:26:09 +0000 Subject: [PATCH 79/87] Swap order of list of actions --- packages/editor/src/components/post-actions/actions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index c44b4af279578c..4b3bad6b355e1d 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -53,8 +53,8 @@ export function usePostActions( { postType, onActionPerformed, context } ) { return useMemo( () => { let actions = [ - shouldShowSetAsHomepageAction ? setAsHomepageAction : [], ...defaultActions, + shouldShowSetAsHomepageAction ? setAsHomepageAction : [], ]; // Filter actions based on provided context. If not provided // all actions are returned. We'll have a single entry for getting the actions From 10d97b7ae689d62a4e27e6e3ea6fc38f00328a82 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 22 Nov 2024 16:34:30 +0000 Subject: [PATCH 80/87] Add comment about manual saveEntityRecord call --- .../editor/src/components/post-actions/set-as-homepage.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index 6cd45e7c3cfe6e..9e04926387c259 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -62,14 +62,17 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { } // Save new home page settings. - await saveEntityRecord( 'root', 'site', { + await saveEditedEntityRecord( 'root', 'site', undefined, { page_on_front: item.id, show_on_front: 'page', } ); closeModal?.(); - await saveEditedEntityRecord( 'root', 'site', undefined, { + // This second call to a save function is a workaround for a bug in + // `saveEditedEntityRecord`. This forces the root site settings to be updated. + // See https://github.com/WordPress/gutenberg/issues/67161. + await saveEntityRecord( 'root', 'site', { page_on_front: item.id, show_on_front: 'page', } ); From c23c35b3245ecc8bc557b84f9e62979679f01e05 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 22 Nov 2024 16:36:22 +0000 Subject: [PATCH 81/87] Remove unnecessary space --- packages/editor/src/components/post-actions/set-as-homepage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index 9e04926387c259..d464bf17132141 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -135,7 +135,7 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { modalTranslatedString, pageTitle, currentHomePageTitle - ) }{ ' ' } + ) } ); }; From b1707e45a2fd33be67f957b43dda63e79b872ae4 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 22 Nov 2024 16:37:20 +0000 Subject: [PATCH 82/87] Remove temporary modalButtonLabel variable --- .../editor/src/components/post-actions/set-as-homepage.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index d464bf17132141..adadac6215a348 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -141,10 +141,9 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { }; // translators: Button label to confirm setting the specified page as the homepage. - let modalButtonLabel = __( 'Set homepage' ); - if ( isPageDraft ) { - modalButtonLabel = __( 'Publish and set homepage' ); - } + const modalButtonLabel = isPageDraft + ? __( 'Publish and set homepage' ) + : __( 'Set homepage' ); return ( From d6a7059bac5a378637a7d94e7efb489c421d30a6 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 22 Nov 2024 17:00:22 +0000 Subject: [PATCH 83/87] Combine draft and publish status tests --- .../specs/site-editor/homepage-settings.spec.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/test/e2e/specs/site-editor/homepage-settings.spec.js b/test/e2e/specs/site-editor/homepage-settings.spec.js index aac2eafbc4392b..2e415e6b3ce9b8 100644 --- a/test/e2e/specs/site-editor/homepage-settings.spec.js +++ b/test/e2e/specs/site-editor/homepage-settings.spec.js @@ -32,7 +32,7 @@ test.describe( 'Homepage Settings via Editor', () => { ] ); } ); - test( 'should show "Set as homepage" action on published pages', async ( { + test( 'should show "Set as homepage" action on pages in `draft` or `publish` statuses', async ( { page, } ) => { const samplePage = page @@ -41,7 +41,7 @@ test.describe( 'Homepage Settings via Editor', () => { const samplePageRow = page .getByRole( 'row' ) .filter( { has: samplePage } ); - await samplePageRow.click(); + await samplePageRow.hover(); await samplePageRow .getByRole( 'button', { name: 'Actions', @@ -50,18 +50,21 @@ test.describe( 'Homepage Settings via Editor', () => { await expect( page.getByRole( 'menuitem', { name: 'Set as homepage' } ) ).toBeVisible(); - } ); + await samplePageRow + .getByRole( 'button', { + name: 'Actions', + } ) + // Force click the actions button to close the menu. + // eslint-disable-next-line playwright/no-force-option + .click( { force: true } ); - test( 'should show "Set as homepage" action on draft pages', async ( { - page, - } ) => { const draftPage = page .getByRole( 'gridcell' ) .getByLabel( 'Draft page' ); const draftPageRow = page .getByRole( 'row' ) .filter( { has: draftPage } ); - await draftPageRow.click(); + await draftPageRow.hover(); await draftPageRow .getByRole( 'button', { name: 'Actions', From 6d01e3498c592325af89b577f5ce54f1b3c67c0e Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 25 Nov 2024 12:07:27 +0000 Subject: [PATCH 84/87] Only allow action on pages with draft or publish status --- packages/editor/src/components/post-actions/set-as-homepage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index adadac6215a348..8f7a090597ca20 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -191,7 +191,7 @@ export const useSetAsHomepageAction = () => { id: 'set-as-homepage', label: __( 'Set as homepage' ), isEligible( post ) { - if ( post.status === 'trash' ) { + if ( post.status !== 'draft' && post.status !== 'publish' ) { return false; } From 18aeaf6ab02c739e2ec50df1bf6f45bfe7cb1695 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 25 Nov 2024 17:08:12 +0000 Subject: [PATCH 85/87] Remove handling of draft pages --- .../post-actions/set-as-homepage.js | 45 ++++--------------- .../site-editor/homepage-settings.spec.js | 29 +----------- 2 files changed, 9 insertions(+), 65 deletions(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index 8f7a090597ca20..f3d53229cf35a0 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { useMemo, useRef } from '@wordpress/element'; +import { useMemo } from '@wordpress/element'; import { Button, __experimentalText as Text, @@ -21,7 +21,7 @@ import { getItemTitle } from '../../dataviews/actions/utils'; const SetAsHomepageModal = ( { items, closeModal } ) => { const [ item ] = items; const pageTitle = getItemTitle( item ); - const { showOnFront, currentHomePage, isSavingSiteSettings } = useSelect( + const { showOnFront, currentHomePage, isSaving } = useSelect( ( select ) => { const { getEntityRecord, isSavingEntityRecord } = select( coreStore ); @@ -34,12 +34,10 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { return { showOnFront: siteSettings?.show_on_front, currentHomePage: currentHomePageItem, - isSavingSiteSettings: isSavingEntityRecord( 'root', 'site' ), + isSaving: isSavingEntityRecord( 'root', 'site' ), }; } ); - const isPageDraftRef = useRef( item.status === 'draft' ); - const isPageDraft = isPageDraftRef.current; const currentHomePageTitle = currentHomePage ? getItemTitle( currentHomePage ) : ''; @@ -53,22 +51,12 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { event.preventDefault(); try { - // If selected page is set to draft, publish the page. - if ( isPageDraft ) { - await saveEntityRecord( 'postType', 'page', { - ...item, - status: 'publish', - } ); - } - // Save new home page settings. await saveEditedEntityRecord( 'root', 'site', undefined, { page_on_front: item.id, show_on_front: 'page', } ); - closeModal?.(); - // This second call to a save function is a workaround for a bug in // `saveEditedEntityRecord`. This forces the root site settings to be updated. // See https://github.com/WordPress/gutenberg/issues/67161. @@ -77,6 +65,7 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { show_on_front: 'page', } ); + closeModal?.(); createSuccessNotice( __( 'Homepage updated' ), { type: 'snackbar', } ); @@ -107,22 +96,6 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { ); } - if ( isPageDraft ) { - return ( - <> - - { sprintf( - // translators: %s: title of the page to be set as the homepage. - __( - '"%s" is a draft and will be published automatically if set as the homepage. Publish page and set as the site homepage?' - ), - pageTitle - ) } - - - ); - } - const modalTranslatedString = // translators: %1$s: title of page to be set as the home page. %2$s: title of the current home page. __( @@ -141,9 +114,7 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { }; // translators: Button label to confirm setting the specified page as the homepage. - const modalButtonLabel = isPageDraft - ? __( 'Publish and set homepage' ) - : __( 'Set homepage' ); + const modalButtonLabel = __( 'Set homepage' ); return ( @@ -156,7 +127,7 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { onClick={ () => { closeModal?.(); } } - disabled={ isSavingSiteSettings } + disabled={ isSaving } accessibleWhenDisabled > { __( 'Cancel' ) } @@ -165,7 +136,7 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { __next40pxDefaultSize variant="primary" type="submit" - disabled={ isSavingSiteSettings } + disabled={ isSaving } accessibleWhenDisabled > { modalButtonLabel } @@ -191,7 +162,7 @@ export const useSetAsHomepageAction = () => { id: 'set-as-homepage', label: __( 'Set as homepage' ), isEligible( post ) { - if ( post.status !== 'draft' && post.status !== 'publish' ) { + if ( post.status !== 'publish' ) { return false; } diff --git a/test/e2e/specs/site-editor/homepage-settings.spec.js b/test/e2e/specs/site-editor/homepage-settings.spec.js index 2e415e6b3ce9b8..d53130af23ac8b 100644 --- a/test/e2e/specs/site-editor/homepage-settings.spec.js +++ b/test/e2e/specs/site-editor/homepage-settings.spec.js @@ -10,10 +10,6 @@ test.describe( 'Homepage Settings via Editor', () => { title: 'Homepage', status: 'publish', } ); - await requestUtils.createPage( { - title: 'Draft page', - status: 'draft', - } ); } ); test.beforeEach( async ( { admin, page } ) => { @@ -32,7 +28,7 @@ test.describe( 'Homepage Settings via Editor', () => { ] ); } ); - test( 'should show "Set as homepage" action on pages in `draft` or `publish` statuses', async ( { + test( 'should show "Set as homepage" action on pages with `publish` status', async ( { page, } ) => { const samplePage = page @@ -50,29 +46,6 @@ test.describe( 'Homepage Settings via Editor', () => { await expect( page.getByRole( 'menuitem', { name: 'Set as homepage' } ) ).toBeVisible(); - await samplePageRow - .getByRole( 'button', { - name: 'Actions', - } ) - // Force click the actions button to close the menu. - // eslint-disable-next-line playwright/no-force-option - .click( { force: true } ); - - const draftPage = page - .getByRole( 'gridcell' ) - .getByLabel( 'Draft page' ); - const draftPageRow = page - .getByRole( 'row' ) - .filter( { has: draftPage } ); - await draftPageRow.hover(); - await draftPageRow - .getByRole( 'button', { - name: 'Actions', - } ) - .click(); - await expect( - page.getByRole( 'menuitem', { name: 'Set as homepage' } ) - ).toBeVisible(); } ); test( 'should not show "Set as homepage" action on current homepage', async ( { From 8bacdbb1353c26ea2d7e89b2d4637ea1574d60bd Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Wed, 27 Nov 2024 15:39:26 +0000 Subject: [PATCH 86/87] Move closeModal into finally block --- packages/editor/src/components/post-actions/set-as-homepage.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index f3d53229cf35a0..ad479b8f40dec9 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -65,7 +65,6 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { show_on_front: 'page', } ); - closeModal?.(); createSuccessNotice( __( 'Homepage updated' ), { type: 'snackbar', } ); @@ -76,6 +75,8 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { ? typedError.message : __( 'An error occurred while setting the homepage' ); createErrorNotice( errorMessage, { type: 'snackbar' } ); + } finally { + closeModal?.(); } } From e1a7aa9400f904dd6cde80bb08615d73d2c51bdc Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Wed, 27 Nov 2024 16:08:01 +0000 Subject: [PATCH 87/87] Refactor and remove renderModalBody --- .../post-actions/set-as-homepage.js | 50 +++++++------------ 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/packages/editor/src/components/post-actions/set-as-homepage.js b/packages/editor/src/components/post-actions/set-as-homepage.js index ad479b8f40dec9..0366a52482f2a8 100644 --- a/packages/editor/src/components/post-actions/set-as-homepage.js +++ b/packages/editor/src/components/post-actions/set-as-homepage.js @@ -80,39 +80,23 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { } } - const renderModalBody = () => { - if ( 'posts' === showOnFront ) { - return ( - <> - - { sprintf( - // translators: %s: title of the page to be set as the homepage. - __( - 'Set "%s" as the site homepage? This will replace the current homepage which is set to display latest posts.' - ), - pageTitle - ) } - - - ); - } - - const modalTranslatedString = - // translators: %1$s: title of page to be set as the home page. %2$s: title of the current home page. - __( - 'Set "%1$s" as the site homepage? This will replace the current homepage: "%2$s"' - ); - - return ( - - { sprintf( - modalTranslatedString, - pageTitle, + const modalWarning = + 'posts' === showOnFront + ? __( + 'This will replace the current homepage which is set to display latest posts.' + ) + : sprintf( + // translators: %s: title of the current home page. + __( 'This will replace the current homepage: "%s"' ), currentHomePageTitle - ) } - - ); - }; + ); + + const modalText = sprintf( + // translators: %1$s: title of the page to be set as the homepage, %2$s: homepage replacement warning message. + __( 'Set "%1$s" as the site homepage? %2$s' ), + pageTitle, + modalWarning + ); // translators: Button label to confirm setting the specified page as the homepage. const modalButtonLabel = __( 'Set homepage' ); @@ -120,7 +104,7 @@ const SetAsHomepageModal = ( { items, closeModal } ) => { return ( - { renderModalBody() } + { modalText }