-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Patterns: add option to set sync status when adding from wp-admin patterns list #52352
Changes from 4 commits
929dee0
4d9d97a
670079a
81ddf49
46b3c29
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,127 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useSelect } from '@wordpress/data'; | ||
import { useSelect, useDispatch } from '@wordpress/data'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { PanelRow } from '@wordpress/components'; | ||
import { | ||
PanelRow, | ||
Modal, | ||
Button, | ||
__experimentalHStack as HStack, | ||
__experimentalVStack as VStack, | ||
ToggleControl, | ||
} from '@wordpress/components'; | ||
import { useEffect, useState } from '@wordpress/element'; | ||
import { ReusableBlocksRenameHint } from '@wordpress/block-editor'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { store as editorStore } from '../../store'; | ||
|
||
export default function PostSyncStatus() { | ||
const { syncStatus, postType } = useSelect( ( select ) => { | ||
const { syncStatus, postType, meta } = useSelect( ( select ) => { | ||
const { getEditedPostAttribute } = select( editorStore ); | ||
return { | ||
syncStatus: getEditedPostAttribute( 'wp_pattern_sync_status' ), | ||
meta: getEditedPostAttribute( 'meta' ), | ||
postType: getEditedPostAttribute( 'type' ), | ||
}; | ||
}, [] ); | ||
} ); | ||
|
||
if ( postType !== 'wp_block' ) { | ||
return null; | ||
} | ||
|
||
const isFullySynced = ! syncStatus; | ||
// When the post is first created, the top level wp_pattern_sync_status is not set so get meta value instead. | ||
const currentSyncStatus = | ||
meta.wp_pattern_sync_status === 'unsynced' ? 'unsynced' : syncStatus; | ||
ramonjd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return ( | ||
<PanelRow className="edit-post-sync-status"> | ||
<span>{ __( 'Sync status' ) }</span> | ||
<div> | ||
{ isFullySynced ? __( 'Fully synced' ) : __( 'Not synced' ) } | ||
{ currentSyncStatus === 'unsynced' | ||
? __( 'Not synced' ) | ||
: __( 'Fully synced' ) } | ||
</div> | ||
</PanelRow> | ||
); | ||
} | ||
|
||
export function PostSyncStatusModal() { | ||
const { editPost } = useDispatch( editorStore ); | ||
const [ isModalOpen, setIsModalOpen ] = useState( false ); | ||
const [ syncType, setSyncType ] = useState( undefined ); | ||
|
||
const { postType, isNewPost } = useSelect( ( select ) => { | ||
const { getEditedPostAttribute, isCleanNewPost } = | ||
select( editorStore ); | ||
return { | ||
postType: getEditedPostAttribute( 'type' ), | ||
isNewPost: isCleanNewPost(), | ||
}; | ||
}, [] ); | ||
|
||
useEffect( () => { | ||
if ( isNewPost && postType === 'wp_block' ) { | ||
setIsModalOpen( true ); | ||
} | ||
// We only want the modal to open when the page is first loaded. | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [] ); | ||
|
||
const setSyncStatus = () => { | ||
editPost( { | ||
meta: { | ||
wp_pattern_sync_status: syncType, | ||
}, | ||
} ); | ||
}; | ||
|
||
if ( postType !== 'wp_block' || ! isNewPost ) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<> | ||
{ isModalOpen && ( | ||
<Modal | ||
title={ __( 'Set pattern sync status' ) } | ||
onRequestClose={ () => { | ||
setIsModalOpen( false ); | ||
} } | ||
overlayClassName="reusable-blocks-menu-items__convert-modal" | ||
> | ||
<form | ||
onSubmit={ ( event ) => { | ||
event.preventDefault(); | ||
setIsModalOpen( false ); | ||
setSyncStatus(); | ||
} } | ||
> | ||
<VStack spacing="5"> | ||
<ReusableBlocksRenameHint /> | ||
<ToggleControl | ||
label={ __( 'Synced' ) } | ||
help={ __( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe change the help text to match the state depending on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to @SaxonF the toggle control standard is to always/only show the positive state help text There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair enough, makes sense 👍🏻 I guess it can be seen as a checkbox in that regard. Cheers! |
||
'Editing the pattern will update it anywhere it is used.' | ||
) } | ||
checked={ ! syncType } | ||
onChange={ () => { | ||
setSyncType( | ||
! syncType ? 'unsynced' : undefined | ||
); | ||
} } | ||
/> | ||
<HStack justify="right"> | ||
<Button variant="primary" type="submit"> | ||
{ __( 'Create' ) } | ||
</Button> | ||
</HStack> | ||
</VStack> | ||
</form> | ||
</Modal> | ||
) } | ||
</> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is
meta
always an object? Just wondering if we need optional chaining here... feel free to ignore if it is always an object! 🙂There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In all my testing the entity always seems to have
meta
set as an object, even if it doesn't have any postmeta fields configured.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent. Thanks for confirming!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, to be 100% correct after double checking, sometimes it is actually an empty array, in which case it still won't fail with an undefined error as never seems to be undefined so I don't think optional chaining is needed - but let me know if you have any concerns about that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated to
meta?.wp_pattern_sync_status === 'unsynced' ? 'unsynced' : syncStatus
Can't hurt, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Probably good to be on the safe side if a call to a selector doesn't necessarily guarantee that an object is returned. From a quick look up from
getEditedPostAttribute
, it winds up callinggetCurrentPostAttribute
, which internally callsgetCurrentPost
. If for some reasongetCurrentPost
returns its default empty object, thengetCurrentPostAttribute
could potentially return undefined around these lines:gutenberg/packages/editor/src/store/selectors.js
Lines 280 to 283 in 81ddf49
In practice, I doubt that'll ever be hit because (in theory) there'll always be a post object of some kind around, but this hardens the logic a little.
Cheers! 🍻
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice digging! We just might thank ourselves later 😄