/** * WordPress dependencies */ import { Button, CheckboxControl, Dropdown, __experimentalVStack as VStack, TextControl, RadioControl, Icon, } from '@safe-wordpress/components'; import * as Icons from '@safe-wordpress/icons'; import { __, sprintf } from '@safe-wordpress/i18n'; import { useDispatch, useSelect } from '@safe-wordpress/data'; import { useState, useMemo } from '@safe-wordpress/element'; import { store as coreStore } from '@safe-wordpress/core-data'; import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@safe-wordpress/block-editor'; import { useInstanceId } from '@safe-wordpress/compose'; import { TEMPLATE_POST_TYPE, TEMPLATE_PART_POST_TYPE, PATTERN_POST_TYPE, NAVIGATION_POST_TYPE, store as editorStore, PostPanelRow, PostSticky, PrivatePostSchedule, } from '@safe-wordpress/editor'; type IconKey = keyof typeof Icons; /** * External dependencies */ import clsx from 'clsx'; import { filter, keyBy, map } from 'lodash'; import { PostId, PostTypeName } from '@nelio-content/types'; import { store as NC_DATA } from '@nelio-content/data'; import { EMPTY_ARRAY } from '@nelio-content/constants'; const DESIGN_POST_TYPES = [ TEMPLATE_POST_TYPE, TEMPLATE_PART_POST_TYPE, PATTERN_POST_TYPE, NAVIGATION_POST_TYPE, ]; export default function ExtendedPostStatus(): JSX.Element | null { const { allStatuses, canPublishPost, date, isUserSubscribed, password, postId, postType, } = useSelect( ( select ) => { const { getEditedPostAttribute, getCurrentPostId, getCurrentPostType } = select( editorStore ); const { canCurrentUserPublishPost, getPost, getPostStatuses, isSubscribed, } = select( NC_DATA ); const currentPostId = getCurrentPostId(); const currentPostType = getCurrentPostType(); const post = currentPostId !== null ? getPost( currentPostId as PostId ) : undefined; return { allStatuses: getPostStatuses( currentPostType as PostTypeName ) || EMPTY_ARRAY, canPublishPost: canCurrentUserPublishPost( post ), status: getEditedPostAttribute( 'status' ) as string, date: getEditedPostAttribute( 'date' ) as string | null, password: getEditedPostAttribute( 'password' ) as string, isUserSubscribed: isSubscribed(), postId: currentPostId, postType: currentPostType, }; }, [] ); const [ showPassword, setShowPassword ] = useState( !! password ); const passwordInputId = useInstanceId( ExtendedPostStatus, 'editor-change-status__password-input' ); const { editEntityRecord } = useDispatch( coreStore ); const popoverProps = useMemo( () => ( { anchor: document .querySelector( '.editor-post-status' ) ?.closest( '.editor-post-panel__row' ), 'aria-label': __( 'Status & visibility' ), headerTitle: __( 'Status & visibility' ), placement: 'left-start', offset: 36, shift: true, } ), [] ); if ( DESIGN_POST_TYPES.includes( postType ) ) { return null; } const validStatuses = filter( allStatuses, ( { slug } ) => ! [ 'nelio-content-unscheduled', 'trash' ].includes( slug ) ); const statuses = map( validStatuses, ( { slug, name, core, description, available, icon, flags = [], } ) => ( { value: slug, label: name, description, icon, core, disabled: ! available || flags.includes( 'disabled-in-editor' ) || ( slug === 'future' && ! canPublishPost ), } ) ).filter( ( s ) => ! s.disabled ); if ( statuses.every( ( s ) => s.core ) ) { return null; } if ( ! isUserSubscribed ) { return null; } const updatePost = ( { status: newStatus = status, password: newPassword = password, date: newDate = date, } ) => { void editEntityRecord( 'postType', postType, postId ?? '', { status: newStatus, date: newDate, password: newPassword, } ); }; const handleTogglePassword = ( value: boolean ) => { setShowPassword( value ); if ( ! value ) { updatePost( { password: '' } ); } }; const handleStatus = ( value: string ) => { let newDate: string | null = date; let newPassword = password; if ( status === 'future' && date && new Date( date ) > new Date() ) { newDate = null; } if ( value === 'private' && password ) { newPassword = ''; } updatePost( { status: value, date: newDate, password: newPassword, } ); }; const postStatusesInfo: Record< string, { label: string; icon?: JSX.Element } > = keyBy( map( statuses, ( { value, label, icon } ) => ( { value, label, icon: icon ? ( )[ icon as IconKey ] ?? Icons.swatch } /> ) : undefined, } ) ), 'value' ); const STATUS_OPTIONS = statuses.map( ( { value, label, description } ) => ( { value, label, description, } ) ); return ( ( ) } renderContent={ ( { onClose } ) => ( <>
{ event.preventDefault(); onClose(); } } > { status === 'future' && (
) } { status !== 'private' && ( { showPassword && (
updatePost( { password: value, } ) } value={ password } placeholder={ __( 'Use a secure password' ) } type="text" id={ passwordInputId } maxLength={ 255 } />
) }
) }
) } />
); } // ================= // HELPER COMPONENTS // ================= // This only loads the style that hides the default editor post status panel // if the ExtendedPostStatus is rendered. const CustomStyle = () => ( );