Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions packages/e2e-tests/specs/editor/various/datepicker.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,13 @@ function trimLeadingZero( str ) {
return str[ 0 ] === '0' ? str.slice( 1 ) : str;
}

function formatDatePickerValues( {
year,
monthLabel,
day,
hours,
minutes,
amOrPm,
} ) {
function formatDatePickerValues(
{ year, monthLabel, day, hours, minutes, amOrPm },
timezone
) {
const dayTrimmed = trimLeadingZero( day );
const hoursTrimmed = trimLeadingZero( hours );
return `${ monthLabel } ${ dayTrimmed }, ${ year } ${ hoursTrimmed }:${ minutes } ${ amOrPm }`;
return `${ monthLabel } ${ dayTrimmed }, ${ year } ${ hoursTrimmed }:${ minutes }\xa0${ amOrPm } ${ timezone }`;
}

async function getPublishingDate() {
Expand All @@ -70,11 +66,13 @@ describe.each( [ [ 'UTC-10' ], [ 'UTC' ], [ 'UTC+10' ] ] )(
( timezone ) => {
let oldTimezone;
beforeEach( async () => {
await page.emulateTimezone( 'America/New_York' ); // Set browser to a timezone that's different to `timezone`.
oldTimezone = await changeSiteTimezone( timezone );
await createNewPost();
} );
afterEach( async () => {
await changeSiteTimezone( oldTimezone );
await page.emulateTimezone( null );
} );

it( 'should show the publishing date as "Immediately" if the date is not altered', async () => {
Expand All @@ -98,7 +96,7 @@ describe.each( [ [ 'UTC-10' ], [ 'UTC' ], [ 'UTC+10' ] ] )(
const publishingDate = await getPublishingDate();

expect( publishingDate ).toBe(
formatDatePickerValues( datePickerValues )
formatDatePickerValues( datePickerValues, timezone )
);
} );

Expand All @@ -119,7 +117,7 @@ describe.each( [ [ 'UTC-10' ], [ 'UTC' ], [ 'UTC+10' ] ] )(
expect( publishingDate ).not.toEqual( 'Immediately' );
// The expected date format will be "Sep 26, 2018 11:52 pm".
expect( publishingDate ).toBe(
formatDatePickerValues( datePickerValues )
formatDatePickerValues( datePickerValues, timezone )
);
} );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ import {
PostSchedule as PostScheduleForm,
PostScheduleLabel,
PostScheduleCheck,
usePostScheduleLabel,
} from '@wordpress/editor';

export function PostSchedule() {
export default function PostSchedule() {
const anchorRef = useRef();

const fullLabel = usePostScheduleLabel( { full: true } );

return (
<PostScheduleCheck>
<PanelRow className="edit-post-post-schedule" ref={ anchorRef }>
Expand All @@ -28,6 +31,7 @@ export function PostSchedule() {
onClick={ onToggle }
aria-expanded={ isOpen }
variant="tertiary"
label={ fullLabel }
>
<PostScheduleLabel />
</Button>
Expand All @@ -41,5 +45,3 @@ export function PostSchedule() {
</PostScheduleCheck>
);
}

export default PostSchedule;
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,30 @@
width: 100%;
position: relative;
justify-content: flex-start;
align-items: flex-start;

span {
display: block;
width: 45%;
flex-shrink: 0;
padding: 6px 0;
}
}

.components-button.edit-post-post-schedule__toggle {
text-align: right;
text-align: left;
white-space: normal;
height: auto;

// This span is added by the Popover in Tooltip when no anchorRef is
// provided. We set its width to 0 so that it does not cause the button text
// to wrap to a new line when displaying the tooltip. A better fix would be
// to pass anchorRef and avoid the need for a span alltogether, which is
// what this PR allows us to do:
// https://github.com/WordPress/gutenberg/pull/41268.
span {
width: 0;
}
}

.edit-post-post-schedule__dialog .components-popover__content {
Expand Down
5 changes: 4 additions & 1 deletion packages/editor/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ export { default as PostPublishPanel } from './post-publish-panel';
export { default as PostSavedState } from './post-saved-state';
export { default as PostSchedule } from './post-schedule';
export { default as PostScheduleCheck } from './post-schedule/check';
export { default as PostScheduleLabel } from './post-schedule/label';
export {
default as PostScheduleLabel,
usePostScheduleLabel,
} from './post-schedule/label';
export { default as PostSlug } from './post-slug';
export { default as PostSlugCheck } from './post-slug/check';
export { default as PostSticky } from './post-sticky';
Expand Down
128 changes: 111 additions & 17 deletions packages/editor/src/components/post-schedule/label.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,122 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { format, __experimentalGetSettings } from '@wordpress/date';
import { withSelect } from '@wordpress/data';
import { __, _x, sprintf, isRTL } from '@wordpress/i18n';
import { __experimentalGetSettings, getDate, dateI18n } from '@wordpress/date';
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import { store as editorStore } from '../../store';

export function PostScheduleLabel( { date, isFloating } ) {
const settings = __experimentalGetSettings();
return date && ! isFloating
? format(
`${ settings.formats.date } ${ settings.formats.time }`,
date
)
: __( 'Immediately' );
export default function PostScheduleLabel( props ) {
return usePostScheduleLabel( props );
}

export default withSelect( ( select ) => {
return {
date: select( editorStore ).getEditedPostAttribute( 'date' ),
isFloating: select( editorStore ).isEditedPostDateFloating(),
};
} )( PostScheduleLabel );
export function usePostScheduleLabel( { full } ) {
const { date, isFloating } = useSelect(
( select ) => ( {
date: select( editorStore ).getEditedPostAttribute( 'date' ),
isFloating: select( editorStore ).isEditedPostDateFloating(),
} ),
[]
);

return full
? getFullPostScheduleLabel( date )
: getPostScheduleLabel( date, { isFloating } );
}

export function getFullPostScheduleLabel( dateAttribute ) {
const date = getDate( dateAttribute );

const timezoneAbbreviation = getTimezoneAbbreviation();
const formattedDate = dateI18n(
// translators: If using a space between 'g:i' and 'a', use a non-breaking sapce.
_x( 'F j, Y g:i\xa0a', 'post schedule full date format' ),
date
);
return isRTL()
? `${ timezoneAbbreviation } ${ formattedDate }`
: `${ formattedDate } ${ timezoneAbbreviation }`;
}

export function getPostScheduleLabel(
dateAttribute,
{ isFloating = false, now = new Date() } = {}
) {
if ( ! dateAttribute || isFloating ) {
return __( 'Immediately' );
}

// If the user timezone does not equal the site timezone then using words
// like 'tomorrow' is confusing, so show the full date.
if ( ! isTimezoneSameAsSiteTimezone( now ) ) {
return getFullPostScheduleLabel( dateAttribute );
}

const date = getDate( dateAttribute );

if ( isSameDay( date, now ) ) {
return sprintf(
// translators: %s: Time of day the post is scheduled for.
__( 'Today at %s' ),
// translators: If using a space between 'g:i' and 'a', use a non-breaking sapce.
dateI18n( _x( 'g:i\xa0a', 'post schedule time format' ), date )
);
}

const tomorrow = new Date( now );
tomorrow.setDate( tomorrow.getDate() + 1 );

if ( isSameDay( date, tomorrow ) ) {
return sprintf(
// translators: %s: Time of day the post is scheduled for.
__( 'Tomorrow at %s' ),
// translators: If using a space between 'g:i' and 'a', use a non-breaking sapce.
dateI18n( _x( 'g:i\xa0a', 'post schedule time format' ), date )
);
}

if ( date.getFullYear() === now.getFullYear() ) {
return dateI18n(
// translators: If using a space between 'g:i' and 'a', use a non-breaking sapce.
_x( 'F j g:i\xa0a', 'post schedule date format without year' ),
date
);
}

return dateI18n(
// translators: Use a non-breaking space between 'g:i' and 'a' if appropriate.
_x( 'F j, Y g:i\xa0a', 'post schedule full date format' ),
date
);
}

function getTimezoneAbbreviation() {
const { timezone } = __experimentalGetSettings();

if ( timezone.abbr && isNaN( Number( timezone.abbr ) ) ) {
return timezone.abbr;
}

const symbol = timezone.offset < 0 ? '' : '+';
return `UTC${ symbol }${ timezone.offset }`;
}

function isTimezoneSameAsSiteTimezone( date ) {
const { timezone } = __experimentalGetSettings();

const siteOffset = Number( timezone.offset );
const dateOffset = -1 * ( date.getTimezoneOffset() / 60 );
return siteOffset === dateOffset;
}

function isSameDay( left, right ) {
return (
left.getDate() === right.getDate() &&
left.getMonth() === right.getMonth() &&
left.getFullYear() === right.getFullYear()
);
}
Loading