Skip to content

Commit

Permalink
Try/publish in site editor (WordPress#51408)
Browse files Browse the repository at this point in the history
* add required inputs

* schedule date

* add password and fix a few things

* re-add status modal

* update change status modal

* revert in sidebar status change

* refine a few status details

* fix merge issues

* fix status label

* use null for status date

* handle empty date

* change to add fields instead of modal

* default publish not draft

* remove style import

* add required inputs

* schedule date

* add password and fix a few things

* re-add status modal

* update change status modal

* revert in sidebar status change

* refine a few status details

* fix merge issues

* fix status label

* use null for status date

* handle empty date

* change to add fields instead of modal

* default publish not draft

* remove style import

* remove css

* only autofocus password field if empty

* aria label on status popover

* remove end line

* create radio with help component

* adjust to use radiocontrol and hide password

* radio label alignment

* add form wrapper

* aria label
  • Loading branch information
SaxonF authored and sethrubenstein committed Jul 13, 2023
1 parent d53a625 commit b33b0c3
Show file tree
Hide file tree
Showing 7 changed files with 465 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/**
* WordPress dependencies
*/
import { PanelBody } from '@wordpress/components';
import {
PanelBody,
__experimentalText as Text,
__experimentalVStack as VStack,
} from '@wordpress/components';
import { page as pageIcon } from '@wordpress/icons';
import { __, sprintf } from '@wordpress/i18n';
import { humanTimeDiff } from '@wordpress/date';
Expand All @@ -15,25 +19,32 @@ import { decodeEntities } from '@wordpress/html-entities';
import { store as editSiteStore } from '../../../store';
import SidebarCard from '../sidebar-card';
import PageContent from './page-content';
import PageSummary from './page-summary';
import EditTemplate from './edit-template';

export default function PagePanels() {
const { hasResolved, title, modified } = useSelect( ( select ) => {
const { getEditedPostContext } = select( editSiteStore );
const { getEditedEntityRecord, hasFinishedResolution } =
select( coreStore );
const context = getEditedPostContext();
const queryArgs = [ 'postType', context.postType, context.postId ];
const page = getEditedEntityRecord( ...queryArgs );
return {
hasResolved: hasFinishedResolution(
'getEditedEntityRecord',
queryArgs
),
title: page?.title,
modified: page?.modified,
};
}, [] );
const { id, type, hasResolved, status, date, password, title, modified } =
useSelect( ( select ) => {
const { getEditedPostContext } = select( editSiteStore );
const { getEditedEntityRecord, hasFinishedResolution } =
select( coreStore );
const context = getEditedPostContext();
const queryArgs = [ 'postType', context.postType, context.postId ];
const page = getEditedEntityRecord( ...queryArgs );
return {
hasResolved: hasFinishedResolution(
'getEditedEntityRecord',
queryArgs
),
title: page?.title,
id: page?.id,
type: page?.type,
status: page?.status,
date: page?.date,
password: page?.password,
modified: page?.modified,
};
}, [] );

if ( ! hasResolved ) {
return null;
Expand All @@ -45,11 +56,26 @@ export default function PagePanels() {
<SidebarCard
title={ decodeEntities( title ) }
icon={ pageIcon }
description={ sprintf(
// translators: %s: Human-readable time difference, e.g. "2 days ago".
__( 'Last edited %s' ),
humanTimeDiff( modified )
) }
description={
<VStack>
<Text>
{ sprintf(
// translators: %s: Human-readable time difference, e.g. "2 days ago".
__( 'Last edited %s' ),
humanTimeDiff( modified )
) }
</Text>
</VStack>
}
/>
</PanelBody>
<PanelBody title={ __( 'Summary' ) }>
<PageSummary
status={ status }
date={ date }
password={ password }
postId={ id }
postType={ type }
/>
</PanelBody>
<PanelBody title={ __( 'Content' ) }>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
/**
* WordPress dependencies
*/
import {
Button,
BaseControl,
ToggleControl,
Dropdown,
__experimentalText as Text,
__experimentalHStack as HStack,
__experimentalVStack as VStack,
TextControl,
RadioControl,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useDispatch } from '@wordpress/data';
import { useState, useMemo } from '@wordpress/element';
import { store as coreStore } from '@wordpress/core-data';
import { store as noticesStore } from '@wordpress/notices';
import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import StatusLabel from '../../sidebar-navigation-screen-page/status-label';

const STATUS_OPTIONS = [
{
label: (
<>
{ __( 'Draft' ) }
<Text variant="muted">{ __( 'Not ready to publish.' ) }</Text>
</>
),
value: 'draft',
},
{
label: (
<>
{ __( 'Pending' ) }
<Text variant="muted">
{ __( 'Waiting for review before publishing.' ) }
</Text>
</>
),
value: 'pending',
},
{
label: (
<>
{ __( 'Private' ) }
<Text variant="muted">
{ __( 'Only visible to site admins and editors.' ) }
</Text>
</>
),
value: 'private',
},
{
label: (
<>
{ __( 'Scheduled' ) }
<Text variant="muted">
{ __( 'Publish automatically on a chosen date.' ) }
</Text>
</>
),
value: 'future',
},
{
label: (
<>
{ __( 'Published' ) }
<Text variant="muted">{ __( 'Visible to everyone.' ) }</Text>
</>
),
value: 'publish',
},
];

export default function PageStatus( {
postType,
postId,
status,
password,
date,
} ) {
const [ showPassword, setShowPassword ] = useState( !! password );

const { editEntityRecord } = useDispatch( coreStore );
const { createErrorNotice } = useDispatch( noticesStore );

const [ popoverAnchor, setPopoverAnchor ] = useState( null );
// Memoize popoverProps to avoid returning a new object every time.
const popoverProps = useMemo(
() => ( {
// Anchor the popover to the middle of the entire row so that it doesn't
// move around when the label changes.
anchor: popoverAnchor,
'aria-label': __( 'Change status' ),
placement: 'bottom-end',
} ),
[ popoverAnchor ]
);

const saveStatus = async ( {
status: newStatus = status,
password: newPassword = password,
date: newDate = date,
} ) => {
try {
await editEntityRecord( 'postType', postType, postId, {
status: newStatus,
date: newDate,
password: newPassword,
} );
} catch ( error ) {
const errorMessage =
error.message && error.code !== 'unknown_error'
? error.message
: __( 'An error occurred while updating the status' );

createErrorNotice( errorMessage, {
type: 'snackbar',
} );
}
};

const handleTogglePassword = ( value ) => {
setShowPassword( value );
if ( ! value ) {
saveStatus( { password: '' } );
}
};

const handleStatus = ( value ) => {
let newDate = date;
let newPassword = password;
if ( value === 'publish' ) {
if ( new Date( date ) > new Date() ) {
newDate = null;
}
} else if ( value === 'future' ) {
if ( ! date || new Date( date ) < new Date() ) {
newDate = new Date();
newDate.setDate( newDate.getDate() + 7 );
}
} else if ( value === 'private' && password ) {
setShowPassword( false );
newPassword = '';
}
saveStatus( {
status: value,
date: newDate,
password: newPassword,
} );
};

return (
<HStack className="edit-site-summary-field">
<Text className="edit-site-summary-field__label">
{ __( 'Status' ) }
</Text>
<Dropdown
contentClassName="edit-site-change-status__content"
popoverProps={ popoverProps }
focusOnMount
ref={ setPopoverAnchor }
renderToggle={ ( { onToggle } ) => (
<Button
className="edit-site-summary-field__trigger"
variant="tertiary"
onClick={ onToggle }
>
<StatusLabel
status={ password ? 'protected' : status }
/>
</Button>
) }
renderContent={ ( { onClose } ) => (
<>
<InspectorPopoverHeader
title={ __( 'Status' ) }
onClose={ onClose }
/>
<form>
<VStack spacing={ 5 }>
<RadioControl
className="edit-site-change-status__options"
hideLabelFromVision
label={ __( 'Status' ) }
options={ STATUS_OPTIONS }
onChange={ handleStatus }
selected={ status }
/>
{ status !== 'private' && (
<BaseControl
id={ `edit-site-change-status__password` }
label={ __( 'Password' ) }
>
<ToggleControl
label={ __(
'Hide this page behind a password'
) }
checked={ showPassword }
onChange={ handleTogglePassword }
/>
{ showPassword && (
<TextControl
onChange={ ( value ) =>
saveStatus( {
password: value,
} )
}
value={ password }
/* eslint-disable jsx-a11y/no-autofocus */
autoFocus={ ! password }
/* eslint-enable jsx-a11y/no-autofocus */
placeholder={ __(
'Enter a secure password'
) }
type="password"
/>
) }
</BaseControl>
) }
</VStack>
</form>
</>
) }
/>
</HStack>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* WordPress dependencies
*/
import { __experimentalVStack as VStack } from '@wordpress/components';
/**
* Internal dependencies
*/
import PageStatus from './page-status';
import PublishDate from './publish-date';

export default function PageSummary( {
status,
date,
password,
postId,
postType,
} ) {
return (
<VStack>
<PageStatus
status={ status }
date={ date }
password={ password }
postId={ postId }
postType={ postType }
/>
<PublishDate
status={ status }
date={ date }
postId={ postId }
postType={ postType }
/>
</VStack>
);
}
Loading

0 comments on commit b33b0c3

Please sign in to comment.