From 62b3e050151bbdf795d004faad5a2b05b730693c Mon Sep 17 00:00:00 2001 From: retrofox Date: Tue, 9 Mar 2021 12:24:56 -0300 Subject: [PATCH 01/29] post-schedule: collect and pass calendar events --- .../src/components/post-schedule/index.js | 45 +++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/components/post-schedule/index.js b/packages/editor/src/components/post-schedule/index.js index 06266f1bd68d9..d1ddfce5274df 100644 --- a/packages/editor/src/components/post-schedule/index.js +++ b/packages/editor/src/components/post-schedule/index.js @@ -2,12 +2,48 @@ * WordPress dependencies */ import { __experimentalGetSettings } from '@wordpress/date'; -import { withSelect, withDispatch } from '@wordpress/data'; +import { withSelect, withDispatch, useSelect } from '@wordpress/data'; import { compose } from '@wordpress/compose'; import { DateTimePicker } from '@wordpress/components'; -import { useRef } from '@wordpress/element'; +import { useRef, useState } from '@wordpress/element'; +import { store as coreStore } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import { store as editorStore } from '../../store'; + +function getDayOfTheMonth( date = new Date(), firstDay = true ) { + const d = new Date( date ); + return new Date( + d.getFullYear(), + d.getMonth() + ( firstDay ? 0 : 1 ), + firstDay ? 1 : 0 + ).toISOString(); +} export function PostSchedule( { date, onUpdateDate } ) { + const [ currentMonth ] = useState( getDayOfTheMonth( date ) ); + + // Pick up published and schduled site posts. + const events = useSelect( + ( select ) => { + const posts = + select( editorStore ).getEntityRecords( 'postType', 'post', { + status: 'publish,future', + after: getDayOfTheMonth( currentMonth ), + before: getDayOfTheMonth( currentMonth, false ), + } ) || []; + + return posts.map( ( { title, type, postDate } ) => ( { + title: title?.raw, + type, + date: new Date( postDate ), + } ) ); + }, + [ currentMonth ] + ); + const ref = useRef(); const settings = __experimentalGetSettings(); // To know if the current timezone is a 12 hour time with look for "a" in the time format @@ -33,6 +69,7 @@ export function PostSchedule( { date, onUpdateDate } ) { currentDate={ date } onChange={ onChange } is12Hour={ is12HourTime } + events={ events } /> ); } @@ -40,13 +77,13 @@ export function PostSchedule( { date, onUpdateDate } ) { export default compose( [ withSelect( ( select ) => { return { - date: select( 'core/editor' ).getEditedPostAttribute( 'date' ), + date: select( coreStore ).getEditedPostAttribute( 'date' ), }; } ), withDispatch( ( dispatch ) => { return { onUpdateDate( date ) { - dispatch( 'core/editor' ).editPost( { date } ); + dispatch( coreStore ).editPost( { date } ); }, }; } ), From 3352cc2775a536afcce2040c059cc537f9b2d800 Mon Sep 17 00:00:00 2001 From: retrofox Date: Tue, 9 Mar 2021 12:45:19 -0300 Subject: [PATCH 02/29] post-schedule: re-write component using function --- .../src/components/post-schedule/index.js | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/packages/editor/src/components/post-schedule/index.js b/packages/editor/src/components/post-schedule/index.js index d1ddfce5274df..18929791d725c 100644 --- a/packages/editor/src/components/post-schedule/index.js +++ b/packages/editor/src/components/post-schedule/index.js @@ -2,8 +2,7 @@ * WordPress dependencies */ import { __experimentalGetSettings } from '@wordpress/date'; -import { withSelect, withDispatch, useSelect } from '@wordpress/data'; -import { compose } from '@wordpress/compose'; +import { useDispatch, useSelect } from '@wordpress/data'; import { DateTimePicker } from '@wordpress/components'; import { useRef, useState } from '@wordpress/element'; import { store as coreStore } from '@wordpress/core-data'; @@ -22,7 +21,15 @@ function getDayOfTheMonth( date = new Date(), firstDay = true ) { ).toISOString(); } -export function PostSchedule( { date, onUpdateDate } ) { +export default function PostSchedule() { + const date = useSelect( + ( select ) => select( coreStore ).getEditedPostAttribute( 'date' ), + [] + ); + + const { editPost } = useDispatch( coreStore ); + const onUpdateDate = ( postDate ) => editPost( { date: postDate } ); + const [ currentMonth ] = useState( getDayOfTheMonth( date ) ); // Pick up published and schduled site posts. @@ -46,6 +53,7 @@ export function PostSchedule( { date, onUpdateDate } ) { const ref = useRef(); const settings = __experimentalGetSettings(); + // To know if the current timezone is a 12 hour time with look for "a" in the time format // We also make sure this a is not escaped by a "/" const is12HourTime = /a(?!\\)/i.test( @@ -73,18 +81,3 @@ export function PostSchedule( { date, onUpdateDate } ) { /> ); } - -export default compose( [ - withSelect( ( select ) => { - return { - date: select( coreStore ).getEditedPostAttribute( 'date' ), - }; - } ), - withDispatch( ( dispatch ) => { - return { - onUpdateDate( date ) { - dispatch( coreStore ).editPost( { date } ); - }, - }; - } ), -] )( PostSchedule ); From c52270540ddfe055f4f4b4700ea76cffbc86c6e9 Mon Sep 17 00:00:00 2001 From: retrofox Date: Tue, 9 Mar 2021 15:56:02 -0300 Subject: [PATCH 03/29] date-time: remove onMonthPreviewed() and highlight --- packages/components/src/date-time/date.js | 18 ------------------ packages/components/src/date-time/index.js | 2 -- 2 files changed, 20 deletions(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 9f6ff3b269180..1943de4fd7d0a 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -24,7 +24,6 @@ class DatePicker extends Component { this.onChangeMoment = this.onChangeMoment.bind( this ); this.nodeRef = createRef(); this.keepFocusInside = this.keepFocusInside.bind( this ); - this.isDayHighlighted = this.isDayHighlighted.bind( this ); } /* @@ -89,22 +88,6 @@ class DatePicker extends Component { return currentDate ? moment( currentDate ) : moment(); } - // todo change reference to `isDayHighlighted` every time, `events` prop change - isDayHighlighted( date ) { - // Do not highlight when no events. - if ( ! this.props.events?.length ) { - return false; - } - if ( this.props.onMonthPreviewed ) { - this.props.onMonthPreviewed( date.toDate() ); - } - - // Compare date against highlighted events. - return this.props.events.some( ( highlighted ) => - date.isSame( highlighted.date, 'day' ) - ); - } - render() { const { currentDate, isInvalidDate } = this.props; const momentDate = this.getMomentDate( currentDate ); @@ -130,7 +113,6 @@ class DatePicker extends Component { isOutsideRange={ ( date ) => { return isInvalidDate && isInvalidDate( date.toDate() ); } } - isDayHighlighted={ this.isDayHighlighted } onPrevMonthClick={ this.keepFocusInside } onNextMonthClick={ this.keepFocusInside } /> diff --git a/packages/components/src/date-time/index.js b/packages/components/src/date-time/index.js index fecc9e302f29e..0df9fb131b53f 100644 --- a/packages/components/src/date-time/index.js +++ b/packages/components/src/date-time/index.js @@ -25,7 +25,6 @@ function DateTimePicker( currentDate, is12Hour, isInvalidDate, - onMonthPreviewed, onChange, events, }, @@ -52,7 +51,6 @@ function DateTimePicker( currentDate={ currentDate } onChange={ onChange } isInvalidDate={ isInvalidDate } - onMonthPreviewed={ onMonthPreviewed } events={ events } /> From ce24e97da51520b4f39e33cc127e12fd73deb16f Mon Sep 17 00:00:00 2001 From: retrofox Date: Tue, 9 Mar 2021 16:00:53 -0300 Subject: [PATCH 04/29] post-schedule: update current month --- packages/components/src/date-time/date.js | 4 +++- packages/components/src/date-time/index.js | 3 +++ packages/editor/src/components/post-schedule/index.js | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 1943de4fd7d0a..9cd760cae1e5e 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -32,7 +32,9 @@ class DatePicker extends Component { * This focus loss closes the date picker popover. * Ideally we should add an upstream commit on react-dates to fix this issue. */ - keepFocusInside() { + keepFocusInside( newMonthDate ) { + this.props?.onMonthChange( newMonthDate.toISOString() ); + if ( ! this.nodeRef.current ) { return; } diff --git a/packages/components/src/date-time/index.js b/packages/components/src/date-time/index.js index 0df9fb131b53f..e3c8e88e43cf7 100644 --- a/packages/components/src/date-time/index.js +++ b/packages/components/src/date-time/index.js @@ -4,6 +4,7 @@ // Needed to initialise the default datepicker styles. // See: https://github.com/airbnb/react-dates#initialize import 'react-dates/initialize'; +import { noop } from 'lodash'; /** * WordPress dependencies @@ -27,6 +28,7 @@ function DateTimePicker( isInvalidDate, onChange, events, + onMonthChange = noop, }, ref ) { @@ -52,6 +54,7 @@ function DateTimePicker( onChange={ onChange } isInvalidDate={ isInvalidDate } events={ events } + onMonthChange={ onMonthChange } /> ) } diff --git a/packages/editor/src/components/post-schedule/index.js b/packages/editor/src/components/post-schedule/index.js index 18929791d725c..602ac14f0c0c6 100644 --- a/packages/editor/src/components/post-schedule/index.js +++ b/packages/editor/src/components/post-schedule/index.js @@ -78,6 +78,7 @@ export default function PostSchedule() { onChange={ onChange } is12Hour={ is12HourTime } events={ events } + onMonthChange={ setCurrentMonth } /> ); } From 58047af4eb3a7d672bc40c2033a9d3b03ba8eac0 Mon Sep 17 00:00:00 2001 From: retrofox Date: Wed, 10 Mar 2021 08:47:49 -0300 Subject: [PATCH 05/29] date-time: render day events using own component --- packages/components/src/date-time/date.js | 24 ++++++++++++++++++++ packages/components/src/date-time/style.scss | 14 ++++++++++++ 2 files changed, 38 insertions(+) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 9cd760cae1e5e..21d6c30d634e6 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -2,6 +2,8 @@ * External dependencies */ import moment from 'moment'; +import classnames from 'classnames'; + // react-dates doesn't tree-shake correctly, so we import from the individual // component here, to avoid including too much of the library import DayPickerSingleDateController from 'react-dates/lib/components/DayPickerSingleDateController'; @@ -17,6 +19,16 @@ import { isRTL } from '@wordpress/i18n'; */ const TIMEZONELESS_FORMAT = 'YYYY-MM-DDTHH:mm:ss'; +function DatePickerDay( { day, events } ) { + return ( +
+ { day.format( 'D' ) } +
+ ); +} + class DatePicker extends Component { constructor() { super( ...arguments ); @@ -90,6 +102,12 @@ class DatePicker extends Component { return currentDate ? moment( currentDate ) : moment(); } + getEventsPerDay( day ) { + return this.props.events.filter( ( eventDay ) => + day.isSame( eventDay.date, 'day' ) + ); + } + render() { const { currentDate, isInvalidDate } = this.props; const momentDate = this.getMomentDate( currentDate ); @@ -117,6 +135,12 @@ class DatePicker extends Component { } } onPrevMonthClick={ this.keepFocusInside } onNextMonthClick={ this.keepFocusInside } + renderDayContents={ ( day ) => ( + + ) } /> ); diff --git a/packages/components/src/date-time/style.scss b/packages/components/src/date-time/style.scss index 7c56708e1fd32..484cbc95f1e9a 100644 --- a/packages/components/src/date-time/style.scss +++ b/packages/components/src/date-time/style.scss @@ -111,6 +111,20 @@ } } +.components-datetime__date__day { + height: 100%; + display: flex; + justify-content: center; + align-content: center; + flex-direction: column; + + &.has-events { + background: #ffe8bc; + color: #484848; + border-radius: 50%; + } +} + .components-datetime__time { padding-bottom: $grid-unit-20; From 378ca18e07ced2307a643ff9f2a61e148641f2ac Mon Sep 17 00:00:00 2001 From: retrofox Date: Wed, 10 Mar 2021 09:05:14 -0300 Subject: [PATCH 06/29] date-time: styling when not selected day --- packages/components/src/date-time/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/date-time/style.scss b/packages/components/src/date-time/style.scss index 484cbc95f1e9a..6846192983d65 100644 --- a/packages/components/src/date-time/style.scss +++ b/packages/components/src/date-time/style.scss @@ -111,7 +111,7 @@ } } -.components-datetime__date__day { +.components-datetime__date .CalendarDay:not(.CalendarDay__selected) .components-datetime__date__day { height: 100%; display: flex; justify-content: center; From 0908be5dccccd674572063e3260ac14769ffdb4d Mon Sep 17 00:00:00 2001 From: retrofox Date: Wed, 10 Mar 2021 10:16:41 -0300 Subject: [PATCH 07/29] fixing eslint issues --- packages/components/src/date-time/date.js | 8 +++++--- packages/editor/src/components/post-schedule/index.js | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 21d6c30d634e6..39c513300944e 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -21,9 +21,11 @@ const TIMEZONELESS_FORMAT = 'YYYY-MM-DDTHH:mm:ss'; function DatePickerDay( { day, events } ) { return ( -
+
{ day.format( 'D' ) }
); diff --git a/packages/editor/src/components/post-schedule/index.js b/packages/editor/src/components/post-schedule/index.js index 602ac14f0c0c6..4fa2800393b35 100644 --- a/packages/editor/src/components/post-schedule/index.js +++ b/packages/editor/src/components/post-schedule/index.js @@ -30,7 +30,9 @@ export default function PostSchedule() { const { editPost } = useDispatch( coreStore ); const onUpdateDate = ( postDate ) => editPost( { date: postDate } ); - const [ currentMonth ] = useState( getDayOfTheMonth( date ) ); + const [ currentMonth, setCurrentMonth ] = useState( + getDayOfTheMonth( date ) + ); // Pick up published and schduled site posts. const events = useSelect( From 3db4fb65a02d0a57ada1dace6cd56595c335b64d Mon Sep 17 00:00:00 2001 From: retrofox Date: Wed, 10 Mar 2021 10:41:46 -0300 Subject: [PATCH 08/29] date-time: tweak calendar events style --- packages/components/src/date-time/style.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/components/src/date-time/style.scss b/packages/components/src/date-time/style.scss index 6846192983d65..dc173c5061a20 100644 --- a/packages/components/src/date-time/style.scss +++ b/packages/components/src/date-time/style.scss @@ -119,8 +119,7 @@ flex-direction: column; &.has-events { - background: #ffe8bc; - color: #484848; + border: 2px solid $gray-400; border-radius: 50%; } } From ce1e4ed5b79bc864137efec1576a00cbdd811d08 Mon Sep 17 00:00:00 2001 From: retrofox Date: Wed, 10 Mar 2021 16:02:04 -0300 Subject: [PATCH 09/29] post-schedule: exlude current post from evenys --- .../editor/src/components/post-schedule/index.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/editor/src/components/post-schedule/index.js b/packages/editor/src/components/post-schedule/index.js index 4fa2800393b35..39722b65236bf 100644 --- a/packages/editor/src/components/post-schedule/index.js +++ b/packages/editor/src/components/post-schedule/index.js @@ -37,17 +37,19 @@ export default function PostSchedule() { // Pick up published and schduled site posts. const events = useSelect( ( select ) => { - const posts = - select( editorStore ).getEntityRecords( 'postType', 'post', { + const postId = select( editorStore ).getCurrentPostId(); + + return ( + select( coreStore ).getEntityRecords( 'postType', 'post', { status: 'publish,future', after: getDayOfTheMonth( currentMonth ), before: getDayOfTheMonth( currentMonth, false ), - } ) || []; - - return posts.map( ( { title, type, postDate } ) => ( { + exclude: [ postId ], + } ) || [] + ).map( ( { title, type, date: eventDate } ) => ( { title: title?.raw, type, - date: new Date( postDate ), + date: new Date( eventDate ), } ) ); }, [ currentMonth ] From d43f042bc7cfc1725af549f1068c20ad923dcb81 Mon Sep 17 00:00:00 2001 From: retrofox Date: Wed, 10 Mar 2021 18:16:05 -0300 Subject: [PATCH 10/29] date-time: decouple onMonthChange with keepFocusInside --- packages/components/src/date-time/date.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 39c513300944e..e1cc330050550 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -37,7 +37,12 @@ class DatePicker extends Component { this.onChangeMoment = this.onChangeMoment.bind( this ); this.nodeRef = createRef(); - this.keepFocusInside = this.keepFocusInside.bind( this ); + this.onMonthChangeHandler = this.onMonthChangeHandler.bind( this ); + } + + onMonthChangeHandler( newMonthDate ) { + this.props?.onMonthChange( newMonthDate.toISOString() ); + this.keepFocusInside(); } /* @@ -46,9 +51,7 @@ class DatePicker extends Component { * This focus loss closes the date picker popover. * Ideally we should add an upstream commit on react-dates to fix this issue. */ - keepFocusInside( newMonthDate ) { - this.props?.onMonthChange( newMonthDate.toISOString() ); - + keepFocusInside() { if ( ! this.nodeRef.current ) { return; } @@ -135,8 +138,8 @@ class DatePicker extends Component { isOutsideRange={ ( date ) => { return isInvalidDate && isInvalidDate( date.toDate() ); } } - onPrevMonthClick={ this.keepFocusInside } - onNextMonthClick={ this.keepFocusInside } + onPrevMonthClick={ this.onMonthChangeHandler } + onNextMonthClick={ this.onMonthChangeHandler } renderDayContents={ ( day ) => ( Date: Fri, 12 Mar 2021 15:31:20 -0300 Subject: [PATCH 11/29] date-time: check events before to pick events day --- packages/components/src/date-time/date.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index e1cc330050550..337ac018090bc 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -108,6 +108,10 @@ class DatePicker extends Component { } getEventsPerDay( day ) { + if ( ! this.props.events?.length ) { + return []; + } + return this.props.events.filter( ( eventDay ) => day.isSame( eventDay.date, 'day' ) ); From 4e3471ef4f0f5272a78cab3fbd37b95bd3bf8346 Mon Sep 17 00:00:00 2001 From: retrofox Date: Mon, 15 Mar 2021 10:49:46 -0300 Subject: [PATCH 12/29] fix rebasing issues --- .../editor/src/components/post-schedule/index.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/editor/src/components/post-schedule/index.js b/packages/editor/src/components/post-schedule/index.js index 39722b65236bf..5471bece0246c 100644 --- a/packages/editor/src/components/post-schedule/index.js +++ b/packages/editor/src/components/post-schedule/index.js @@ -23,7 +23,7 @@ function getDayOfTheMonth( date = new Date(), firstDay = true ) { export default function PostSchedule() { const date = useSelect( - ( select ) => select( coreStore ).getEditedPostAttribute( 'date' ), + ( select ) => select( editorStore ).getEditedPostAttribute( 'date' ), [] ); @@ -36,22 +36,19 @@ export default function PostSchedule() { // Pick up published and schduled site posts. const events = useSelect( - ( select ) => { - const postId = select( editorStore ).getCurrentPostId(); - - return ( + ( select ) => + ( select( coreStore ).getEntityRecords( 'postType', 'post', { status: 'publish,future', after: getDayOfTheMonth( currentMonth ), before: getDayOfTheMonth( currentMonth, false ), - exclude: [ postId ], + exclude: [ select( editorStore ).getCurrentPostId() ], } ) || [] ).map( ( { title, type, date: eventDate } ) => ( { title: title?.raw, type, date: new Date( eventDate ), - } ) ); - }, + } ) ), [ currentMonth ] ); From 415f543008c719b340f134bacf712a82077d1c9b Mon Sep 17 00:00:00 2001 From: retrofox Date: Mon, 15 Mar 2021 11:22:41 -0300 Subject: [PATCH 13/29] date-time: events replace circles by dots --- packages/components/src/date-time/style.scss | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/components/src/date-time/style.scss b/packages/components/src/date-time/style.scss index dc173c5061a20..a7be7fd73bd8d 100644 --- a/packages/components/src/date-time/style.scss +++ b/packages/components/src/date-time/style.scss @@ -111,19 +111,31 @@ } } -.components-datetime__date .CalendarDay:not(.CalendarDay__selected) .components-datetime__date__day { +.components-datetime__date .CalendarDay .components-datetime__date__day { height: 100%; display: flex; justify-content: center; align-content: center; flex-direction: column; + position: relative; - &.has-events { - border: 2px solid $gray-400; - border-radius: 50%; + &.has-events::before { + content: ' '; + width: 4px; + height: 4px; + border-radius: 2px; + position: absolute; + left: 50%; + margin-left: -2px; + bottom: 0; + background-color: $white; } } +.components-datetime__date .CalendarDay:not(.CalendarDay__selected) .components-datetime__date__day.has-events::before { + background: var(--wp-admin-theme-color); +} + .components-datetime__time { padding-bottom: $grid-unit-20; From 51e49d27c66af4ad885e2c419d3858f8dd8f817d Mon Sep 17 00:00:00 2001 From: retrofox Date: Mon, 15 Mar 2021 11:30:21 -0300 Subject: [PATCH 14/29] fix rebasing bug --- packages/editor/src/components/post-schedule/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-schedule/index.js b/packages/editor/src/components/post-schedule/index.js index 5471bece0246c..b4fdb92a81aec 100644 --- a/packages/editor/src/components/post-schedule/index.js +++ b/packages/editor/src/components/post-schedule/index.js @@ -27,7 +27,7 @@ export default function PostSchedule() { [] ); - const { editPost } = useDispatch( coreStore ); + const { editPost } = useDispatch( editorStore ); const onUpdateDate = ( postDate ) => editPost( { date: postDate } ); const [ currentMonth, setCurrentMonth ] = useState( From efed5602cb43308f7775367e2aab850e6d8045b2 Mon Sep 17 00:00:00 2001 From: retrofox Date: Tue, 16 Mar 2021 09:44:09 -0300 Subject: [PATCH 15/29] post-schedule: split up processing post events --- .../src/components/post-schedule/index.js | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/editor/src/components/post-schedule/index.js b/packages/editor/src/components/post-schedule/index.js index b4fdb92a81aec..483b966595cce 100644 --- a/packages/editor/src/components/post-schedule/index.js +++ b/packages/editor/src/components/post-schedule/index.js @@ -4,7 +4,7 @@ import { __experimentalGetSettings } from '@wordpress/date'; import { useDispatch, useSelect } from '@wordpress/data'; import { DateTimePicker } from '@wordpress/components'; -import { useRef, useState } from '@wordpress/element'; +import { useRef, useState, useMemo } from '@wordpress/element'; import { store as coreStore } from '@wordpress/core-data'; /** @@ -35,23 +35,29 @@ export default function PostSchedule() { ); // Pick up published and schduled site posts. - const events = useSelect( + const postsEvents = useSelect( ( select ) => - ( - select( coreStore ).getEntityRecords( 'postType', 'post', { - status: 'publish,future', - after: getDayOfTheMonth( currentMonth ), - before: getDayOfTheMonth( currentMonth, false ), - exclude: [ select( editorStore ).getCurrentPostId() ], - } ) || [] - ).map( ( { title, type, date: eventDate } ) => ( { - title: title?.raw, - type, - date: new Date( eventDate ), - } ) ), + select( coreStore ).getEntityRecords( 'postType', 'post', { + status: 'publish,future', + after: getDayOfTheMonth( currentMonth ), + before: getDayOfTheMonth( currentMonth, false ), + exclude: [ select( editorStore ).getCurrentPostId() ], + } ), [ currentMonth ] ); + const events = useMemo( + () => + ( postsEvents || [] ).map( + ( { title, type, date: eventDate } ) => ( { + title: title?.raw, + type, + date: new Date( eventDate ), + } ) + ), + [ postsEvents ] + ); + const ref = useRef(); const settings = __experimentalGetSettings(); From 7db090cbcab36c79cea5b4259de5eb0c79ad8635 Mon Sep 17 00:00:00 2001 From: retrofox Date: Tue, 16 Mar 2021 09:48:04 -0300 Subject: [PATCH 16/29] date-time: revert prop name change --- packages/components/src/date-time/date.js | 10 +++++----- packages/components/src/date-time/index.js | 4 ++-- packages/editor/src/components/post-schedule/index.js | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 337ac018090bc..6a2cd2ce1ef9b 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -37,11 +37,11 @@ class DatePicker extends Component { this.onChangeMoment = this.onChangeMoment.bind( this ); this.nodeRef = createRef(); - this.onMonthChangeHandler = this.onMonthChangeHandler.bind( this ); + this.onMonthPreviewedHandler = this.onMonthPreviewedHandler.bind( this ); } - onMonthChangeHandler( newMonthDate ) { - this.props?.onMonthChange( newMonthDate.toISOString() ); + onMonthPreviewedHandler( newMonthDate ) { + this.props?.onMonthPreviewed( newMonthDate.toISOString() ); this.keepFocusInside(); } @@ -142,8 +142,8 @@ class DatePicker extends Component { isOutsideRange={ ( date ) => { return isInvalidDate && isInvalidDate( date.toDate() ); } } - onPrevMonthClick={ this.onMonthChangeHandler } - onNextMonthClick={ this.onMonthChangeHandler } + onPrevMonthClick={ this.onMonthPreviewedHandler } + onNextMonthClick={ this.onMonthPreviewedHandler } renderDayContents={ ( day ) => ( ) } diff --git a/packages/editor/src/components/post-schedule/index.js b/packages/editor/src/components/post-schedule/index.js index 483b966595cce..fb10332240edf 100644 --- a/packages/editor/src/components/post-schedule/index.js +++ b/packages/editor/src/components/post-schedule/index.js @@ -30,7 +30,7 @@ export default function PostSchedule() { const { editPost } = useDispatch( editorStore ); const onUpdateDate = ( postDate ) => editPost( { date: postDate } ); - const [ currentMonth, setCurrentMonth ] = useState( + const [ previewedMonth, setPreviewedMonth ] = useState( getDayOfTheMonth( date ) ); @@ -39,11 +39,11 @@ export default function PostSchedule() { ( select ) => select( coreStore ).getEntityRecords( 'postType', 'post', { status: 'publish,future', - after: getDayOfTheMonth( currentMonth ), - before: getDayOfTheMonth( currentMonth, false ), + after: getDayOfTheMonth( previewedMonth ), + before: getDayOfTheMonth( previewedMonth, false ), exclude: [ select( editorStore ).getCurrentPostId() ], } ), - [ currentMonth ] + [ previewedMonth ] ); const events = useMemo( @@ -85,7 +85,7 @@ export default function PostSchedule() { onChange={ onChange } is12Hour={ is12HourTime } events={ events } - onMonthChange={ setCurrentMonth } + onMonthPreviewed={ setPreviewedMonth } /> ); } From bd196cfe8e539a7db3d4eb13ac3ac0fa3ecee5c4 Mon Sep 17 00:00:00 2001 From: retrofox Date: Tue, 16 Mar 2021 14:47:06 -0300 Subject: [PATCH 17/29] date-time: add screen reader support --- packages/components/src/date-time/date.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 6a2cd2ce1ef9b..149049f8f65bb 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -12,7 +12,12 @@ import DayPickerSingleDateController from 'react-dates/lib/components/DayPickerS * WordPress dependencies */ import { Component, createRef } from '@wordpress/element'; -import { isRTL } from '@wordpress/i18n'; +import { isRTL, _n } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import VisuallyHidden from '../visually-hidden'; /** * Module Constants @@ -27,6 +32,11 @@ function DatePickerDay( { day, events } ) { } ) } > { day.format( 'D' ) } + { events?.length > 0 && ( + + { _n( 'has one post', 'has some posts', events.length ) } + + ) }
); } From 07d1f8e113f48e9d7d66d4b21de2951a799545c4 Mon Sep 17 00:00:00 2001 From: retrofox Date: Wed, 17 Mar 2021 10:48:38 -0300 Subject: [PATCH 18/29] date-time: update content for screen reader --- packages/components/src/date-time/date.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 149049f8f65bb..83273b81d2752 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -34,9 +34,13 @@ function DatePickerDay( { day, events } ) { { day.format( 'D' ) } { events?.length > 0 && ( - { _n( 'has one post', 'has some posts', events.length ) } + { _n( + 'has published/scheduled item', + 'Has published/scheduled items', + events.length + ) } - ) } + ) } ); } From 576ec799db24a7e39bc4e88efb3acbc68e799512 Mon Sep 17 00:00:00 2001 From: retrofox Date: Wed, 17 Mar 2021 10:49:38 -0300 Subject: [PATCH 19/29] date-time: fix eslint error --- packages/components/src/date-time/date.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 83273b81d2752..cfd20a095a6e7 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -51,7 +51,9 @@ class DatePicker extends Component { this.onChangeMoment = this.onChangeMoment.bind( this ); this.nodeRef = createRef(); - this.onMonthPreviewedHandler = this.onMonthPreviewedHandler.bind( this ); + this.onMonthPreviewedHandler = this.onMonthPreviewedHandler.bind( + this + ); } onMonthPreviewedHandler( newMonthDate ) { From 79567d344aae3348b66f2d0a0e6ad530301a3c64 Mon Sep 17 00:00:00 2001 From: retrofox Date: Wed, 17 Mar 2021 10:59:18 -0300 Subject: [PATCH 20/29] post-schedule: get events by post type --- .../src/components/post-schedule/index.js | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/editor/src/components/post-schedule/index.js b/packages/editor/src/components/post-schedule/index.js index fb10332240edf..2e8dac1e03d8d 100644 --- a/packages/editor/src/components/post-schedule/index.js +++ b/packages/editor/src/components/post-schedule/index.js @@ -22,40 +22,43 @@ function getDayOfTheMonth( date = new Date(), firstDay = true ) { } export default function PostSchedule() { - const date = useSelect( - ( select ) => select( editorStore ).getEditedPostAttribute( 'date' ), + const { postDate, postType } = useSelect( + ( select ) => ( { + postDate: select( editorStore ).getEditedPostAttribute( 'date' ), + postType: select( editorStore ).getCurrentPostType(), + } ), [] ); const { editPost } = useDispatch( editorStore ); - const onUpdateDate = ( postDate ) => editPost( { date: postDate } ); + const onUpdateDate = ( date ) => editPost( { date } ); const [ previewedMonth, setPreviewedMonth ] = useState( - getDayOfTheMonth( date ) + getDayOfTheMonth( postDate ) ); // Pick up published and schduled site posts. - const postsEvents = useSelect( + const eventsByPostType = useSelect( ( select ) => - select( coreStore ).getEntityRecords( 'postType', 'post', { + select( coreStore ).getEntityRecords( 'postType', postType, { status: 'publish,future', after: getDayOfTheMonth( previewedMonth ), before: getDayOfTheMonth( previewedMonth, false ), exclude: [ select( editorStore ).getCurrentPostId() ], } ), - [ previewedMonth ] + [ previewedMonth, postType ] ); const events = useMemo( () => - ( postsEvents || [] ).map( + ( eventsByPostType || [] ).map( ( { title, type, date: eventDate } ) => ( { title: title?.raw, type, date: new Date( eventDate ), } ) ), - [ postsEvents ] + [ eventsByPostType ] ); const ref = useRef(); @@ -81,7 +84,7 @@ export default function PostSchedule() { return ( Date: Wed, 17 Mar 2021 12:52:01 -0300 Subject: [PATCH 21/29] date-time: rephrase events number for readers --- packages/components/src/date-time/date.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index cfd20a095a6e7..640bd6f86f9e8 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -12,7 +12,7 @@ import DayPickerSingleDateController from 'react-dates/lib/components/DayPickerS * WordPress dependencies */ import { Component, createRef } from '@wordpress/element'; -import { isRTL, _n } from '@wordpress/i18n'; +import { isRTL, _n, sprintf } from '@wordpress/i18n'; /** * Internal dependencies @@ -34,9 +34,13 @@ function DatePickerDay( { day, events } ) { { day.format( 'D' ) } { events?.length > 0 && ( - { _n( - 'has published/scheduled item', - 'Has published/scheduled items', + { sprintf( + /* translators: %d: number of calendar events. */ + _n( + 'There is %d event.', + 'There are %d events.', + events.length + ), events.length ) } From 0ced50aa757590339b76012563d67571a541603a Mon Sep 17 00:00:00 2001 From: retrofox Date: Mon, 22 Mar 2021 17:37:47 -0300 Subject: [PATCH 22/29] date-time: add events to aria label --- packages/components/src/date-time/date.js | 55 ++++++++++++++--------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 640bd6f86f9e8..40b432033c9f7 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -11,40 +11,55 @@ import DayPickerSingleDateController from 'react-dates/lib/components/DayPickerS /** * WordPress dependencies */ -import { Component, createRef } from '@wordpress/element'; +import { Component, createRef, useEffect, useRef } from '@wordpress/element'; import { isRTL, _n, sprintf } from '@wordpress/i18n'; -/** - * Internal dependencies - */ -import VisuallyHidden from '../visually-hidden'; - /** * Module Constants */ const TIMEZONELESS_FORMAT = 'YYYY-MM-DDTHH:mm:ss'; -function DatePickerDay( { day, events } ) { +function DatePickerDay( { day, events = [] } ) { + const ref = useRef(); + + // a11y hack to make the `There is/are n events` string + // available speaking for readers, + // re-defining the aria-label attribute. + // This attribute is handled by the react-dates component. + useEffect( () => { + if ( ! ref?.current?.parentNode ) { + return; + } + + if ( ! events.length ) { + return; + } + + const { parentNode } = ref.current; + + const eventsString = sprintf( + /* translators: %d: number of calendar events. */ + _n( 'There is %d event', 'There are %d events', events.length ), + events.length + ); + + const initAriaLabel = + parentNode + .getAttribute( 'aria-label' ) + .replace( /\. There (?:are|is) \d+ event\s?/, '' ) + + `. ${ eventsString }`; + + parentNode.setAttribute( 'aria-label', initAriaLabel ); + }, [ ref, events.length ] ); + return (
{ day.format( 'D' ) } - { events?.length > 0 && ( - - { sprintf( - /* translators: %d: number of calendar events. */ - _n( - 'There is %d event.', - 'There are %d events.', - events.length - ), - events.length - ) } - - ) }
); } From 3645a7acf712f0354c246ac754bd60a02accbe58 Mon Sep 17 00:00:00 2001 From: retrofox Date: Tue, 6 Apr 2021 13:49:35 -0300 Subject: [PATCH 23/29] date-time: fix lint error. tidy. --- packages/components/src/date-time/date.js | 16 ++++++++++------ packages/components/src/date-time/style.scss | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 40b432033c9f7..cab794bcf897b 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -22,16 +22,20 @@ const TIMEZONELESS_FORMAT = 'YYYY-MM-DDTHH:mm:ss'; function DatePickerDay( { day, events = [] } ) { const ref = useRef(); - // a11y hack to make the `There is/are n events` string - // available speaking for readers, - // re-defining the aria-label attribute. - // This attribute is handled by the react-dates component. + /* + * a11y hack to make the `There is/are n events` string + * available speaking for readers, + * re-defining the aria-label attribute. + * This attribute is handled by the react-dates component. + */ useEffect( () => { - if ( ! ref?.current?.parentNode ) { + // Bail early when no events. + if ( ! events.length ) { return; } - if ( ! events.length ) { + // Bail when no parent node. + if ( ! ref?.current?.parentNode ) { return; } diff --git a/packages/components/src/date-time/style.scss b/packages/components/src/date-time/style.scss index a7be7fd73bd8d..43f95756c8d70 100644 --- a/packages/components/src/date-time/style.scss +++ b/packages/components/src/date-time/style.scss @@ -120,7 +120,7 @@ position: relative; &.has-events::before { - content: ' '; + content: " "; width: 4px; height: 4px; border-radius: 2px; From 212bb21f25bc52855b93a305a12bddec4f60f2bc Mon Sep 17 00:00:00 2001 From: retrofox Date: Tue, 6 Apr 2021 15:16:09 -0300 Subject: [PATCH 24/29] date-time: set aria-label value --- packages/components/src/date-time/date.js | 25 ++++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index cab794bcf897b..2f694f5a5c493 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -18,6 +18,7 @@ import { isRTL, _n, sprintf } from '@wordpress/i18n'; * Module Constants */ const TIMEZONELESS_FORMAT = 'YYYY-MM-DDTHH:mm:ss'; +const ARIAL_LABEL_TIME_FORMAT = 'dddd, LL'; function DatePickerDay( { day, events = [] } ) { const ref = useRef(); @@ -29,17 +30,19 @@ function DatePickerDay( { day, events = [] } ) { * This attribute is handled by the react-dates component. */ useEffect( () => { - // Bail early when no events. - if ( ! events.length ) { - return; - } - // Bail when no parent node. if ( ! ref?.current?.parentNode ) { return; } const { parentNode } = ref.current; + const dayAriaLabel = moment( day ).format( ARIAL_LABEL_TIME_FORMAT ); + + if ( ! events.length ) { + // Set aria-label without event description. + parentNode.setAttribute( 'aria-label', dayAriaLabel ); + return; + } const eventsString = sprintf( /* translators: %d: number of calendar events. */ @@ -47,13 +50,10 @@ function DatePickerDay( { day, events = [] } ) { events.length ); - const initAriaLabel = - parentNode - .getAttribute( 'aria-label' ) - .replace( /\. There (?:are|is) \d+ event\s?/, '' ) + - `. ${ eventsString }`; - - parentNode.setAttribute( 'aria-label', initAriaLabel ); + parentNode.setAttribute( + 'aria-label', + `${ dayAriaLabel }. ${ eventsString }` + ); }, [ ref, events.length ] ); return ( @@ -177,6 +177,7 @@ class DatePicker extends Component { onDateChange={ this.onChangeMoment } transitionDuration={ 0 } weekDayFormat="ddd" + dayAriaLabelFormat={ ARIAL_LABEL_TIME_FORMAT } // Friday, F j, 2021. There is 1 event isRTL={ isRTL() } isOutsideRange={ ( date ) => { return isInvalidDate && isInvalidDate( date.toDate() ); From 3a9bc181ce4dbe68371625f295144a4a5af7a5bb Mon Sep 17 00:00:00 2001 From: retrofox Date: Tue, 6 Apr 2021 16:15:50 -0300 Subject: [PATCH 25/29] date-time: update e2e test --- packages/e2e-tests/specs/editor/various/post-visibility.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/e2e-tests/specs/editor/various/post-visibility.test.js b/packages/e2e-tests/specs/editor/various/post-visibility.test.js index 6844b9bd97345..c395ea8795236 100644 --- a/packages/e2e-tests/specs/editor/various/post-visibility.test.js +++ b/packages/e2e-tests/specs/editor/various/post-visibility.test.js @@ -51,7 +51,7 @@ describe( 'Post visibility', () => { ); await ( await page.$x( - '//td[contains(concat(" ", @class, " "), " CalendarDay ")][text() = "15"]' + '//td[contains(concat(" ", @class, " "), " CalendarDay ")]/div[contains(concat(" ", @class, " "), " components-datetime__date__day ")][text() = "15"]' ) )[ 0 ].click(); From fa33d949ce06b5f359e05e458f964cd26f1e0108 Mon Sep 17 00:00:00 2001 From: retrofox Date: Wed, 7 Apr 2021 10:06:17 -0300 Subject: [PATCH 26/29] date-time: clean comment --- packages/components/src/date-time/date.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 2f694f5a5c493..0ad979c87408f 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -177,7 +177,7 @@ class DatePicker extends Component { onDateChange={ this.onChangeMoment } transitionDuration={ 0 } weekDayFormat="ddd" - dayAriaLabelFormat={ ARIAL_LABEL_TIME_FORMAT } // Friday, F j, 2021. There is 1 event + dayAriaLabelFormat={ ARIAL_LABEL_TIME_FORMAT } isRTL={ isRTL() } isOutsideRange={ ( date ) => { return isInvalidDate && isInvalidDate( date.toDate() ); From f677f377060999f700ac5e5311740afa5de4e5fa Mon Sep 17 00:00:00 2001 From: retrofox Date: Wed, 7 Apr 2021 13:22:40 -0300 Subject: [PATCH 27/29] date-time: join day-with-events string to improve its translation --- packages/components/src/date-time/date.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 0ad979c87408f..82d03de1873e3 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -44,16 +44,18 @@ function DatePickerDay( { day, events = [] } ) { return; } - const eventsString = sprintf( - /* translators: %d: number of calendar events. */ - _n( 'There is %d event', 'There are %d events', events.length ), + const dayWithEventsDescription = sprintf( + // translators: 1: Calendar day format, 2: Calendar event number. + _n( + '%1$s. There is %2$d event.', + '%1$s. There are %2$d events.', + events.length + ), + dayAriaLabel, events.length ); - parentNode.setAttribute( - 'aria-label', - `${ dayAriaLabel }. ${ eventsString }` - ); + parentNode.setAttribute( 'aria-label', dayWithEventsDescription ); }, [ ref, events.length ] ); return ( From 153fac3de354005958db0062bb945412dee7e889 Mon Sep 17 00:00:00 2001 From: retrofox Date: Thu, 8 Apr 2021 06:35:40 -0300 Subject: [PATCH 28/29] date-time: remove ref as hook dependency The ref nevers changes its value --- packages/components/src/date-time/date.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/date-time/date.js b/packages/components/src/date-time/date.js index 82d03de1873e3..66c54275ea8a8 100644 --- a/packages/components/src/date-time/date.js +++ b/packages/components/src/date-time/date.js @@ -56,7 +56,7 @@ function DatePickerDay( { day, events = [] } ) { ); parentNode.setAttribute( 'aria-label', dayWithEventsDescription ); - }, [ ref, events.length ] ); + }, [ events.length ] ); return (
Date: Thu, 8 Apr 2021 08:38:05 -0300 Subject: [PATCH 29/29] post-scheudle: use title.rendered prop for events --- packages/editor/src/components/post-schedule/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-schedule/index.js b/packages/editor/src/components/post-schedule/index.js index 2e8dac1e03d8d..89526384b2ba1 100644 --- a/packages/editor/src/components/post-schedule/index.js +++ b/packages/editor/src/components/post-schedule/index.js @@ -53,7 +53,7 @@ export default function PostSchedule() { () => ( eventsByPostType || [] ).map( ( { title, type, date: eventDate } ) => ( { - title: title?.raw, + title: title?.rendered, type, date: new Date( eventDate ), } )