From 7c63d1095606ac069a288116f4ece054730ae30b Mon Sep 17 00:00:00 2001 From: Jorge Date: Wed, 7 Nov 2018 12:01:30 +0000 Subject: [PATCH 1/4] Allow a block to disable being converted into a reusable block; Fix: Column block (#11550) --- docs/block-api.md | 7 +++++ packages/block-library/src/classic/index.js | 3 ++ packages/block-library/src/columns/column.js | 1 + packages/block-library/src/missing/index.js | 1 + .../reusable-block-convert-button.js | 29 ++++++++----------- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/docs/block-api.md b/docs/block-api.md index a3df73ffcb80e..01b2295b46de0 100644 --- a/docs/block-api.md +++ b/docs/block-api.md @@ -504,6 +504,13 @@ inserter: false, multiple: false, ``` +- `reusable` (default `true`): A block may want to disable the ability of being converted into a reusable block. +By default all blocks can be converted to a reusable block. If supports reusable is set to false, the option to convert the block into a reusable block will not appear. + +```js +// Don't allow the block to be converted into a reusable block. +reusable: false, +``` ## Edit and Save The `edit` and `save` functions define the editor interface with which a user would interact, and the markup to be serialized back when a post is saved. They are the heart of how a block operates, so they are [covered separately](../docs/block-api/block-edit-save.md). diff --git a/packages/block-library/src/classic/index.js b/packages/block-library/src/classic/index.js index e30d7fa75eada..bcc4f0a388010 100644 --- a/packages/block-library/src/classic/index.js +++ b/packages/block-library/src/classic/index.js @@ -31,6 +31,9 @@ export const settings = { supports: { className: false, customClassName: false, + // Hide 'Add to Reusable Blocks' on Classic blocks. Showing it causes a + // confusing UX, because of its similarity to the 'Convert to Blocks' button. + reusable: false, }, edit, diff --git a/packages/block-library/src/columns/column.js b/packages/block-library/src/columns/column.js index 89e22f1601d2c..a8f37dd7df7ec 100644 --- a/packages/block-library/src/columns/column.js +++ b/packages/block-library/src/columns/column.js @@ -20,6 +20,7 @@ export const settings = { supports: { inserter: false, + reusable: false, }, edit() { diff --git a/packages/block-library/src/missing/index.js b/packages/block-library/src/missing/index.js index 1ef9391b9264c..82de41b1d6eff 100644 --- a/packages/block-library/src/missing/index.js +++ b/packages/block-library/src/missing/index.js @@ -66,6 +66,7 @@ export const settings = { customClassName: false, inserter: false, html: false, + reusable: false, }, attributes: { diff --git a/packages/editor/src/components/block-settings-menu/reusable-block-convert-button.js b/packages/editor/src/components/block-settings-menu/reusable-block-convert-button.js index 84530fb22bbef..6d39538aa5e5a 100644 --- a/packages/editor/src/components/block-settings-menu/reusable-block-convert-button.js +++ b/packages/editor/src/components/block-settings-menu/reusable-block-convert-button.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { noop, every, map } from 'lodash'; +import { noop, every } from 'lodash'; /** * WordPress dependencies @@ -9,7 +9,7 @@ import { noop, every, map } from 'lodash'; import { Fragment } from '@wordpress/element'; import { MenuItem } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { isReusableBlock } from '@wordpress/blocks'; +import { hasBlockSupport, isReusableBlock } from '@wordpress/blocks'; import { withSelect, withDispatch } from '@wordpress/data'; import { compose } from '@wordpress/compose'; @@ -50,31 +50,26 @@ export function ReusableBlockConvertButton( { export default compose( [ withSelect( ( select, { clientIds } ) => { const { - getBlock, + getBlocksByClientId, canInsertBlockType, __experimentalGetReusableBlock: getReusableBlock, } = select( 'core/editor' ); - const { - getFreeformFallbackBlockName, - getUnregisteredFallbackBlockName, - } = select( 'core/blocks' ); - const blocks = map( clientIds, ( clientId ) => getBlock( clientId ) ); + const blocks = getBlocksByClientId( clientIds ); const isVisible = ( - // Guard against the case where a regular block has *just* been converted to a - // reusable block and doesn't yet exist in the editor store. - every( blocks, ( block ) => !! block ) && - // Hide 'Add to Reusable Blocks' when Reusable Blocks are disabled, i.e. when // core/block is not in the allowed_block_types filter. canInsertBlockType( 'core/block' ) && - // Hide 'Add to Reusable Blocks' on Classic blocks. Showing it causes a - // confusing UX, because of its similarity to the 'Convert to Blocks' button. - ( blocks.length !== 1 || ( - blocks[ 0 ].name !== getFreeformFallbackBlockName() && - blocks[ 0 ].name !== getUnregisteredFallbackBlockName() + every( blocks, ( block ) => ( + // Guard against the case where a regular block has *just* been converted to a + // reusable block and doesn't yet exist in the editor store. + !! block && + // Only show the option to covert to reusable blocks on valid blocks. + block.isValid && + // Make sure the block supports being converted into a reusable block (by default that is the case). + hasBlockSupport( block.name, 'reusable', true ) ) ) ); From 16a718a4bf359c53f0fb9c3626b08e2434a6fd7d Mon Sep 17 00:00:00 2001 From: Jorge Date: Wed, 7 Nov 2018 12:16:22 +0000 Subject: [PATCH 2/4] Add mechanism to avoid forced child selection on blocks with templates. (#10696) Currently, if a block contains a template when we insert that block the block that gets focused is one of the child blocks specified in the template. We don't offer a way to disable this behavior. This current behavior makes sense in most cases (e.g: columns) but for some cases, we may want to keep the focus on the parent. E.g. In PR #9416 @afercia pointed some a11y concerns in automatically selecting the child block on the InnerBlocks area. Blocks may have their own edition area and an InnerBlocks are at the end. Automatically selecting a block in the InnerBlocks area, has some accessible concerns has the parent block edition area may be unnoticeable for screen reader users. This PR adds a flag to the InnerBlocks component that allows blocks to disable the behavior of automatically selecting the children. In order for this flag to be possible another flag was added in insertBlock(s) action that allows for blocks to be inserted without a selection update happening. --- docs/data/data-core-editor.md | 8 +++---- .../src/components/inner-blocks/README.md | 7 ++++++ .../src/components/inner-blocks/index.js | 4 ++-- packages/editor/src/store/actions.js | 23 ++++++++++--------- packages/editor/src/store/reducer.js | 20 +++++++++------- packages/editor/src/store/test/actions.js | 2 ++ packages/editor/src/store/test/reducer.js | 19 +++++++++++++++ 7 files changed, 58 insertions(+), 25 deletions(-) diff --git a/docs/data/data-core-editor.md b/docs/data/data-core-editor.md index 267184d78113e..5b823d1893d0d 100644 --- a/docs/data/data-core-editor.md +++ b/docs/data/data-core-editor.md @@ -1532,8 +1532,8 @@ inserted, optionally at a specific index respective a root block list. * block: Block object to insert. * index: Index at which block should be inserted. - * rootClientId: Optional root client ID of block list on which - to insert. + * rootClientId: Optional root client ID of block list on which to insert. + * updateSelection: If true block selection will be updated. If false, block selection will not change. Defaults to true. ### insertBlocks @@ -1544,8 +1544,8 @@ be inserted, optionally at a specific index respective a root block list. * blocks: Block objects to insert. * index: Index at which block should be inserted. - * rootClientId: Optional root client ID of block list on - which to insert. + * rootClientId: Optional root cliente ID of block list on which to insert. + * updateSelection: If true block selection will be updated. If false, block selection will not change. Defaults to true. ### showInsertionPoint diff --git a/packages/editor/src/components/inner-blocks/README.md b/packages/editor/src/components/inner-blocks/README.md index 494fb750fb74c..040b0d463861c 100644 --- a/packages/editor/src/components/inner-blocks/README.md +++ b/packages/editor/src/components/inner-blocks/README.md @@ -90,6 +90,13 @@ const TEMPLATE = [ [ 'core/columns', {}, [ The previous example creates an InnerBlocks area containing two columns one with an image and the other with a paragraph. +### `templateInsertUpdatesSelection` +* **Type:** `Boolean` +* **Default:** `true` + +If true when child blocks in the template are inserted the selection is updated. +If false the selection should not be updated when child blocks specified in the template are inserted. + ### `templateLock` * **Type:** `String|Boolean` diff --git a/packages/editor/src/components/inner-blocks/index.js b/packages/editor/src/components/inner-blocks/index.js index c9252e912b5df..2183163221181 100644 --- a/packages/editor/src/components/inner-blocks/index.js +++ b/packages/editor/src/components/inner-blocks/index.js @@ -142,7 +142,7 @@ InnerBlocks = compose( [ insertBlocks, updateBlockListSettings, } = dispatch( 'core/editor' ); - const { block, clientId } = ownProps; + const { block, clientId, templateInsertUpdatesSelection = true } = ownProps; return { replaceInnerBlocks( blocks ) { @@ -150,7 +150,7 @@ InnerBlocks = compose( [ if ( clientIds.length ) { replaceBlocks( clientIds, blocks ); } else { - insertBlocks( blocks, undefined, clientId ); + insertBlocks( blocks, undefined, clientId, templateInsertUpdatesSelection ); } }, updateNestedSettings( settings ) { diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index 7d5c0d71ee2d1..a77b27add51c2 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -295,35 +295,36 @@ export function moveBlockToPosition( clientId, fromRootClientId, toRootClientId, * Returns an action object used in signalling that a single block should be * inserted, optionally at a specific index respective a root block list. * - * @param {Object} block Block object to insert. - * @param {?number} index Index at which block should be inserted. - * @param {?string} rootClientId Optional root client ID of block list on which - * to insert. + * @param {Object} block Block object to insert. + * @param {?number} index Index at which block should be inserted. + * @param {?string} rootClientId Optional root client ID of block list on which to insert. + * @param {?boolean} updateSelection If true block selection will be updated. If false, block selection will not change. Defaults to true. * * @return {Object} Action object. */ -export function insertBlock( block, index, rootClientId ) { - return insertBlocks( [ block ], index, rootClientId ); +export function insertBlock( block, index, rootClientId, updateSelection = true ) { + return insertBlocks( [ block ], index, rootClientId, updateSelection ); } /** * Returns an action object used in signalling that an array of blocks should * be inserted, optionally at a specific index respective a root block list. * - * @param {Object[]} blocks Block objects to insert. - * @param {?number} index Index at which block should be inserted. - * @param {?string} rootClientId Optional root client ID of block list on - * which to insert. + * @param {Object[]} blocks Block objects to insert. + * @param {?number} index Index at which block should be inserted. + * @param {?string} rootClientId Optional root cliente ID of block list on which to insert. + * @param {?boolean} updateSelection If true block selection will be updated. If false, block selection will not change. Defaults to true. * * @return {Object} Action object. */ -export function insertBlocks( blocks, index, rootClientId ) { +export function insertBlocks( blocks, index, rootClientId, updateSelection = true ) { return { type: 'INSERT_BLOCKS', blocks: castArray( blocks ), index, rootClientId, time: Date.now(), + updateSelection, }; } diff --git a/packages/editor/src/store/reducer.js b/packages/editor/src/store/reducer.js index e95b010dc94d9..9ea2259b2c791 100644 --- a/packages/editor/src/store/reducer.js +++ b/packages/editor/src/store/reducer.js @@ -705,14 +705,18 @@ export function blockSelection( state = { end: action.clientId, initialPosition: action.initialPosition, }; - case 'INSERT_BLOCKS': - return { - ...state, - start: action.blocks[ 0 ].clientId, - end: action.blocks[ 0 ].clientId, - initialPosition: null, - isMultiSelecting: false, - }; + case 'INSERT_BLOCKS': { + if ( action.updateSelection ) { + return { + ...state, + start: action.blocks[ 0 ].clientId, + end: action.blocks[ 0 ].clientId, + initialPosition: null, + isMultiSelecting: false, + }; + } + return state; + } case 'REMOVE_BLOCKS': if ( ! action.clientIds || ! action.clientIds.length || action.clientIds.indexOf( state.start ) === -1 ) { return state; diff --git a/packages/editor/src/store/test/actions.js b/packages/editor/src/store/test/actions.js index 4358054f8573b..b071dc78204fb 100644 --- a/packages/editor/src/store/test/actions.js +++ b/packages/editor/src/store/test/actions.js @@ -188,6 +188,7 @@ describe( 'actions', () => { index, rootClientId: 'testclientid', time: expect.any( Number ), + updateSelection: true, } ); } ); } ); @@ -204,6 +205,7 @@ describe( 'actions', () => { index, rootClientId: 'testclientid', time: expect.any( Number ), + updateSelection: true, } ); } ); } ); diff --git a/packages/editor/src/store/test/reducer.js b/packages/editor/src/store/test/reducer.js index 7d75ce2c55b4f..005fd9127690f 100644 --- a/packages/editor/src/store/test/reducer.js +++ b/packages/editor/src/store/test/reducer.js @@ -1567,6 +1567,7 @@ describe( 'state', () => { clientId: 'ribs', name: 'core/freeform', } ], + updateSelection: true, } ); expect( state3 ).toEqual( { @@ -1577,6 +1578,24 @@ describe( 'state', () => { } ); } ); + it( 'should not select inserted block if updateSelection flag is false', () => { + const original = deepFreeze( { start: 'a', end: 'b' } ); + + const state3 = blockSelection( original, { + type: 'INSERT_BLOCKS', + blocks: [ { + clientId: 'ribs', + name: 'core/freeform', + } ], + updateSelection: false, + } ); + + expect( state3 ).toEqual( { + start: 'a', + end: 'b', + } ); + } ); + it( 'should not update the state if the block moved is already selected', () => { const original = deepFreeze( { start: 'ribs', end: 'ribs' } ); const state = blockSelection( original, { From 26ccc159f373e5412d4fabf20fa00431d8fce7b6 Mon Sep 17 00:00:00 2001 From: Marko Savic Date: Wed, 7 Nov 2018 13:59:49 +0100 Subject: [PATCH 3/4] Slot/Fill pattern with Toolbar #199 (#11115) Added support for native toolbar component --- packages/block-library/src/code/edit.native.js | 7 ++++++- packages/block-library/src/code/theme.android.scss | 4 ++++ packages/block-library/src/code/theme.ios.scss | 5 +++++ packages/block-library/src/heading/edit.native.js | 6 ++++-- packages/block-library/src/paragraph/edit.native.js | 9 +++++++-- packages/block-library/src/paragraph/style.native.scss | 3 +++ packages/components/src/button/index.native.js | 4 ++-- packages/components/src/index.native.js | 1 + .../components/src/toolbar/toolbar-container.native.js | 2 +- packages/editor/src/components/index.native.js | 2 ++ packages/editor/src/components/rich-text/index.native.js | 5 +++-- 11 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 packages/block-library/src/code/theme.android.scss create mode 100644 packages/block-library/src/code/theme.ios.scss create mode 100644 packages/block-library/src/paragraph/style.native.scss diff --git a/packages/block-library/src/code/edit.native.js b/packages/block-library/src/code/edit.native.js index 563c37dd4b13c..b6f4a8e541b37 100644 --- a/packages/block-library/src/code/edit.native.js +++ b/packages/block-library/src/code/edit.native.js @@ -13,6 +13,11 @@ import { __ } from '@wordpress/i18n'; */ import { PlainText } from '@wordpress/editor'; +/** + * Block code style + */ +import styles from './theme.scss'; + // Note: styling is applied directly to the (nested) PlainText component. Web-side components // apply it to the container 'div' but we don't have a proper proposal for cascading styling yet. export default function CodeEdit( { attributes, setAttributes, style } ) { @@ -20,7 +25,7 @@ export default function CodeEdit( { attributes, setAttributes, style } ) { setAttributes( { content } ) } diff --git a/packages/block-library/src/code/theme.android.scss b/packages/block-library/src/code/theme.android.scss new file mode 100644 index 0000000000000..18d9c4cdcf2dc --- /dev/null +++ b/packages/block-library/src/code/theme.android.scss @@ -0,0 +1,4 @@ +.blockCode { + font-family: monospace; +} + diff --git a/packages/block-library/src/code/theme.ios.scss b/packages/block-library/src/code/theme.ios.scss new file mode 100644 index 0000000000000..c553ba8e275f7 --- /dev/null +++ b/packages/block-library/src/code/theme.ios.scss @@ -0,0 +1,5 @@ +/* stylelint-disable font-family-no-missing-generic-family-keyword */ +.blockCode { + font-family: courier; +} + diff --git a/packages/block-library/src/heading/edit.native.js b/packages/block-library/src/heading/edit.native.js index 30cc236034e97..077d2701c84d3 100644 --- a/packages/block-library/src/heading/edit.native.js +++ b/packages/block-library/src/heading/edit.native.js @@ -13,7 +13,7 @@ import { View } from 'react-native'; */ import { __ } from '@wordpress/i18n'; import { Component } from '@wordpress/element'; -import { RichText } from '@wordpress/editor'; +import { RichText, BlockControls } from '@wordpress/editor'; import { parse, createBlock } from '@wordpress/blocks'; /** @@ -42,7 +42,9 @@ class HeadingEdit extends Component { return ( <View> - <HeadingToolbar minLevel={ 2 } maxLevel={ 5 } selectedLevel={ level } onChange={ ( newLevel ) => setAttributes( { level: newLevel } ) } /> + <BlockControls> + <HeadingToolbar minLevel={ 2 } maxLevel={ 5 } selectedLevel={ level } onChange={ ( newLevel ) => setAttributes( { level: newLevel } ) } /> + </BlockControls> <RichText tagName={ tagName } value={ content } diff --git a/packages/block-library/src/paragraph/edit.native.js b/packages/block-library/src/paragraph/edit.native.js index 0a0216d24865c..c77f28fd556d7 100644 --- a/packages/block-library/src/paragraph/edit.native.js +++ b/packages/block-library/src/paragraph/edit.native.js @@ -11,7 +11,10 @@ import { Component } from '@wordpress/element'; import { parse, createBlock } from '@wordpress/blocks'; import { RichText } from '@wordpress/editor'; -const minHeight = 50; +/** + * Import style + */ +import styles from './style.scss'; const name = 'core/paragraph'; @@ -68,8 +71,8 @@ class ParagraphEdit extends Component { const { attributes, setAttributes, - style, mergeBlocks, + style, } = this.props; const { @@ -77,6 +80,8 @@ class ParagraphEdit extends Component { content, } = attributes; + const minHeight = styles.blockText.minHeight; + return ( <View> <RichText diff --git a/packages/block-library/src/paragraph/style.native.scss b/packages/block-library/src/paragraph/style.native.scss new file mode 100644 index 0000000000000..8724a7ca468ca --- /dev/null +++ b/packages/block-library/src/paragraph/style.native.scss @@ -0,0 +1,3 @@ +.blockText { + min-height: 50; +} diff --git a/packages/components/src/button/index.native.js b/packages/components/src/button/index.native.js index f4d2f2b9542a4..be7f7caf4369b 100644 --- a/packages/components/src/button/index.native.js +++ b/packages/components/src/button/index.native.js @@ -12,9 +12,9 @@ export default function Button( props ) { onPress={ onClick } style={ { borderColor: ariaPressed ? 'black' : 'white', borderWidth: 1, borderRadius: 2 } } > - <View style={ { flex: 1, flexDirection: 'row' } }> + <View style={ { height: 44, width: 44, flexDirection: 'row', justifyContent: 'center', alignItems: 'center' } }> { children } - { subscript && ( <Text style={ { fontVariant: [ 'small-caps' ], textAlignVertical: 'bottom' } }>{ subscript }</Text> ) } + { subscript && ( <Text style={ { fontVariant: [ 'small-caps' ] } }>{ subscript }</Text> ) } </View> </TouchableOpacity> ); diff --git a/packages/components/src/index.native.js b/packages/components/src/index.native.js index e363c136f3628..2fd9eaa5e836e 100644 --- a/packages/components/src/index.native.js +++ b/packages/components/src/index.native.js @@ -3,6 +3,7 @@ export * from './primitives'; export { default as Dashicon } from './dashicon'; export { default as Toolbar } from './toolbar'; export { default as withSpokenMessages } from './higher-order/with-spoken-messages'; +export { createSlotFill, Slot, Fill, Provider as SlotFillProvider } from './slot-fill'; // Higher-Order Components export { default as withFilters } from './higher-order/with-filters'; diff --git a/packages/components/src/toolbar/toolbar-container.native.js b/packages/components/src/toolbar/toolbar-container.native.js index c3504fc40202c..08106a987f408 100644 --- a/packages/components/src/toolbar/toolbar-container.native.js +++ b/packages/components/src/toolbar/toolbar-container.native.js @@ -4,7 +4,7 @@ import { View } from 'react-native'; export default ( props ) => ( - <View style={ { flex: 1, flexDirection: 'row' } }> + <View style={ { flexDirection: 'row' } }> { props.children } </View> ); diff --git a/packages/editor/src/components/index.native.js b/packages/editor/src/components/index.native.js index 9cb399c034a6a..17943dee6b3ae 100644 --- a/packages/editor/src/components/index.native.js +++ b/packages/editor/src/components/index.native.js @@ -3,4 +3,6 @@ export * from './font-sizes'; export { default as PlainText } from './plain-text'; export { default as RichText } from './rich-text'; export { default as MediaPlaceholder } from './media-placeholder'; +export { default as BlockFormatControls } from './block-format-controls'; +export { default as BlockControls } from './block-controls'; export { default as BlockEdit } from './block-edit'; diff --git a/packages/editor/src/components/rich-text/index.native.js b/packages/editor/src/components/rich-text/index.native.js index c0fb04867bde4..7fe26564cae5e 100644 --- a/packages/editor/src/components/rich-text/index.native.js +++ b/packages/editor/src/components/rich-text/index.native.js @@ -14,6 +14,7 @@ import { import { Component, RawHTML } from '@wordpress/element'; import { withInstanceId, compose } from '@wordpress/compose'; import { Toolbar } from '@wordpress/components'; +import { BlockFormatControls } from '@wordpress/editor'; import { isEmpty, create, @@ -342,9 +343,9 @@ export class RichText extends Component { return ( <View> - <View style={ { flex: 1 } }> + <BlockFormatControls> <Toolbar controls={ toolbarControls } /> - </View> + </BlockFormatControls> <RCTAztecView ref={ ( ref ) => { this._editor = ref; From 1ac70e14a0986a9e9ff93386f3a76aaaa7ef53f8 Mon Sep 17 00:00:00 2001 From: Riad Benguella <benguella@gmail.com> Date: Wed, 7 Nov 2018 16:54:55 +0100 Subject: [PATCH 4/4] Fix the isBeingScheduled Selector. (#11572) * Fix publish button label (schedule instead of publish) * Fix the isBeingScheduledSelector calculation * Tweak function comments * Clarify test comment Co-Authored-By: youknowriad <benguella@gmail.com> --- packages/date/src/index.js | 17 ++++++++++- packages/date/src/test/index.js | 40 ++++++++++++++++++++++++++ packages/editor/src/store/selectors.js | 6 ++-- 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 packages/date/src/test/index.js diff --git a/packages/date/src/index.js b/packages/date/src/index.js index bcc1e4d32be6d..8580f97062f27 100644 --- a/packages/date/src/index.js +++ b/packages/date/src/index.js @@ -395,7 +395,7 @@ export function dateI18n( dateFormat, dateValue = new Date(), gmt = false ) { /** * Check whether a date is considered in the future according to the WordPress settings. * - * @param {(Date|string)} dateValue Date object or string. + * @param {string} dateValue Date String or Date object in the Defined WP Timezone. * * @return {boolean} Is in the future. */ @@ -406,4 +406,19 @@ export function isInTheFuture( dateValue ) { return momentObject.isAfter( now ); } +/** + * Create and return a JavaScript Date Object from a date string in the WP timezone. + * + * @param {string?} dateString Date formatted in the WP timezone. + * + * @return {Date} Date + */ +export function getDate( dateString ) { + if ( ! dateString ) { + return momentLib.tz( 'WP' ).toDate(); + } + + return momentLib.tz( dateString, 'WP' ).toDate(); +} + setupWPTimezone(); diff --git a/packages/date/src/test/index.js b/packages/date/src/test/index.js new file mode 100644 index 0000000000000..f18e2b0915825 --- /dev/null +++ b/packages/date/src/test/index.js @@ -0,0 +1,40 @@ +/** + * Internal dependencies + */ +import { isInTheFuture, getDate, setSettings, __experimentalGetSettings } from '../'; + +describe( 'isInTheFuture', () => { + it( 'should return true if the date is in the future', () => { + // Create a Date object 1 minute in the future. + const date = new Date( Number( getDate() ) + ( 1000 * 60 ) ); + + expect( isInTheFuture( date ) ).toBe( true ); + } ); + + it( 'should return true if the date is in the past', () => { + // Create a Date object 1 minute in the past. + const date = new Date( Number( getDate() ) - ( 1000 * 60 ) ); + + expect( isInTheFuture( date ) ).toBe( false ); + } ); + + it( 'should ignore the timezone', () => { + const settings = __experimentalGetSettings(); + + // Set a timezone in the future + setSettings( { + ...settings, + timezone: { offset: '4', string: '' }, + } ); + // Create a Date object 1 minute in the past. + let date = new Date( Number( getDate() ) - ( 1000 * 60 ) ); + expect( isInTheFuture( date ) ).toBe( false ); + + // Create a Date object 1 minute in the future. + date = new Date( Number( getDate() ) + ( 1000 * 60 ) ); + expect( isInTheFuture( date ) ).toBe( true ); + + // Restore default settings + setSettings( settings ); + } ); +} ); diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index f405c90cbe272..a4e426507f816 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -32,7 +32,7 @@ import { getFreeformContentHandlerName, isUnmodifiedDefaultBlock, } from '@wordpress/blocks'; -import { isInTheFuture } from '@wordpress/date'; +import { isInTheFuture, getDate } from '@wordpress/date'; import { removep } from '@wordpress/autop'; import { select } from '@wordpress/data'; import deprecated from '@wordpress/deprecated'; @@ -333,7 +333,7 @@ export function isCurrentPostPublished( state ) { const post = getCurrentPost( state ); return [ 'publish', 'private' ].indexOf( post.status ) !== -1 || - ( post.status === 'future' && ! isInTheFuture( new Date( Number( new Date( post.date ) ) + ONE_MINUTE_IN_MS ) ) ); + ( post.status === 'future' && ! isInTheFuture( new Date( Number( getDate( post.date ) ) - ONE_MINUTE_IN_MS ) ) ); } /** @@ -493,7 +493,7 @@ export function hasAutosave( state ) { export function isEditedPostBeingScheduled( state ) { const date = getEditedPostAttribute( state, 'date' ); // Offset the date by one minute (network latency) - const checkedDate = new Date( Number( new Date( date ) ) + ONE_MINUTE_IN_MS ); + const checkedDate = new Date( Number( getDate( date ) ) - ONE_MINUTE_IN_MS ); return isInTheFuture( checkedDate ); }