From 8fd66e5bfc3b61d851760cffc413bc8a4ddb21bc Mon Sep 17 00:00:00 2001 From: epiqueras Date: Wed, 15 Jan 2020 13:51:12 -0500 Subject: [PATCH 01/66] Components: Implement a combobox control. --- docs/manifest.json | 6 + package-lock.json | 4 +- .../components/src/combobox-control/README.md | 146 ++++++++++++++++++ .../components/src/combobox-control/index.js | 126 +++++++++++++++ .../src/combobox-control/stories/index.js | 53 +++++++ .../src/combobox-control/style.scss | 70 +++++++++ .../src/custom-select-control/README.md | 44 +++--- packages/components/src/style.scss | 1 + 8 files changed, 430 insertions(+), 20 deletions(-) create mode 100644 packages/components/src/combobox-control/README.md create mode 100644 packages/components/src/combobox-control/index.js create mode 100644 packages/components/src/combobox-control/stories/index.js create mode 100644 packages/components/src/combobox-control/style.scss diff --git a/docs/manifest.json b/docs/manifest.json index e7293389ef83c..678dd15a40966 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -707,6 +707,12 @@ "markdown_source": "../packages/components/src/color-picker/README.md", "parent": "components" }, + { + "title": "ComboboxControl", + "slug": "combobox-control", + "markdown_source": "../packages/components/src/combobox-control/README.md", + "parent": "components" + }, { "title": "CustomSelectControl", "slug": "custom-select-control", diff --git a/package-lock.json b/package-lock.json index 089fec0a2fd9e..b172eb0014907 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20770,7 +20770,7 @@ }, "node-pre-gyp": { "version": "0.12.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz", + "resolved": false, "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", "dev": true, "optional": true, @@ -20801,7 +20801,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "resolved": false, "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, diff --git a/packages/components/src/combobox-control/README.md b/packages/components/src/combobox-control/README.md new file mode 100644 index 0000000000000..f888a3211e364 --- /dev/null +++ b/packages/components/src/combobox-control/README.md @@ -0,0 +1,146 @@ +# ComboboxControl + +`ComboboxControl` is an enhanced version of a [`CustomSelectControl`](/packages/components/src/custom-select-control/readme.md), with the addition of being able to search for options using a search input. + +## Table of contents + +1. [Design guidelines](#design-guidelines) +2. [Development guidelines](#development-guidelines) +3. [Related components](#related-components) + +## Design guidelines + +These are the same as [the ones for `CustomSelectControl`s](/packages/components/src/select-control/readme.md#design-guidelines), but this component is better suited for when there are too many items to scroll through or load at once so you need to filter them based on user input. + +## Development guidelines + +### Usage + +```jsx +/** + * WordPress dependencies + */ +import { ComboboxControl } from "@wordpress/components"; +import { useState } from "@wordpress/compose"; + +const options = [ + { + key: "small", + name: "Small", + style: { fontSize: "50%" } + }, + { + key: "normal", + name: "Normal", + style: { fontSize: "100%" } + }, + { + key: "large", + name: "Large", + style: { fontSize: "200%" } + }, + { + key: "huge", + name: "Huge", + style: { fontSize: "300%" } + } +]; + +function MyComboboxControl() { + const [, setFontSize] = useState(); + const [filteredOptions, setFilteredOptions] = useState(options); + return ( + + setFilteredOptions( + options.filter(option => + option.name.toLowerCase().startsWith(inputValue.toLowerCase()) + ) + ) + } + onChange={({ selectedItem }) => setFontSize(selectedItem)} + /> + ); +} + +function MyControlledComboboxControl() { + const [fontSize, setFontSize] = useState(options[0]); + const [filteredOptions, setFilteredOptions] = useState(options); + return ( + + setFilteredOptions( + options.filter(option => + option.name.toLowerCase().startsWith(inputValue.toLowerCase()) + ) + ) + } + onChange={({ selectedItem }) => setFontSize(selectedItem)} + value={options.find(option => option.key === fontSize.key)} + /> + ); +} +``` + +### Props + +#### className + +A custom class name to append to the outer `
`. + +- Type: `String` +- Required: No + +#### hideLabelFromVision + +Used to visually hide the label. It will always be visible to screen readers. + +- Type: `Boolean` +- Required: No + +#### label + +The label for the control. + +- Type: `String` +- Required: Yes + +#### options + +The options that can be chosen from. + +- Type: `Array<{ key: String, name: String, style: ?{}, ...rest }>` +- Required: Yes + +#### onInputValueChange + +Function called with the control's search input value changes. The `inputValue` property contains the next input value. + +- Type: `Function` +- Required: No + +#### onChange + +Function called with the control's internal state changes. The `selectedItem` property contains the next selected item. + +- Type: `Function` +- Required: No + +#### value + +Can be used to externally control the value of the control, like in the `MyControlledComboboxControl` example above. + +- Type: `Object` +- Required: No + +## Related components + +- Like this component, but without a search input, the `CustomSelectControl` component. + +- To select one option from a set, when you want to show all the available options at once, use the `Radio` component. +- To select one or more items from a set, use the `CheckboxControl` component. +- To toggle a single setting on or off, use the `ToggleControl` component. diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js new file mode 100644 index 0000000000000..a8befe7416e5a --- /dev/null +++ b/packages/components/src/combobox-control/index.js @@ -0,0 +1,126 @@ +/** + * External dependencies + */ +import { useCombobox } from 'downshift'; +import classnames from 'classnames'; + +/** + * Internal dependencies + */ +import { Button, Dashicon } from '../'; + +const itemToString = ( item ) => item && item.name; +export default function ComboboxControl( { + className, + hideLabelFromVision, + label, + options: items, + onInputValueChange: onInputValueChange, + onChange: onSelectedItemChange, + value: _selectedItem, +} ) { + const { + getLabelProps, + getToggleButtonProps, + getComboboxProps, + getInputProps, + getMenuProps, + getItemProps, + isOpen, + highlightedIndex, + selectedItem, + } = useCombobox( { + initialSelectedItem: items[ 0 ], + items, + itemToString, + onInputValueChange, + onSelectedItemChange, + selectedItem: _selectedItem, + } ); + const menuProps = getMenuProps( { + className: 'components-combobox-control__menu', + } ); + // We need this here, because the null active descendant is not + // fully ARIA compliant. + if ( + menuProps[ 'aria-activedescendant' ] && + menuProps[ 'aria-activedescendant' ].slice( + 0, + 'downshift-null'.length + ) === 'downshift-null' + ) { + delete menuProps[ 'aria-activedescendant' ]; + } + return ( +
+ { /* eslint-disable-next-line jsx-a11y/label-has-associated-control, jsx-a11y/label-has-for */ } + +
+ + +
+
    + { isOpen && + items.map( ( item, index ) => ( + // eslint-disable-next-line react/jsx-key +
  • + { item === selectedItem && ( + + ) } + { item.name } +
  • + ) ) } +
+
+ ); +} diff --git a/packages/components/src/combobox-control/stories/index.js b/packages/components/src/combobox-control/stories/index.js new file mode 100644 index 0000000000000..aa621666466fe --- /dev/null +++ b/packages/components/src/combobox-control/stories/index.js @@ -0,0 +1,53 @@ +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import ComboboxControl from '../'; + +export default { title: 'ComboboxControl', component: ComboboxControl }; + +const options = [ + { + key: 'small', + name: 'Small', + style: { fontSize: '50%' }, + }, + { + key: 'normal', + name: 'Normal', + style: { fontSize: '100%' }, + }, + { + key: 'large', + name: 'Large', + style: { fontSize: '200%' }, + }, + { + key: 'huge', + name: 'Huge', + style: { fontSize: '300%' }, + }, +]; +function ComboboxControlWithState() { + const [ filteredOptions, setFilteredOptions ] = useState( options ); + return ( + + setFilteredOptions( + options.filter( ( option ) => + option.name + .toLowerCase() + .startsWith( inputValue.toLowerCase() ) + ) + ) + } + /> + ); +} +export const _default = () => ; diff --git a/packages/components/src/combobox-control/style.scss b/packages/components/src/combobox-control/style.scss new file mode 100644 index 0000000000000..655221c2b9c2d --- /dev/null +++ b/packages/components/src/combobox-control/style.scss @@ -0,0 +1,70 @@ +.components-combobox-control { + color: $dark-gray-500; + position: relative; +} + +.components-combobox-control__label { + display: block; + margin-bottom: 5px; +} + +.components-combobox-control__button { + border: 1px solid $dark-gray-200; + border-radius: 4px; + color: $dark-gray-500; + display: inline-block; + min-height: 30px; + min-width: 130px; + position: relative; + text-align: left; + + &:focus { + border-color: $blue-medium-500; + } + + &-input { + border: none; + height: calc(100% - 2px); + left: 1px; + padding: 0 4px; + position: absolute; + top: 1px; + width: calc(100% - 2px); + } + + &-button:hover { + box-shadow: none !important; + } + + &-icon { + height: 100%; + padding: 0 4px; + position: absolute; + right: 0; + top: 0; + } +} + +.components-combobox-control__menu { + background: $white; + min-width: 100%; + padding: 0; + position: absolute; + z-index: z-index(".components-popover"); +} + +.components-combobox-control__item { + align-items: center; + display: flex; + list-style-type: none; + padding: 10px 5px 10px 25px; + + &.is-highlighted { + background: $light-gray-500; + } + + &-icon { + margin-left: -20px; + margin-right: 0; + } +} diff --git a/packages/components/src/custom-select-control/README.md b/packages/components/src/custom-select-control/README.md index 62dc6920b49a2..8da7d6842e3db 100644 --- a/packages/components/src/custom-select-control/README.md +++ b/packages/components/src/custom-select-control/README.md @@ -20,8 +20,8 @@ These are the same as [the ones for `SelectControl`s](/packages/components/src/s /** * WordPress dependencies */ -import { CustomSelectControl } from "@wordpress/components"; -import { useState } from "@wordpress/compose"; +import { CustomSelectControl } from '@wordpress/components'; +import { useState } from '@wordpress/compose'; const options = [ { @@ -75,43 +75,51 @@ function MyControlledCustomSelectControl() { #### className A custom class name to append to the outer `
`. -- Type: `String` -- Required: No + +- Type: `String` +- Required: No #### hideLabelFromVision Used to visually hide the label. It will always be visible to screen readers. -- Type: `Boolean` -- Required: No + +- Type: `Boolean` +- Required: No #### label The label for the control. -- Type: `String` -- Required: Yes + +- Type: `String` +- Required: Yes #### options The options that can be chosen from. -- Type: `Array<{ key: String, name: String, style: ?{}, ...rest }>` -- Required: Yes + +- Type: `Array<{ key: String, name: String, style: ?{}, ...rest }>` +- Required: Yes #### onChange Function called with the control's internal state changes. The `selectedItem` property contains the next selected item. -- Type: `Function` -- Required: No + +- Type: `Function` +- Required: No #### value Can be used to externally control the value of the control, like in the `MyControlledCustomSelectControl` example above. -- Type: `Object` -- Required: No + +- Type: `Object` +- Required: No ## Related components -- Like this component, but implemented using a native `` for when custom styling is not necessary, the `SelectControl` component. + +- To select one option from a set, when you want to show all the available options at once, use the `Radio` component. +- To select one or more items from a set, use the `CheckboxControl` component. +- To toggle a single setting on or off, use the `ToggleControl` component. -- To select one option from a set, when you want to show all the available options at once, use the `Radio` component. -- To select one or more items from a set, use the `CheckboxControl` component. -- To toggle a single setting on or off, use the `ToggleControl` component. +- If you have a lot of items, `ComboboxControl` might be a better fit. diff --git a/packages/components/src/style.scss b/packages/components/src/style.scss index 83e26e37cb09a..5fe4afbb8305e 100644 --- a/packages/components/src/style.scss +++ b/packages/components/src/style.scss @@ -8,6 +8,7 @@ @import "./circular-option-picker/style.scss"; @import "./color-indicator/style.scss"; @import "./color-picker/style.scss"; +@import "./combobox-control/style.scss"; @import "./custom-gradient-picker/style.scss"; @import "./custom-select-control/style.scss"; @import "./dashicon/style.scss"; From c0bc82f19ead233e8f5f74f4bfc56172bbde0af0 Mon Sep 17 00:00:00 2001 From: epiqueras Date: Wed, 19 Feb 2020 22:07:15 -0800 Subject: [PATCH 02/66] Components: Update Downshift. --- package-lock.json | 2 +- packages/components/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index b172eb0014907..b92e45f894a32 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9944,7 +9944,7 @@ "classnames": "^2.2.5", "clipboard": "^2.0.1", "dom-scroll-into-view": "^1.2.1", - "downshift": "^4.0.5", + "downshift": "^5.0.3", "gradient-parser": "^0.1.5", "lodash": "^4.17.15", "memize": "^1.1.0", diff --git a/packages/components/package.json b/packages/components/package.json index 629ece0260c0c..dcaa52875cdbb 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -45,7 +45,7 @@ "classnames": "^2.2.5", "clipboard": "^2.0.1", "dom-scroll-into-view": "^1.2.1", - "downshift": "^4.0.5", + "downshift": "^5.0.3", "gradient-parser": "^0.1.5", "lodash": "^4.17.15", "memize": "^1.1.0", From 35ed6827667f0f8fb0984e26f832c3da06313c9b Mon Sep 17 00:00:00 2001 From: epiqueras Date: Mon, 18 May 2020 14:11:02 -0700 Subject: [PATCH 03/66] Components: Update Downshift. --- package-lock.json | 30 +++++++++++++++--------------- packages/components/package.json | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index b92e45f894a32..567e5ec896d6c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9944,7 +9944,7 @@ "classnames": "^2.2.5", "clipboard": "^2.0.1", "dom-scroll-into-view": "^1.2.1", - "downshift": "^5.0.3", + "downshift": "^5.4.0", "gradient-parser": "^0.1.5", "lodash": "^4.17.15", "memize": "^1.1.0", @@ -14923,9 +14923,9 @@ } }, "compute-scroll-into-view": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.11.tgz", - "integrity": "sha512-uUnglJowSe0IPmWOdDtrlHXof5CTIJitfJEyITHBW6zDVOGu9Pjk5puaLM73SLcwak0L4hEjO7Td88/a6P5i7A==" + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.13.tgz", + "integrity": "sha512-o+w9w7A98aAFi/GjK8cxSV+CdASuPa2rR5UWs3+yHkJzWqaKoBEufFNWYaXInCSmUfDCVhesG+v9MTWqOjsxFg==" }, "computed-style": { "version": "0.1.4", @@ -17028,20 +17028,20 @@ } }, "downshift": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/downshift/-/downshift-4.0.7.tgz", - "integrity": "sha512-w6KFbpnMZrO53Lcbh21lRTSokEvz+FCdv7fAtN8+Oxvst+qUTIy/2FQCX6AQUncRb/gOqG4aBqm2fGgbsmAiGg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/downshift/-/downshift-5.4.0.tgz", + "integrity": "sha512-r3ikikP6H/2c+WSWcP/1nOwBSXwmyiuH3LeEmsjKumWjqd+FAazNUIa/ox2VA+qQ86JuaAIaA4xw79G3Sz/XMA==", "requires": { - "@babel/runtime": "^7.4.5", - "compute-scroll-into-view": "^1.0.9", + "@babel/runtime": "^7.9.1", + "compute-scroll-into-view": "^1.0.13", "prop-types": "^15.7.2", - "react-is": "^16.9.0" + "react-is": "^16.13.1" }, "dependencies": { "react-is": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", - "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==" + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" } } }, @@ -20770,7 +20770,7 @@ }, "node-pre-gyp": { "version": "0.12.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz", "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", "dev": true, "optional": true, @@ -20801,7 +20801,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, diff --git a/packages/components/package.json b/packages/components/package.json index dcaa52875cdbb..3e3dcbb17aa5f 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -45,7 +45,7 @@ "classnames": "^2.2.5", "clipboard": "^2.0.1", "dom-scroll-into-view": "^1.2.1", - "downshift": "^5.0.3", + "downshift": "^5.4.0", "gradient-parser": "^0.1.5", "lodash": "^4.17.15", "memize": "^1.1.0", From e7dcb29831b48569a88b35c0f635afc98b0511bf Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 15 Jun 2020 18:06:13 -0600 Subject: [PATCH 04/66] New post author selector, initial scaffolding. --- .../components/src/combobox-control/index.js | 6 +- packages/core-data/src/resolvers.js | 2 +- .../src/components/post-author/index.js | 20 +--- .../editor/src/components/post-author/new.js | 110 ++++++++++++++++++ 4 files changed, 121 insertions(+), 17 deletions(-) create mode 100644 packages/editor/src/components/post-author/new.js diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js index a8befe7416e5a..475068820c8a1 100644 --- a/packages/components/src/combobox-control/index.js +++ b/packages/components/src/combobox-control/index.js @@ -18,6 +18,7 @@ export default function ComboboxControl( { onInputValueChange: onInputValueChange, onChange: onSelectedItemChange, value: _selectedItem, + initialSelectedItem, } ) { const { getLabelProps, @@ -30,12 +31,11 @@ export default function ComboboxControl( { highlightedIndex, selectedItem, } = useCombobox( { - initialSelectedItem: items[ 0 ], items, itemToString, onInputValueChange, onSelectedItemChange, - selectedItem: _selectedItem, + selectedItem: _selectedItem || initialSelectedItem, } ); const menuProps = getMenuProps( { className: 'components-combobox-control__menu', @@ -51,6 +51,8 @@ export default function ComboboxControl( { ) { delete menuProps[ 'aria-activedescendant' ]; } + /* eslint-disable no-console */ + console.log( 'ComboboxControl initialSelectedItem', initialSelectedItem ); return (
- - + ); /* eslint-enable jsx-a11y/no-onchange */ diff --git a/packages/editor/src/components/post-author/new.js b/packages/editor/src/components/post-author/new.js new file mode 100644 index 0000000000000..9a4e5bc6059cf --- /dev/null +++ b/packages/editor/src/components/post-author/new.js @@ -0,0 +1,110 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { withInstanceId, compose } from '@wordpress/compose'; +import { withSelect, withDispatch } from '@wordpress/data'; +import ComboboxControl from '../../../../components/build/combobox-control/'; +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import PostAuthorCheck from './check'; + +/* eslint-disable no-console */ +console.log( 'ComboboxControl', ComboboxControl ); + +function NewPostAuthor( { postAuthor, instanceId, authors } ) { + let mappedAuthors = []; + authors.map( ( author, i ) => { + mappedAuthors = [ + ...mappedAuthors, + { + key: i, + name: author.name, + value: author.name, + id: author.id, + }, + ]; + } ); + /* eslint-disable no-console */ + + const [ filteredAuthors, setFilteredAuthors ] = useState( mappedAuthors ); + const foundAuthor = filteredAuthors.filter( + ( author ) => postAuthor === author.id + ); + const [ selectedAuthor, setSelectedAuthor ] = useState( foundAuthor[ 0 ] ); + const handleSelect = ( selectedItem, downshift ) => { + setSelectedAuthor( selectedItem ); + downshift.reset(); + }; + + const handleKeydown = ( { + event, + isOpen, + selectHighlightedItem, + inputValue, + } ) => { + console.log( 'handleKeydown', { + event, + isOpen, + selectHighlightedItem, + inputValue, + } ); + }; + + const setAuthorId = ( event ) => { + const { onUpdateAuthor } = this.props; + const { value } = event.target; + onUpdateAuthor( Number( value ) ); + }; + + const selectId = 'post-author-selector-' + instanceId; + console.log( selectedAuthor ); + + return ( + + + { + handleKeydown( { + event, + isOpen, + selectHighlightedItem, + inputValue, + } ); + } } + onSelectedItemChange={ ( { selectedItem } ) => { + console.log( 'onSelectedItemChange', selectedItem ); + setSelectedAuthor( selectedItem ); + } } + /> + + ); + /* eslint-enable jsx-a11y/no-onchange */ +} + +export default compose( [ + withSelect( ( select ) => { + return { + postAuthor: select( 'core/editor' ).getEditedPostAttribute( + 'author' + ), + authors: select( 'core' ).getAuthors(), + }; + } ), + withDispatch( ( dispatch ) => ( { + onUpdateAuthor( author ) { + dispatch( 'core/editor' ).editPost( { author } ); + }, + } ) ), + withInstanceId, +] )( NewPostAuthor ); From d4c149fc1aea493db805ebf0b769da02a6e0eea8 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 17 Jun 2020 07:32:57 -0600 Subject: [PATCH 05/66] New post author selector, async work. --- .../developers/data/data-core.md | 12 ++++ .../components/src/combobox-control/index.js | 62 +++++++++++-------- packages/core-data/README.md | 12 ++++ packages/core-data/src/resolvers.js | 9 +++ packages/core-data/src/selectors.js | 11 ++++ .../editor/src/components/post-author/new.js | 49 ++++++++++++--- 6 files changed, 119 insertions(+), 36 deletions(-) diff --git a/docs/designers-developers/developers/data/data-core.md b/docs/designers-developers/developers/data/data-core.md index 142538c635468..34ada5ec168c3 100644 --- a/docs/designers-developers/developers/data/data-core.md +++ b/docs/designers-developers/developers/data/data-core.md @@ -27,6 +27,18 @@ _Returns_ - `(boolean|undefined)`: Whether or not the user can perform the action, or `undefined` if the OPTIONS request is still being made. +# **getAuthor** + +Returns all available authors. + +_Parameters_ + +- _state_ `Object`: Data state. + +_Returns_ + +- `Array`: Authors list. + # **getAuthors** Returns all available authors. diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js index 475068820c8a1..e43f863ef5c5f 100644 --- a/packages/components/src/combobox-control/index.js +++ b/packages/components/src/combobox-control/index.js @@ -3,6 +3,7 @@ */ import { useCombobox } from 'downshift'; import classnames from 'classnames'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -19,6 +20,8 @@ export default function ComboboxControl( { onChange: onSelectedItemChange, value: _selectedItem, initialSelectedItem, + initialInputValue, + isLoading, } ) { const { getLabelProps, @@ -35,7 +38,10 @@ export default function ComboboxControl( { itemToString, onInputValueChange, onSelectedItemChange, - selectedItem: _selectedItem || initialSelectedItem, + selectedItem: _selectedItem, + initialSelectedItem, + initialInputValue, + initialIsOpen: false, } ); const menuProps = getMenuProps( { className: 'components-combobox-control__menu', @@ -96,31 +102,35 @@ export default function ComboboxControl( {
    { isOpen && - items.map( ( item, index ) => ( - // eslint-disable-next-line react/jsx-key -
  • - { item === selectedItem && ( - - ) } - { item.name } -
  • + ( isLoading ? ( +
    { __( 'Loading...' ) }
    + ) : ( + items.map( ( item, index ) => ( + // eslint-disable-next-line react/jsx-key +
  • + { item === selectedItem && ( + + ) } + { item.name } +
  • + ) ) ) ) }
diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 5e2d337eabea4..3cc077c693b8e 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -252,6 +252,18 @@ _Returns_ - `(boolean|undefined)`: Whether or not the user can perform the action, or `undefined` if the OPTIONS request is still being made. +# **getAuthor** + +Returns all available authors. + +_Parameters_ + +- _state_ `Object`: Data state. + +_Returns_ + +- `Array`: Authors list. + # **getAuthors** Returns all available authors. diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 97b280415768a..341269f87920b 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -35,6 +35,15 @@ export function* getAuthors() { } ); yield receiveUserQuery( 'authors', users ); } +/** + * Request a single author from the REST API. + */ +export function* getAuthor( id = '' ) { + const users = yield apiFetch( { + path: `/wp/v2/users/${ id }?who=authors&per_page=1`, + } ); + yield receiveUserQuery( 'author', users ); +} /** * Requests the current user from the REST API. diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index 815ff19031547..8cba20f7403bb 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -75,6 +75,17 @@ export const getUserQueryResults = createSelector( ( state, queryID ) => [ state.users.queries[ queryID ], state.users.byId ] ); +/** + * Returns all available authors. + * + * @param {Object} state Data state. + * + * @return {Array} Authors list. + */ +export function getAuthor( state ) { + return getUserQueryResults( state, 'author' ); +} + /** * Returns whether the entities for the give kind are loaded. * diff --git a/packages/editor/src/components/post-author/new.js b/packages/editor/src/components/post-author/new.js index 9a4e5bc6059cf..1198bb9d77e5a 100644 --- a/packages/editor/src/components/post-author/new.js +++ b/packages/editor/src/components/post-author/new.js @@ -6,16 +6,23 @@ import { withInstanceId, compose } from '@wordpress/compose'; import { withSelect, withDispatch } from '@wordpress/data'; import ComboboxControl from '../../../../components/build/combobox-control/'; import { useState } from '@wordpress/element'; +import apiRequest from '@wordpress/api-request'; /** * Internal dependencies */ import PostAuthorCheck from './check'; +import { debounce } from 'lodash'; + /* eslint-disable no-console */ -console.log( 'ComboboxControl', ComboboxControl ); function NewPostAuthor( { postAuthor, instanceId, authors } ) { + console.log( 'postAuthor', postAuthor ); + if ( 0 === postAuthor.length ) { + return null; + } + const currentPostAuthor = postAuthor[ 0 ]; let mappedAuthors = []; authors.map( ( author, i ) => { mappedAuthors = [ @@ -28,13 +35,16 @@ function NewPostAuthor( { postAuthor, instanceId, authors } ) { }, ]; } ); - /* eslint-disable no-console */ - const [ filteredAuthors, setFilteredAuthors ] = useState( mappedAuthors ); - const foundAuthor = filteredAuthors.filter( - ( author ) => postAuthor === author.id + const [ isLoading, setIsLoading ] = useState( false ); + const foundAuthor = mappedAuthors.filter( + ( author ) => currentPostAuthor.id === author.id ); - const [ selectedAuthor, setSelectedAuthor ] = useState( foundAuthor[ 0 ] ); + if ( foundAuthor.length === 0 ) { + mappedAuthors = [ ...mappedAuthors, currentPostAuthor ]; + } + const [ filteredAuthors, setFilteredAuthors ] = useState( mappedAuthors ); + const [ selectedAuthor, setSelectedAuthor ] = useState( currentPostAuthor ); const handleSelect = ( selectedItem, downshift ) => { setSelectedAuthor( selectedItem ); downshift.reset(); @@ -52,8 +62,25 @@ function NewPostAuthor( { postAuthor, instanceId, authors } ) { selectHighlightedItem, inputValue, } ); + suggestAuthor( inputValue ); }; + const suggestAuthor = debounce( ( query, populateResults ) => { + const payload = '?search=' + encodeURIComponent( query ); + setIsLoading( true ); + apiRequest( { path: '/wp/v2/users' + payload } ).done( ( results ) => { + setFilteredAuthors( + results.map( ( author, i ) => ( { + key: i, + name: author.name, + value: author.name, + id: author.id, + } ) ) + ); + setIsLoading( false ); + } ); + }, 150 ); + const setAuthorId = ( event ) => { const { onUpdateAuthor } = this.props; const { value } = event.target; @@ -67,8 +94,10 @@ function NewPostAuthor( { postAuthor, instanceId, authors } ) { { + onChange={ ( { selectedItem } ) => { console.log( 'onSelectedItemChange', selectedItem ); setSelectedAuthor( selectedItem ); } } @@ -95,8 +124,8 @@ function NewPostAuthor( { postAuthor, instanceId, authors } ) { export default compose( [ withSelect( ( select ) => { return { - postAuthor: select( 'core/editor' ).getEditedPostAttribute( - 'author' + postAuthor: select( 'core' ).getAuthor( + select( 'core/editor' ).getEditedPostAttribute( 'author' ) ), authors: select( 'core' ).getAuthors(), }; From 1fe770033ab0702deea0a4f62f41f8c90ded8145 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 19 Jun 2020 10:16:23 -0600 Subject: [PATCH 06/66] Complete initial implementation. --- .../components/src/combobox-control/index.js | 15 +- .../post-author/enhanced-post-author.js | 116 +++++++++++++++ .../src/components/post-author/index.js | 43 +++++- .../editor/src/components/post-author/new.js | 139 ------------------ 4 files changed, 161 insertions(+), 152 deletions(-) create mode 100644 packages/editor/src/components/post-author/enhanced-post-author.js delete mode 100644 packages/editor/src/components/post-author/new.js diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js index e43f863ef5c5f..8588386e90837 100644 --- a/packages/components/src/combobox-control/index.js +++ b/packages/components/src/combobox-control/index.js @@ -1,9 +1,12 @@ +/* eslint-disable no-console */ + /** * External dependencies */ import { useCombobox } from 'downshift'; import classnames from 'classnames'; import { __ } from '@wordpress/i18n'; +import { Spinner } from '@wordpress/components'; /** * Internal dependencies @@ -19,7 +22,7 @@ export default function ComboboxControl( { onInputValueChange: onInputValueChange, onChange: onSelectedItemChange, value: _selectedItem, - initialSelectedItem, + initialHighlightedIndex, initialInputValue, isLoading, } ) { @@ -39,10 +42,11 @@ export default function ComboboxControl( { onInputValueChange, onSelectedItemChange, selectedItem: _selectedItem, - initialSelectedItem, + initialHighlightedIndex, initialInputValue, initialIsOpen: false, } ); + const menuProps = getMenuProps( { className: 'components-combobox-control__menu', } ); @@ -57,8 +61,7 @@ export default function ComboboxControl( { ) { delete menuProps[ 'aria-activedescendant' ]; } - /* eslint-disable no-console */ - console.log( 'ComboboxControl initialSelectedItem', initialSelectedItem ); + return (
{ isOpen && ( isLoading ? ( -
{ __( 'Loading...' ) }
+ + { __( 'Loading' ) } + ) : ( items.map( ( item, index ) => ( // eslint-disable-next-line react/jsx-key diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js new file mode 100644 index 0000000000000..110be8a805c58 --- /dev/null +++ b/packages/editor/src/components/post-author/enhanced-post-author.js @@ -0,0 +1,116 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { withInstanceId, compose } from '@wordpress/compose'; +import { withSelect, withDispatch } from '@wordpress/data'; +import ComboboxControl from '../../../../components/build/combobox-control'; +import { useState, useEffect } from '@wordpress/element'; +import apiRequest from '@wordpress/api-request'; + +/** + * External dependencies + */ +import { debounce } from 'lodash'; + +function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { + // Wait until we have the post author before displaying the component. + if ( 0 === postAuthor.length ) { + return null; + } + const currentPostAuthor = postAuthor[ 0 ]; + let initialAuthors = []; + authors.forEach( ( author, i ) => { + initialAuthors = [ + ...initialAuthors, + { + key: i, + name: author.name, + value: author.name, + id: author.id, + }, + ]; + } ); + + // Ensure the current author is included in the initial dropdown list. + let foundAuthor = initialAuthors.findIndex( + ( author ) => currentPostAuthor.id === author.id + ); + if ( foundAuthor < 0 ) { + initialAuthors = [ currentPostAuthor, ...initialAuthors ]; + foundAuthor = 0; + } + + // The search result loading state. + const [ isLoadingSearchResults, setIsLoadingSearchResult ] = useState( + false + ); + + // The list of authors available in the dropdown. + const [ availableAuthors, setAvailableAuthors ] = useState( + initialAuthors + ); + + // The currently selected author. + const [ selectedAuthor, setSelectedAuthor ] = useState( currentPostAuthor ); + + /** + * Handle author selection. + * + * @param {object} selectedItem The selected Author. + */ + const handleSelect = ( { selectedItem } ) => { + setSelectedAuthor( selectedItem ); + onUpdateAuthor( selectedItem.id ); + }; + + /** + * Handle user input. + * + * @param {object} param0 Contains a single property `inputValue` with the string value of the input field. + */ + const handleKeydown = ( { inputValue } ) => { + if ( '' === inputValue ) { + // When the field is cleared, reset the author list to the original list. + setAvailableAuthors( initialAuthors ); + } else { + // Otherwise search for authors matching the input. + searchAuthors( inputValue ); + } + }; + + /** + * Search for authors from the rest API. + * + * @param string query The string to search for. + **/ + const searchAuthors = debounce( ( query ) => { + const payload = '?search=' + encodeURIComponent( query ); + setIsLoadingSearchResult( true ); + apiRequest( { path: '/wp/v2/users' + payload } ).done( ( results ) => { + setAvailableAuthors( + results.map( ( author, i ) => ( { + key: i, + name: author.name, + value: author.name, + id: author.id, + } ) ) + ); + setIsLoadingSearchResult( false ); + } ); + }, 150 ); + + return ( + + ); +} + +export default EnhancedPostAuthor; diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index 7e651b996acef..791e9f1cd876a 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -6,7 +6,7 @@ import { withInstanceId, compose } from '@wordpress/compose'; import { Component } from '@wordpress/element'; import { withSelect, withDispatch } from '@wordpress/data'; import { decodeEntities } from '@wordpress/html-entities'; -import NewPostAuthor from './new'; +import EnhancedPostAuthor from './enhanced-post-author'; /** * Internal dependencies */ @@ -26,7 +26,13 @@ export class PostAuthor extends Component { } render() { - const { postAuthor, instanceId, authors } = this.props; + const { + postAuthor, + postAuthorID, + instanceId, + authors, + onUpdateAuthor, + } = this.props; const selectId = 'post-author-selector-' + instanceId; // Disable reason: A select with an onchange throws a warning @@ -34,11 +40,29 @@ export class PostAuthor extends Component { /* eslint-disable jsx-a11y/no-onchange */ return ( - + + { authors.length > 50 ? ( + + ) : ( + + ) } ); /* eslint-enable jsx-a11y/no-onchange */ @@ -48,9 +72,12 @@ export class PostAuthor extends Component { export default compose( [ withSelect( ( select ) => { return { - postAuthor: select( 'core/editor' ).getEditedPostAttribute( + postAuthorID: select( 'core/editor' ).getEditedPostAttribute( 'author' ), + postAuthor: select( 'core' ).getAuthor( + select( 'core/editor' ).getEditedPostAttribute( 'author' ) + ), authors: select( 'core' ).getAuthors(), }; } ), diff --git a/packages/editor/src/components/post-author/new.js b/packages/editor/src/components/post-author/new.js deleted file mode 100644 index 1198bb9d77e5a..0000000000000 --- a/packages/editor/src/components/post-author/new.js +++ /dev/null @@ -1,139 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { withInstanceId, compose } from '@wordpress/compose'; -import { withSelect, withDispatch } from '@wordpress/data'; -import ComboboxControl from '../../../../components/build/combobox-control/'; -import { useState } from '@wordpress/element'; -import apiRequest from '@wordpress/api-request'; - -/** - * Internal dependencies - */ -import PostAuthorCheck from './check'; - -import { debounce } from 'lodash'; - -/* eslint-disable no-console */ - -function NewPostAuthor( { postAuthor, instanceId, authors } ) { - console.log( 'postAuthor', postAuthor ); - if ( 0 === postAuthor.length ) { - return null; - } - const currentPostAuthor = postAuthor[ 0 ]; - let mappedAuthors = []; - authors.map( ( author, i ) => { - mappedAuthors = [ - ...mappedAuthors, - { - key: i, - name: author.name, - value: author.name, - id: author.id, - }, - ]; - } ); - - const [ isLoading, setIsLoading ] = useState( false ); - const foundAuthor = mappedAuthors.filter( - ( author ) => currentPostAuthor.id === author.id - ); - if ( foundAuthor.length === 0 ) { - mappedAuthors = [ ...mappedAuthors, currentPostAuthor ]; - } - const [ filteredAuthors, setFilteredAuthors ] = useState( mappedAuthors ); - const [ selectedAuthor, setSelectedAuthor ] = useState( currentPostAuthor ); - const handleSelect = ( selectedItem, downshift ) => { - setSelectedAuthor( selectedItem ); - downshift.reset(); - }; - - const handleKeydown = ( { - event, - isOpen, - selectHighlightedItem, - inputValue, - } ) => { - console.log( 'handleKeydown', { - event, - isOpen, - selectHighlightedItem, - inputValue, - } ); - suggestAuthor( inputValue ); - }; - - const suggestAuthor = debounce( ( query, populateResults ) => { - const payload = '?search=' + encodeURIComponent( query ); - setIsLoading( true ); - apiRequest( { path: '/wp/v2/users' + payload } ).done( ( results ) => { - setFilteredAuthors( - results.map( ( author, i ) => ( { - key: i, - name: author.name, - value: author.name, - id: author.id, - } ) ) - ); - setIsLoading( false ); - } ); - }, 150 ); - - const setAuthorId = ( event ) => { - const { onUpdateAuthor } = this.props; - const { value } = event.target; - onUpdateAuthor( Number( value ) ); - }; - - const selectId = 'post-author-selector-' + instanceId; - console.log( selectedAuthor ); - - return ( - - - { - handleKeydown( { - event, - isOpen, - selectHighlightedItem, - inputValue, - } ); - } } - onChange={ ( { selectedItem } ) => { - console.log( 'onSelectedItemChange', selectedItem ); - setSelectedAuthor( selectedItem ); - } } - /> - - ); - /* eslint-enable jsx-a11y/no-onchange */ -} - -export default compose( [ - withSelect( ( select ) => { - return { - postAuthor: select( 'core' ).getAuthor( - select( 'core/editor' ).getEditedPostAttribute( 'author' ) - ), - authors: select( 'core' ).getAuthors(), - }; - } ), - withDispatch( ( dispatch ) => ( { - onUpdateAuthor( author ) { - dispatch( 'core/editor' ).editPost( { author } ); - }, - } ) ), - withInstanceId, -] )( NewPostAuthor ); From 9061e9b50ef389e75b0371fa29694e7a1fc742f0 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 19 Jun 2020 10:44:47 -0600 Subject: [PATCH 07/66] Cleanup. --- .../post-author/enhanced-post-author.js | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js index 110be8a805c58..e09ce2ade1a1f 100644 --- a/packages/editor/src/components/post-author/enhanced-post-author.js +++ b/packages/editor/src/components/post-author/enhanced-post-author.js @@ -1,12 +1,13 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; -import { withInstanceId, compose } from '@wordpress/compose'; -import { withSelect, withDispatch } from '@wordpress/data'; -import ComboboxControl from '../../../../components/build/combobox-control'; -import { useState, useEffect } from '@wordpress/element'; -import apiRequest from '@wordpress/api-request'; +import { useState } from '@wordpress/element'; +import apiFetch from '@wordpress/api-fetch'; + +/** + * Internal dependencies + */ +import ComboboxControl from '../../../../components/build/combobox-control/'; /** * External dependencies @@ -14,10 +15,6 @@ import apiRequest from '@wordpress/api-request'; import { debounce } from 'lodash'; function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { - // Wait until we have the post author before displaying the component. - if ( 0 === postAuthor.length ) { - return null; - } const currentPostAuthor = postAuthor[ 0 ]; let initialAuthors = []; authors.forEach( ( author, i ) => { @@ -54,10 +51,15 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { // The currently selected author. const [ selectedAuthor, setSelectedAuthor ] = useState( currentPostAuthor ); + // Wait until we have the post author before displaying the component. + if ( 0 === postAuthor.length ) { + return null; + } + /** * Handle author selection. * - * @param {object} selectedItem The selected Author. + * @param {Object} selectedItem The selected Author. */ const handleSelect = ( { selectedItem } ) => { setSelectedAuthor( selectedItem ); @@ -67,7 +69,7 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { /** * Handle user input. * - * @param {object} param0 Contains a single property `inputValue` with the string value of the input field. + * @param {Object} param0 Contains a single property `inputValue` with the string value of the input field. */ const handleKeydown = ( { inputValue } ) => { if ( '' === inputValue ) { @@ -87,7 +89,7 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { const searchAuthors = debounce( ( query ) => { const payload = '?search=' + encodeURIComponent( query ); setIsLoadingSearchResult( true ); - apiRequest( { path: '/wp/v2/users' + payload } ).done( ( results ) => { + apiFetch( { path: '/wp/v2/users' + payload } ).done( ( results ) => { setAvailableAuthors( results.map( ( author, i ) => ( { key: i, From d679caa89d40bfaa2267f86bbb2f86fa67dd95ad Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 19 Jun 2020 11:20:28 -0600 Subject: [PATCH 08/66] Clean up user selection and search. --- .../components/src/combobox-control/index.js | 9 +++--- .../post-author/enhanced-post-author.js | 29 +++++++++---------- .../src/components/post-author/index.js | 7 ++++- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js index 8588386e90837..858c202c2a419 100644 --- a/packages/components/src/combobox-control/index.js +++ b/packages/components/src/combobox-control/index.js @@ -1,17 +1,18 @@ -/* eslint-disable no-console */ - /** * External dependencies */ import { useCombobox } from 'downshift'; import classnames from 'classnames'; + +/** + * WordPress dependencies + */ import { __ } from '@wordpress/i18n'; -import { Spinner } from '@wordpress/components'; /** * Internal dependencies */ -import { Button, Dashicon } from '../'; +import { Button, Dashicon, Spinner } from '../'; const itemToString = ( item ) => item && item.name; export default function ComboboxControl( { diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js index e09ce2ade1a1f..86f18fc3fb455 100644 --- a/packages/editor/src/components/post-author/enhanced-post-author.js +++ b/packages/editor/src/components/post-author/enhanced-post-author.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import { debounce } from 'lodash'; + /** * WordPress dependencies */ @@ -9,11 +14,6 @@ import apiFetch from '@wordpress/api-fetch'; */ import ComboboxControl from '../../../../components/build/combobox-control/'; -/** - * External dependencies - */ -import { debounce } from 'lodash'; - function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { const currentPostAuthor = postAuthor[ 0 ]; let initialAuthors = []; @@ -31,9 +31,11 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { // Ensure the current author is included in the initial dropdown list. let foundAuthor = initialAuthors.findIndex( - ( author ) => currentPostAuthor.id === author.id + ( author ) => currentPostAuthor && currentPostAuthor.id === author.id ); - if ( foundAuthor < 0 ) { + + if ( currentPostAuthor && foundAuthor < 0 ) { + currentPostAuthor.key = initialAuthors.length; initialAuthors = [ currentPostAuthor, ...initialAuthors ]; foundAuthor = 0; } @@ -51,11 +53,6 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { // The currently selected author. const [ selectedAuthor, setSelectedAuthor ] = useState( currentPostAuthor ); - // Wait until we have the post author before displaying the component. - if ( 0 === postAuthor.length ) { - return null; - } - /** * Handle author selection. * @@ -69,7 +66,7 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { /** * Handle user input. * - * @param {Object} param0 Contains a single property `inputValue` with the string value of the input field. + * @param {string} inputValue The current value of the input field. */ const handleKeydown = ( { inputValue } ) => { if ( '' === inputValue ) { @@ -89,7 +86,7 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { const searchAuthors = debounce( ( query ) => { const payload = '?search=' + encodeURIComponent( query ); setIsLoadingSearchResult( true ); - apiFetch( { path: '/wp/v2/users' + payload } ).done( ( results ) => { + apiFetch( { path: '/wp/v2/users' + payload } ).then( ( results ) => { setAvailableAuthors( results.map( ( author, i ) => ( { key: i, @@ -100,12 +97,12 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { ); setIsLoadingSearchResult( false ); } ); - }, 150 ); + }, 300 ); return ( Date: Wed, 24 Jun 2020 06:49:04 -0600 Subject: [PATCH 09/66] Update packages/editor/src/components/post-author/enhanced-post-author.js Co-authored-by: Enrique Piqueras --- .../editor/src/components/post-author/enhanced-post-author.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js index 86f18fc3fb455..fb0c97fc32256 100644 --- a/packages/editor/src/components/post-author/enhanced-post-author.js +++ b/packages/editor/src/components/post-author/enhanced-post-author.js @@ -31,7 +31,7 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { // Ensure the current author is included in the initial dropdown list. let foundAuthor = initialAuthors.findIndex( - ( author ) => currentPostAuthor && currentPostAuthor.id === author.id + ( author ) => currentPostAuthor?.id === author.id ); if ( currentPostAuthor && foundAuthor < 0 ) { From 03ccfad5ff7590b20dbe0e0c1893a989a052f147 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 24 Jun 2020 09:00:46 -0600 Subject: [PATCH 10/66] merge --- packages/core-data/src/selectors.js | 6 +++--- .../src/components/post-author/enhanced-post-author.js | 9 ++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index 8cba20f7403bb..4e97be7fceed8 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -76,14 +76,14 @@ export const getUserQueryResults = createSelector( ); /** - * Returns all available authors. + * Returns an Author by ID. * * @param {Object} state Data state. * * @return {Array} Authors list. */ -export function getAuthor( state ) { - return getUserQueryResults( state, 'author' ); +export function getAuthor( state, id ) { + return getUserQueryResults( state, 'author' )[ 0 ]; } /** diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js index fb0c97fc32256..1579bf1c5cc2d 100644 --- a/packages/editor/src/components/post-author/enhanced-post-author.js +++ b/packages/editor/src/components/post-author/enhanced-post-author.js @@ -15,7 +15,6 @@ import apiFetch from '@wordpress/api-fetch'; import ComboboxControl from '../../../../components/build/combobox-control/'; function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { - const currentPostAuthor = postAuthor[ 0 ]; let initialAuthors = []; authors.forEach( ( author, i ) => { initialAuthors = [ @@ -34,9 +33,9 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { ( author ) => currentPostAuthor?.id === author.id ); - if ( currentPostAuthor && foundAuthor < 0 ) { - currentPostAuthor.key = initialAuthors.length; - initialAuthors = [ currentPostAuthor, ...initialAuthors ]; + if ( postAuthor && foundAuthor < 0 ) { + postAuthor.key = initialAuthors.length; + initialAuthors = [ postAuthor, ...initialAuthors ]; foundAuthor = 0; } @@ -51,7 +50,7 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { ); // The currently selected author. - const [ selectedAuthor, setSelectedAuthor ] = useState( currentPostAuthor ); + const [ selectedAuthor, setSelectedAuthor ] = useState( postAuthor ); /** * Handle author selection. From 69e46265042acddd5a03cd37920ac9389e29d774 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 24 Jun 2020 10:33:54 -0600 Subject: [PATCH 11/66] Clean up checks, return a single value from selector. --- docs/designers-developers/developers/data/data-core.md | 2 +- packages/core-data/README.md | 2 +- packages/core-data/src/selectors.js | 2 +- .../editor/src/components/post-author/enhanced-post-author.js | 4 ++-- packages/editor/src/components/post-author/index.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/designers-developers/developers/data/data-core.md b/docs/designers-developers/developers/data/data-core.md index 34ada5ec168c3..7b2175ff96f71 100644 --- a/docs/designers-developers/developers/data/data-core.md +++ b/docs/designers-developers/developers/data/data-core.md @@ -29,7 +29,7 @@ _Returns_ # **getAuthor** -Returns all available authors. +Returns an Author by ID. _Parameters_ diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 3cc077c693b8e..48c56adc70636 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -254,7 +254,7 @@ _Returns_ # **getAuthor** -Returns all available authors. +Returns an Author by ID. _Parameters_ diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index 4e97be7fceed8..107b913f65152 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -82,7 +82,7 @@ export const getUserQueryResults = createSelector( * * @return {Array} Authors list. */ -export function getAuthor( state, id ) { +export function getAuthor( state ) { return getUserQueryResults( state, 'author' )[ 0 ]; } diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js index 1579bf1c5cc2d..22cf057590b5d 100644 --- a/packages/editor/src/components/post-author/enhanced-post-author.js +++ b/packages/editor/src/components/post-author/enhanced-post-author.js @@ -30,7 +30,7 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { // Ensure the current author is included in the initial dropdown list. let foundAuthor = initialAuthors.findIndex( - ( author ) => currentPostAuthor?.id === author.id + ( author ) => postAuthor?.id === author.id ); if ( postAuthor && foundAuthor < 0 ) { @@ -104,7 +104,7 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { isLoading={ isLoadingSearchResults } options={ availableAuthors } initialHighlightedIndex={ foundAuthor } - initialInputValue={ selectedAuthor.name } + initialInputValue={ selectedAuthor?.name } onInputValueChange={ handleKeydown } onChange={ handleSelect } /> diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index f792fad3e3061..e796830b22a9f 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -36,7 +36,7 @@ export class PostAuthor extends Component { const selectId = 'post-author-selector-' + instanceId; // Wait until we have the post author before displaying the component. - if ( 0 === postAuthor.length ) { + if ( ! postAuthor || 0 === postAuthor.length ) { return null; } From 79a2523999e84825aa123ce18b4a6e160afdbe00 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 24 Jun 2020 10:36:31 -0600 Subject: [PATCH 12/66] Change element keys to author ids. --- .../src/components/post-author/enhanced-post-author.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js index 22cf057590b5d..f507515c52e30 100644 --- a/packages/editor/src/components/post-author/enhanced-post-author.js +++ b/packages/editor/src/components/post-author/enhanced-post-author.js @@ -16,11 +16,11 @@ import ComboboxControl from '../../../../components/build/combobox-control/'; function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { let initialAuthors = []; - authors.forEach( ( author, i ) => { + authors.forEach( ( author ) => { initialAuthors = [ ...initialAuthors, { - key: i, + key: author.id, name: author.name, value: author.name, id: author.id, @@ -87,8 +87,8 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { setIsLoadingSearchResult( true ); apiFetch( { path: '/wp/v2/users' + payload } ).then( ( results ) => { setAvailableAuthors( - results.map( ( author, i ) => ( { - key: i, + results.map( ( author ) => ( { + key: author.id, name: author.name, value: author.name, id: author.id, From a649ad664c768719b53292b3d021d4ce7005767a Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 24 Jun 2020 17:36:27 -0600 Subject: [PATCH 13/66] Refresh the user list when the field value changes or the selection is changed. --- .../post-author/enhanced-post-author.js | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js index f507515c52e30..cee1c4b6b42ab 100644 --- a/packages/editor/src/components/post-author/enhanced-post-author.js +++ b/packages/editor/src/components/post-author/enhanced-post-author.js @@ -6,7 +6,7 @@ import { debounce } from 'lodash'; /** * WordPress dependencies */ -import { useState } from '@wordpress/element'; +import { useState, useMemo, useEffect } from '@wordpress/element'; import apiFetch from '@wordpress/api-fetch'; /** @@ -15,25 +15,24 @@ import apiFetch from '@wordpress/api-fetch'; import ComboboxControl from '../../../../components/build/combobox-control/'; function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { - let initialAuthors = []; - authors.forEach( ( author ) => { - initialAuthors = [ - ...initialAuthors, - { + + let initialAuthors = useMemo( () => { + return authors.map( ( author ) => { + return { key: author.id, name: author.name, value: author.name, id: author.id, - }, - ]; - } ); + }; + } ); + }, [ authors ] ) // Ensure the current author is included in the initial dropdown list. let foundAuthor = initialAuthors.findIndex( ( author ) => postAuthor?.id === author.id ); - if ( postAuthor && foundAuthor < 0 ) { + if ( foundAuthor < 0 ) { postAuthor.key = initialAuthors.length; initialAuthors = [ postAuthor, ...initialAuthors ]; foundAuthor = 0; @@ -52,14 +51,18 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { // The currently selected author. const [ selectedAuthor, setSelectedAuthor ] = useState( postAuthor ); + // The currently field value. + const [ fieldValue, setFieldValue ] = useState( postAuthor.name ); + /** * Handle author selection. * * @param {Object} selectedItem The selected Author. */ const handleSelect = ( { selectedItem } ) => { - setSelectedAuthor( selectedItem ); + setFieldValue( selectedItem.name ); onUpdateAuthor( selectedItem.id ); + setSelectedAuthor( selectedItem ); }; /** @@ -68,14 +71,18 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { * @param {string} inputValue The current value of the input field. */ const handleKeydown = ( { inputValue } ) => { - if ( '' === inputValue ) { - // When the field is cleared, reset the author list to the original list. + setFieldValue( inputValue ); + }; + + // Refresh the user list when the field value changes or the selection is changed. + useEffect( () => { + // When the field is cleared or unchanged, use the original author list. + if ( '' === fieldValue || fieldValue === selectedAuthor.name ) { setAvailableAuthors( initialAuthors ); } else { - // Otherwise search for authors matching the input. - searchAuthors( inputValue ); + searchAuthors( fieldValue ); } - }; + }, [ fieldValue, selectedAuthor ] ); /** * Search for authors from the rest API. @@ -96,7 +103,8 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { ); setIsLoadingSearchResult( false ); } ); - }, 300 ); + }, + 300 ); return ( Date: Thu, 25 Jun 2020 12:38:08 -0600 Subject: [PATCH 14/66] Refresh the user list when the field value changes or the selection is changed. --- .../developers/data/data-core.md | 12 ++++ .../components/src/combobox-control/index.js | 64 ++++++++----------- packages/core-data/README.md | 12 ++++ packages/core-data/src/resolvers.js | 16 +++++ packages/core-data/src/selectors.js | 11 ++++ .../post-author/enhanced-post-author.js | 62 ++++++------------ 6 files changed, 96 insertions(+), 81 deletions(-) diff --git a/docs/designers-developers/developers/data/data-core.md b/docs/designers-developers/developers/data/data-core.md index 7b2175ff96f71..1bb76edef9adf 100644 --- a/docs/designers-developers/developers/data/data-core.md +++ b/docs/designers-developers/developers/data/data-core.md @@ -465,6 +465,18 @@ _Returns_ - `boolean`: Whether the entity record is saving or not. +# **searchAuthors** + +Returns searched authors. + +_Parameters_ + +- _state_ `Object`: Data state. + +_Returns_ + +- `Array`: Authors list. + ## Actions diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js index 858c202c2a419..aae17002b4d77 100644 --- a/packages/components/src/combobox-control/index.js +++ b/packages/components/src/combobox-control/index.js @@ -4,15 +4,10 @@ import { useCombobox } from 'downshift'; import classnames from 'classnames'; -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; - /** * Internal dependencies */ -import { Button, Dashicon, Spinner } from '../'; +import { Button, Dashicon } from '../'; const itemToString = ( item ) => item && item.name; export default function ComboboxControl( { @@ -25,7 +20,6 @@ export default function ComboboxControl( { value: _selectedItem, initialHighlightedIndex, initialInputValue, - isLoading, } ) { const { getLabelProps, @@ -106,37 +100,31 @@ export default function ComboboxControl( {
    { isOpen && - ( isLoading ? ( - - { __( 'Loading' ) } - - ) : ( - items.map( ( item, index ) => ( - // eslint-disable-next-line react/jsx-key -
  • - { item === selectedItem && ( - - ) } - { item.name } -
  • - ) ) + items.map( ( item, index ) => ( + // eslint-disable-next-line react/jsx-key +
  • + { item === selectedItem && ( + + ) } + { item.name } +
  • ) ) }
diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 48c56adc70636..d13beee566e08 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -690,6 +690,18 @@ _Returns_ - `boolean`: Whether the entity record is saving or not. +# **searchAuthors** + +Returns searched authors. + +_Parameters_ + +- _state_ `Object`: Data state. + +_Returns_ + +- `Array`: Authors list. + diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 341269f87920b..4749c95ce6eb4 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -35,8 +35,24 @@ export function* getAuthors() { } ); yield receiveUserQuery( 'authors', users ); } + +/** + * Searches for authors from the REST API. + * + * @param {string} search A search query string. + */ +export function* searchAuthors( search = '' ) { + const users = yield apiFetch( { + path: `/wp/v2/users/?who=authors&per_page=100&search=${ search }`, + } ); + + yield receiveUserQuery( 'searchAuthors', users ); +} + /** * Request a single author from the REST API. + * + * @param {string} id The ID of the author to retrieve. */ export function* getAuthor( id = '' ) { const users = yield apiFetch( { diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index 107b913f65152..5c1dfab26f693 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -47,6 +47,17 @@ export function getAuthors( state ) { return getUserQueryResults( state, 'authors' ); } +/** + * Returns searched authors. + * + * @param {Object} state Data state. + * + * @return {Array} Authors list. + */ +export function searchAuthors( state ) { + return getUserQueryResults( state, 'searchAuthors' ); +} + /** * Returns the current user. * diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js index cee1c4b6b42ab..0cf1ba75f6534 100644 --- a/packages/editor/src/components/post-author/enhanced-post-author.js +++ b/packages/editor/src/components/post-author/enhanced-post-author.js @@ -6,8 +6,8 @@ import { debounce } from 'lodash'; /** * WordPress dependencies */ -import { useState, useMemo, useEffect } from '@wordpress/element'; -import apiFetch from '@wordpress/api-fetch'; +import { useState, useMemo } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -15,7 +15,6 @@ import apiFetch from '@wordpress/api-fetch'; import ComboboxControl from '../../../../components/build/combobox-control/'; function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { - let initialAuthors = useMemo( () => { return authors.map( ( author ) => { return { @@ -25,7 +24,7 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { id: author.id, }; } ); - }, [ authors ] ) + }, [ authors ] ); // Ensure the current author is included in the initial dropdown list. let foundAuthor = initialAuthors.findIndex( @@ -38,16 +37,6 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { foundAuthor = 0; } - // The search result loading state. - const [ isLoadingSearchResults, setIsLoadingSearchResult ] = useState( - false - ); - - // The list of authors available in the dropdown. - const [ availableAuthors, setAvailableAuthors ] = useState( - initialAuthors - ); - // The currently selected author. const [ selectedAuthor, setSelectedAuthor ] = useState( postAuthor ); @@ -60,6 +49,9 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { * @param {Object} selectedItem The selected Author. */ const handleSelect = ( { selectedItem } ) => { + if ( ! selectedItem ) { + return; + } setFieldValue( selectedItem.name ); onUpdateAuthor( selectedItem.id ); setSelectedAuthor( selectedItem ); @@ -74,46 +66,30 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { setFieldValue( inputValue ); }; - // Refresh the user list when the field value changes or the selection is changed. - useEffect( () => { - // When the field is cleared or unchanged, use the original author list. - if ( '' === fieldValue || fieldValue === selectedAuthor.name ) { - setAvailableAuthors( initialAuthors ); - } else { - searchAuthors( fieldValue ); - } - }, [ fieldValue, selectedAuthor ] ); - - /** - * Search for authors from the rest API. - * - * @param string query The string to search for. - **/ - const searchAuthors = debounce( ( query ) => { - const payload = '?search=' + encodeURIComponent( query ); - setIsLoadingSearchResult( true ); - apiFetch( { path: '/wp/v2/users' + payload } ).then( ( results ) => { - setAvailableAuthors( - results.map( ( author ) => ( { + const availableAuthors = useSelect( + ( select ) => { + if ( '' === fieldValue || fieldValue === selectedAuthor.name ) { + return initialAuthors; + } + return select( 'core' ) + .searchAuthors( fieldValue ) + .map( ( author ) => ( { key: author.id, name: author.name, value: author.name, id: author.id, - } ) ) - ); - setIsLoadingSearchResult( false ); - } ); - }, - 300 ); + } ) ); + }, + [ fieldValue, selectedAuthor ] + ); return ( ); From ed75df84a39d53b6fee47795f1ee81c4283a04c8 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 25 Jun 2020 12:46:25 -0600 Subject: [PATCH 15/66] =?UTF-8?q?Remove=20=E2=80=98value=E2=80=99=20from?= =?UTF-8?q?=20author=20objects.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../editor/src/components/post-author/enhanced-post-author.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js index 0cf1ba75f6534..e320a3d8539b6 100644 --- a/packages/editor/src/components/post-author/enhanced-post-author.js +++ b/packages/editor/src/components/post-author/enhanced-post-author.js @@ -20,7 +20,6 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { return { key: author.id, name: author.name, - value: author.name, id: author.id, }; } ); @@ -76,7 +75,6 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { .map( ( author ) => ( { key: author.id, name: author.name, - value: author.name, id: author.id, } ) ); }, From c467b5c9b776bff8001263b78ce21651c7a8b34b Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 25 Jun 2020 12:49:42 -0600 Subject: [PATCH 16/66] Remove unused id from ComboboxControl. --- .../editor/src/components/post-author/enhanced-post-author.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js index e320a3d8539b6..dd4ff00e04edb 100644 --- a/packages/editor/src/components/post-author/enhanced-post-author.js +++ b/packages/editor/src/components/post-author/enhanced-post-author.js @@ -14,7 +14,7 @@ import { useSelect } from '@wordpress/data'; */ import ComboboxControl from '../../../../components/build/combobox-control/'; -function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { +function EnhancedPostAuthor( { postAuthor, authors, onUpdateAuthor } ) { let initialAuthors = useMemo( () => { return authors.map( ( author ) => { return { @@ -83,7 +83,6 @@ function EnhancedPostAuthor( { postAuthor, id, authors, onUpdateAuthor } ) { return ( Date: Thu, 25 Jun 2020 12:53:56 -0600 Subject: [PATCH 17/66] use unshift --- .../editor/src/components/post-author/enhanced-post-author.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js index dd4ff00e04edb..9e22f214ef1f1 100644 --- a/packages/editor/src/components/post-author/enhanced-post-author.js +++ b/packages/editor/src/components/post-author/enhanced-post-author.js @@ -15,7 +15,7 @@ import { useSelect } from '@wordpress/data'; import ComboboxControl from '../../../../components/build/combobox-control/'; function EnhancedPostAuthor( { postAuthor, authors, onUpdateAuthor } ) { - let initialAuthors = useMemo( () => { + const initialAuthors = useMemo( () => { return authors.map( ( author ) => { return { key: author.id, @@ -32,7 +32,7 @@ function EnhancedPostAuthor( { postAuthor, authors, onUpdateAuthor } ) { if ( foundAuthor < 0 ) { postAuthor.key = initialAuthors.length; - initialAuthors = [ postAuthor, ...initialAuthors ]; + initialAuthors.unshift( postAuthor ); foundAuthor = 0; } From e1d688d07755bbefbc1fb6704dec592e87583a42 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 25 Jun 2020 15:04:53 -0600 Subject: [PATCH 18/66] remove tracking of selectedAuthor --- .../src/components/post-author/enhanced-post-author.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js index 9e22f214ef1f1..03ce259b6b4ef 100644 --- a/packages/editor/src/components/post-author/enhanced-post-author.js +++ b/packages/editor/src/components/post-author/enhanced-post-author.js @@ -36,9 +36,6 @@ function EnhancedPostAuthor( { postAuthor, authors, onUpdateAuthor } ) { foundAuthor = 0; } - // The currently selected author. - const [ selectedAuthor, setSelectedAuthor ] = useState( postAuthor ); - // The currently field value. const [ fieldValue, setFieldValue ] = useState( postAuthor.name ); @@ -53,7 +50,6 @@ function EnhancedPostAuthor( { postAuthor, authors, onUpdateAuthor } ) { } setFieldValue( selectedItem.name ); onUpdateAuthor( selectedItem.id ); - setSelectedAuthor( selectedItem ); }; /** @@ -67,7 +63,7 @@ function EnhancedPostAuthor( { postAuthor, authors, onUpdateAuthor } ) { const availableAuthors = useSelect( ( select ) => { - if ( '' === fieldValue || fieldValue === selectedAuthor.name ) { + if ( '' === fieldValue || fieldValue === postAuthor.name ) { return initialAuthors; } return select( 'core' ) @@ -78,14 +74,14 @@ function EnhancedPostAuthor( { postAuthor, authors, onUpdateAuthor } ) { id: author.id, } ) ); }, - [ fieldValue, selectedAuthor ] + [ fieldValue, postAuthor ] ); return ( From 70a9029cc6639e22755e99c2f95e854a606a3712 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 26 Jun 2020 13:49:03 -0600 Subject: [PATCH 19/66] merge --- .../developers/data/data-core-block-editor.md | 2 +- packages/api-fetch/src/index.js | 4 +- .../components/block-switcher/test/index.js | 20 +++--- packages/block-editor/src/store/actions.js | 5 +- packages/block-library/src/cover/edit.js | 5 +- packages/block-library/src/embed/settings.js | 8 ++- .../block-library/src/missing/edit.native.js | 54 ++++++++-------- .../placeholder/template-part-previews.js | 4 +- .../styles/box-control-icon-styles.js | 2 +- .../box-control/styles/box-control-styles.js | 6 +- .../styles/box-control-visualizer-styles.js | 12 ++-- packages/components/src/button/test/index.js | 9 +-- packages/components/src/card/stories/media.js | 4 +- .../components/src/card/styles/card-styles.js | 46 +++++++------- packages/components/src/draggable/index.js | 43 +++++++------ .../components/src/flex/styles/flex-styles.js | 12 ++-- .../styles/input-control-styles.js | 62 +++++++++---------- .../styles/number-control-styles.js | 2 +- .../styles/range-control-styles.js | 52 ++++++++-------- .../styles/resize-tooltip.styles.js | 6 +- .../styles/unit-control-styles.js | 14 ++--- .../lib/index.js | 10 ++- packages/edit-navigation/src/store/actions.js | 6 +- packages/env/lib/config.js | 5 +- .../eslint-plugin/rules/dependency-group.js | 8 +-- packages/lazy-import/lib/index.js | 4 +- .../lib/tasks/first-time-contributor/index.js | 4 +- packages/react-native-editor/babel.config.js | 2 +- .../react-native-editor/sass-transformer.js | 2 +- packages/react-native-editor/src/globals.js | 2 +- .../react-native-editor/src/jsdom-patches.js | 6 +- .../rich-text/src/component/index.native.js | 51 ++++++++------- 32 files changed, 236 insertions(+), 236 deletions(-) diff --git a/docs/designers-developers/developers/data/data-core-block-editor.md b/docs/designers-developers/developers/data/data-core-block-editor.md index ed2a8e15ff6fc..429f2f0fda4d8 100644 --- a/docs/designers-developers/developers/data/data-core-block-editor.md +++ b/docs/designers-developers/developers/data/data-core-block-editor.md @@ -952,6 +952,7 @@ _Returns_ - `?boolean`: Whether the template is valid or not. + ## Actions @@ -1480,5 +1481,4 @@ _Returns_ - `Object`: Action object - diff --git a/packages/api-fetch/src/index.js b/packages/api-fetch/src/index.js index ae97d869ecde2..b9fe1a6d0875a 100644 --- a/packages/api-fetch/src/index.js +++ b/packages/api-fetch/src/index.js @@ -147,9 +147,7 @@ function apiFetch( options ) { .then( ( data ) => data.text() ) .then( ( text ) => { apiFetch.nonceMiddleware.nonce = text; - apiFetch( options ) - .then( resolve ) - .catch( reject ); + apiFetch( options ).then( resolve ).catch( reject ); } ) .catch( reject ); } ); diff --git a/packages/block-editor/src/components/block-switcher/test/index.js b/packages/block-editor/src/components/block-switcher/test/index.js index 667f48da497db..a5879995c271d 100644 --- a/packages/block-editor/src/components/block-switcher/test/index.js +++ b/packages/block-editor/src/components/block-switcher/test/index.js @@ -182,12 +182,10 @@ describe( 'BlockSwitcher', () => { test( 'should simulate a keydown event, which should call onToggle and open transform toggle.', () => { const toggleClosed = mount( - getDropdown() - .props() - .renderToggle( { - onToggle: onToggleStub, - isOpen: false, - } ) + getDropdown().props().renderToggle( { + onToggle: onToggleStub, + isOpen: false, + } ) ); const iconButtonClosed = toggleClosed.find( Button ); @@ -198,12 +196,10 @@ describe( 'BlockSwitcher', () => { test( 'should simulate a click event, which should call onToggle.', () => { const toggleOpen = mount( - getDropdown() - .props() - .renderToggle( { - onToggle: onToggleStub, - isOpen: true, - } ) + getDropdown().props().renderToggle( { + onToggle: onToggleStub, + isOpen: true, + } ) ); const iconButtonOpen = toggleOpen.find( Button ); diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 86a313caae73b..1f388d2e22979 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -274,8 +274,9 @@ function getBlocksWithDefaultStylesApplied( blocks, blockEditorSettings ) { ...block, attributes: { ...attributes, - className: `${ className || - '' } is-style-${ blockStyle }`.trim(), + className: `${ + className || '' + } is-style-${ blockStyle }`.trim(), }, }; } ); diff --git a/packages/block-library/src/cover/edit.js b/packages/block-library/src/cover/edit.js index dff50cd2866aa..4ba780ee2805a 100644 --- a/packages/block-library/src/cover/edit.js +++ b/packages/block-library/src/cover/edit.js @@ -292,8 +292,9 @@ function CoverEdit( { } if ( focalPoint ) { - style.backgroundPosition = `${ focalPoint.x * 100 }% ${ focalPoint.y * - 100 }%`; + style.backgroundPosition = `${ focalPoint.x * 100 }% ${ + focalPoint.y * 100 + }%`; } const hasBackground = !! ( url || overlayColor.color || gradientValue ); diff --git a/packages/block-library/src/embed/settings.js b/packages/block-library/src/embed/settings.js index 7ccf53f6e4f5f..86c928623df4d 100644 --- a/packages/block-library/src/embed/settings.js +++ b/packages/block-library/src/embed/settings.js @@ -137,7 +137,9 @@ export function getEmbedBlockSettings( { return (
- { `\n${ url }\n` /* URL needs to be on its own line. */ } + { + `\n${ url }\n` /* URL needs to be on its own line. */ + }
{ ! RichText.isEmpty( caption ) && ( - { `\n${ url }\n` /* URL needs to be on its own line. */ } + { + `\n${ url }\n` /* URL needs to be on its own line. */ + } { ! RichText.isEmpty( caption ) && ( - { // eslint-disable-next-line no-undef - __DEV__ - ? __( - "We are working hard to add more blocks with each release. In the meantime, you can also edit this block using your device's web browser." - ) - : __( - 'We are working hard to add more blocks with each release. In the meantime, you can also edit this post on the web.' - ) } + { + // eslint-disable-next-line no-undef + __DEV__ + ? __( + "We are working hard to add more blocks with each release. In the meantime, you can also edit this block using your device's web browser." + ) + : __( + 'We are working hard to add more blocks with each release. In the meantime, you can also edit this post on the web.' + ) + } - { // eslint-disable-next-line no-undef - __DEV__ && ( - <> - - - - ) } + { + // eslint-disable-next-line no-undef + __DEV__ && ( + <> + + + + ) + } ); } diff --git a/packages/block-library/src/template-part/edit/placeholder/template-part-previews.js b/packages/block-library/src/template-part/edit/placeholder/template-part-previews.js index f15bcce5bb849..7cbe4312cf9a2 100644 --- a/packages/block-library/src/template-part/edit/placeholder/template-part-previews.js +++ b/packages/block-library/src/template-part/edit/placeholder/template-part-previews.js @@ -119,9 +119,7 @@ function TemplatePartSearchResults( { ( { slug, meta: { theme } } ) => slug.toLowerCase().includes( normalizedFilterValue ) || // Since diacritics can be used in theme names, remove them for the comparison. - deburr( theme ) - .toLowerCase() - .includes( normalizedFilterValue ) + deburr( theme ).toLowerCase().includes( normalizedFilterValue ) ); // Order based on value location. searchResults.sort( ( a, b ) => { diff --git a/packages/components/src/box-control/styles/box-control-icon-styles.js b/packages/components/src/box-control/styles/box-control-icon-styles.js index dae56d7619a96..3443458d262dc 100644 --- a/packages/components/src/box-control/styles/box-control-icon-styles.js +++ b/packages/components/src/box-control/styles/box-control-icon-styles.js @@ -33,7 +33,7 @@ const Stroke = styled.span` display: block; pointer-events: none; position: absolute; - ${strokeFocus}; + ${ strokeFocus }; `; const VerticalStroke = styled( Stroke )` diff --git a/packages/components/src/box-control/styles/box-control-styles.js b/packages/components/src/box-control/styles/box-control-styles.js index efecdb24c1fc0..78cf6ceb9a696 100644 --- a/packages/components/src/box-control/styles/box-control-styles.js +++ b/packages/components/src/box-control/styles/box-control-styles.js @@ -18,7 +18,7 @@ export const Root = styled.div` `; export const Header = styled( Flex )` - color: ${color( 'ui.label' )}; + color: ${ color( 'ui.label' ) }; padding-bottom: 8px; `; @@ -66,6 +66,6 @@ const unitControlMarginStyles = ( { isFirst } ) => { export const UnitControl = styled( BaseUnitControl )` max-width: 60px; - ${unitControlBorderRadiusStyles}; - ${unitControlMarginStyles}; + ${ unitControlBorderRadiusStyles }; + ${ unitControlMarginStyles }; `; diff --git a/packages/components/src/box-control/styles/box-control-visualizer-styles.js b/packages/components/src/box-control/styles/box-control-visualizer-styles.js index f1d67edd06731..0b0e2b614fbfe 100644 --- a/packages/components/src/box-control/styles/box-control-visualizer-styles.js +++ b/packages/components/src/box-control/styles/box-control-visualizer-styles.js @@ -26,12 +26,12 @@ const containerPositionStyles = ( { isPositionAbsolute } ) => { export const Container = styled.div` box-sizing: border-box; position: relative; - ${containerPositionStyles}; + ${ containerPositionStyles }; `; export const Side = styled.div` box-sizing: border-box; - background: ${color( 'ui.brand' )}; + background: ${ color( 'ui.brand' ) }; filter: brightness( 1 ); opacity: 0; position: absolute; @@ -39,11 +39,11 @@ export const Side = styled.div` transition: opacity 120ms linear; z-index: 1; - ${( { isActive } ) => + ${ ( { isActive } ) => isActive && ` opacity: 0.3; - `} + ` } `; export const TopView = styled( Side )` @@ -55,7 +55,7 @@ export const TopView = styled( Side )` export const RightView = styled( Side )` top: 0; bottom: 0; - ${rtl( { right: 0 } )}; + ${ rtl( { right: 0 } ) }; `; export const BottomView = styled( Side )` @@ -67,5 +67,5 @@ export const BottomView = styled( Side )` export const LeftView = styled( Side )` top: 0; bottom: 0; - ${rtl( { left: 0 } )}; + ${ rtl( { left: 0 } ) }; `; diff --git a/packages/components/src/button/test/index.js b/packages/components/src/button/test/index.js index f257bd1e57de2..49de9ef1d59ad 100644 --- a/packages/components/src/button/test/index.js +++ b/packages/components/src/button/test/index.js @@ -97,12 +97,9 @@ describe( 'Button', () => { /> ); expect( iconButton.find( 'Icon' ).dive() ).not.toBeNull(); - expect( - iconButton - .find( '.test' ) - .shallow() - .text() - ).toBe( 'Test' ); + expect( iconButton.find( '.test' ).shallow().text() ).toBe( + 'Test' + ); } ); it( 'should add an aria-label when the label property is used, with Tooltip wrapper', () => { diff --git a/packages/components/src/card/stories/media.js b/packages/components/src/card/stories/media.js index ab762576423b5..4d499b3067f7e 100644 --- a/packages/components/src/card/stories/media.js +++ b/packages/components/src/card/stories/media.js @@ -120,11 +120,11 @@ const HorizontallyAlignedCard = styled( Card )` flex-direction: row-reverse; } - ${StyledCardBody} { + ${ StyledCardBody } { flex: 1; } - ${StyledCardMedia} { + ${ StyledCardMedia } { &.is-left { border-radius: 3px 0 0 3px; } diff --git a/packages/components/src/card/styles/card-styles.js b/packages/components/src/card/styles/card-styles.js index 388b80fb9fe37..27421a29631d4 100644 --- a/packages/components/src/card/styles/card-styles.js +++ b/packages/components/src/card/styles/card-styles.js @@ -23,12 +23,12 @@ export const styleProps = { const { borderColor, borderRadius, backgroundShady } = styleProps; export const CardUI = styled.div` - background: ${color( 'white' )}; + background: ${ color( 'white' ) }; box-sizing: border-box; - border-radius: ${borderRadius}; - border: 1px solid ${borderColor}; + border-radius: ${ borderRadius }; + border: 1px solid ${ borderColor }; - ${handleBorderless}; + ${ handleBorderless }; &.is-elevated { box-shadow: 0px 1px 3px 0px rgba( 0, 0, 0, 0.2 ), @@ -38,18 +38,18 @@ export const CardUI = styled.div` `; export const HeaderUI = styled( Flex )` - border-bottom: 1px solid ${borderColor}; - border-top-left-radius: ${borderRadius}; - border-top-right-radius: ${borderRadius}; + border-bottom: 1px solid ${ borderColor }; + border-top-left-radius: ${ borderRadius }; + border-top-right-radius: ${ borderRadius }; box-sizing: border-box; &:last-child { border-bottom: none; } - ${headerFooterSizes}; - ${handleBorderless}; - ${handleShady}; + ${ headerFooterSizes }; + ${ handleBorderless }; + ${ handleShady }; `; export const MediaUI = styled.div` @@ -65,41 +65,41 @@ export const MediaUI = styled.div` } &:first-of-type { - border-top-left-radius: ${borderRadius}; - border-top-right-radius: ${borderRadius}; + border-top-left-radius: ${ borderRadius }; + border-top-right-radius: ${ borderRadius }; } &:last-of-type { - border-bottom-left-radius: ${borderRadius}; - border-bottom-right-radius: ${borderRadius}; + border-bottom-left-radius: ${ borderRadius }; + border-bottom-right-radius: ${ borderRadius }; } `; export const BodyUI = styled.div` box-sizing: border-box; - ${bodySize}; - ${handleShady}; + ${ bodySize }; + ${ handleShady }; `; export const FooterUI = styled( Flex )` - border-top: 1px solid ${borderColor}; - border-bottom-left-radius: ${borderRadius}; - border-bottom-right-radius: ${borderRadius}; + border-top: 1px solid ${ borderColor }; + border-bottom-left-radius: ${ borderRadius }; + border-bottom-right-radius: ${ borderRadius }; box-sizing: border-box; &:first-of-type { border-top: none; } - ${headerFooterSizes}; - ${handleBorderless}; - ${handleShady}; + ${ headerFooterSizes }; + ${ handleBorderless }; + ${ handleShady }; `; export const DividerUI = styled( HorizontalRule )` all: unset; - border-top: 1px solid ${borderColor}; + border-top: 1px solid ${ borderColor }; box-sizing: border-box; display: block; height: 0; diff --git a/packages/components/src/draggable/index.js b/packages/components/src/draggable/index.js index 008a7c9914ee2..c234524370080 100644 --- a/packages/components/src/draggable/index.js +++ b/packages/components/src/draggable/index.js @@ -52,18 +52,16 @@ class Draggable extends Component { * @param {Object} event The non-custom DragEvent. */ onDragOver( event ) { - this.cloneWrapper.style.top = `${ parseInt( - this.cloneWrapper.style.top, - 10 - ) + + this.cloneWrapper.style.top = `${ + parseInt( this.cloneWrapper.style.top, 10 ) + event.clientY - - this.cursorTop }px`; - this.cloneWrapper.style.left = `${ parseInt( - this.cloneWrapper.style.left, - 10 - ) + + this.cursorTop + }px`; + this.cloneWrapper.style.left = `${ + parseInt( this.cloneWrapper.style.left, 10 ) + event.clientX - - this.cursorLeft }px`; + this.cursorLeft + }px`; // Update cursor coordinates. this.cursorLeft = event.clientX; @@ -126,17 +124,20 @@ class Draggable extends Component { this.cloneWrapper.classList.add( cloneClassname ); } - this.cloneWrapper.style.width = `${ elementRect.width + - clonePadding * 2 }px`; + this.cloneWrapper.style.width = `${ + elementRect.width + clonePadding * 2 + }px`; // If a dragComponent is defined, the following logic will clone the // HTML node and inject it into the cloneWrapper. if ( this.dragComponentRef.current ) { // Position clone right over the original element (20px padding). - this.cloneWrapper.style.top = `${ elementTopOffset - - clonePadding }px`; - this.cloneWrapper.style.left = `${ elementLeftOffset - - clonePadding }px`; + this.cloneWrapper.style.top = `${ + elementTopOffset - clonePadding + }px`; + this.cloneWrapper.style.left = `${ + elementLeftOffset - clonePadding + }px`; const clonedDragComponent = document.createElement( 'div' ); clonedDragComponent.innerHTML = this.dragComponentRef.current.innerHTML; @@ -154,10 +155,12 @@ class Draggable extends Component { this.cloneWrapper.style.left = `${ event.clientX }px`; } else { // Position clone right over the original element (20px padding). - this.cloneWrapper.style.top = `${ elementTopOffset - - clonePadding }px`; - this.cloneWrapper.style.left = `${ elementLeftOffset - - clonePadding }px`; + this.cloneWrapper.style.top = `${ + elementTopOffset - clonePadding + }px`; + this.cloneWrapper.style.left = `${ + elementLeftOffset - clonePadding + }px`; } // Hack: Remove iFrames as it's causing the embeds drag clone to freeze diff --git a/packages/components/src/flex/styles/flex-styles.js b/packages/components/src/flex/styles/flex-styles.js index 50bfbfd087b58..fddb2c975edec 100644 --- a/packages/components/src/flex/styles/flex-styles.js +++ b/packages/components/src/flex/styles/flex-styles.js @@ -40,10 +40,10 @@ const gapStyle = ( { gap, isReversed } ) => { return css` > * { - ${padding}: ${value}px; + ${ padding }: ${ value }px; &:last-child { - ${padding}: 0; + ${ padding }: 0; } } `; @@ -61,10 +61,10 @@ export const Flex = styled.div` box-sizing: border-box; display: flex; - ${alignStyle}; - ${justifyStyle}; - ${gapStyle}; - ${reversedStyles}; + ${ alignStyle }; + ${ justifyStyle }; + ${ gapStyle }; + ${ reversedStyles }; `; export const Item = styled.div` diff --git a/packages/components/src/input-control/styles/input-control-styles.js b/packages/components/src/input-control/styles/input-control-styles.js index ca7c95ebbdd90..bdb866c058d43 100644 --- a/packages/components/src/input-control/styles/input-control-styles.js +++ b/packages/components/src/input-control/styles/input-control-styles.js @@ -28,8 +28,8 @@ export const Root = styled.div` position: relative; border-radius: 2px; - ${rootFloatLabelStyles}; - ${rootFocusedStyles}; + ${ rootFloatLabelStyles }; + ${ rootFocusedStyles }; `; const containerDisabledStyle = ( { disabled } ) => { @@ -47,7 +47,7 @@ export const Container = styled.div` display: flex; position: relative; - ${containerDisabledStyle}; + ${ containerDisabledStyle }; `; const disabledStyles = ( { disabled } ) => { @@ -70,10 +70,10 @@ const fontSizeStyles = ( { size } ) => { if ( ! fontSize ) return ''; return css` - font-size: ${fontSizeMobile}; + font-size: ${ fontSizeMobile }; @media ( min-width: 600px ) { - font-size: ${fontSize}; + font-size: ${ fontSize }; } `; }; @@ -108,7 +108,7 @@ const placeholderStyles = ( { isFilled, isFloating, isFloatingLabel } ) => { return css` &::placeholder { - opacity: ${opacity}; + opacity: ${ opacity }; } &::-webkit-input-placeholder { @@ -123,7 +123,7 @@ const dragStyles = ( { isDragging, dragCursor } ) => { if ( isDragging ) { defaultArrowStyles = css` - cursor: ${dragCursor}; + cursor: ${ dragCursor }; user-select: none; &::-webkit-outer-spin-button, @@ -137,14 +137,14 @@ const dragStyles = ( { isDragging, dragCursor } ) => { if ( isDragging && dragCursor ) { activeDragCursorStyles = css` &:active { - cursor: ${dragCursor}; + cursor: ${ dragCursor }; } `; } return css` - ${defaultArrowStyles}; - ${activeDragCursorStyles}; + ${ defaultArrowStyles }; + ${ activeDragCursorStyles }; `; }; @@ -157,19 +157,19 @@ export const Input = styled.input` box-sizing: border-box; border: none; box-shadow: none !important; - color: ${color( 'black' )}; + color: ${ color( 'black' ) }; display: block; outline: none; padding-left: 8px; padding-right: 8px; width: 100%; - ${dragStyles}; - ${disabledStyles}; - ${fontSizeStyles}; - ${sizeStyles}; + ${ dragStyles }; + ${ disabledStyles }; + ${ fontSizeStyles }; + ${ sizeStyles }; - ${placeholderStyles}; + ${ placeholderStyles }; } `; @@ -256,17 +256,17 @@ const BaseLabel = styled( Text )` padding: 0; pointer-events: none; top: 50%; - transition: transform ${FLOATING_LABEL_TRANSITION_SPEED} linear, - max-width ${FLOATING_LABEL_TRANSITION_SPEED} linear; + transition: transform ${ FLOATING_LABEL_TRANSITION_SPEED } linear, + max-width ${ FLOATING_LABEL_TRANSITION_SPEED } linear; z-index: 1; - ${laberColor}; - ${labelFontSize}; - ${labelPosition}; - ${labelTruncation}; - ${reduceMotion( 'transition' )}; + ${ laberColor }; + ${ labelFontSize }; + ${ labelPosition }; + ${ labelTruncation }; + ${ reduceMotion( 'transition' ) }; - ${rtl( { left: 0 } )} + ${ rtl( { left: 0 } ) } } `; @@ -304,9 +304,9 @@ export const Fieldset = styled.fieldset` position: absolute; right: 0; - ${fieldsetFocusedStyles}; - ${fieldsetTopStyles}; - ${rtl( { paddingLeft: 2 } )} + ${ fieldsetFocusedStyles }; + ${ fieldsetTopStyles }; + ${ rtl( { paddingLeft: 2 } ) } } `; @@ -333,19 +333,19 @@ export const Legend = styled.legend` line-height: 11px; margin: 0; padding: 0; - transition: max-width ${FLOATING_LABEL_TRANSITION_SPEED} linear; + transition: max-width ${ FLOATING_LABEL_TRANSITION_SPEED } linear; visibility: hidden; width: auto; - ${legendSize}; - ${reduceMotion( 'transition' )}; + ${ legendSize }; + ${ reduceMotion( 'transition' ) }; } `; const BaseLegendText = styled( Text )` box-sizing: border-box; display: inline-block; - ${rtl( { paddingLeft: 4, paddingRight: 5 } )} + ${ rtl( { paddingLeft: 4, paddingRight: 5 } ) } `; export const LegendText = ( props ) => ( diff --git a/packages/components/src/number-control/styles/number-control-styles.js b/packages/components/src/number-control/styles/number-control-styles.js index fe85c4bb90222..abc89fc916183 100644 --- a/packages/components/src/number-control/styles/number-control-styles.js +++ b/packages/components/src/number-control/styles/number-control-styles.js @@ -21,5 +21,5 @@ const htmlArrowStyles = ( { hideHTMLArrows } ) => { }; export const Input = styled( InputControl )` - ${htmlArrowStyles}; + ${ htmlArrowStyles }; `; diff --git a/packages/components/src/range-control/styles/range-control-styles.js b/packages/components/src/range-control/styles/range-control-styles.js index 9cced10d2b18c..f820c3e2dbf05 100644 --- a/packages/components/src/range-control/styles/range-control-styles.js +++ b/packages/components/src/range-control/styles/range-control-styles.js @@ -39,23 +39,23 @@ export const Wrapper = styled.span` position: relative; width: 100%; - ${wrapperColor}; - ${rangeHeight}; - ${wrapperMargin}; + ${ wrapperColor }; + ${ rangeHeight }; + ${ wrapperMargin }; - ${rtl( { marginLeft: 10 } )} + ${ rtl( { marginLeft: 10 } ) } `; export const BeforeIconWrapper = styled.span` margin-top: 3px; - ${rtl( { marginRight: 6 } )} + ${ rtl( { marginRight: 6 } ) } `; export const AfterIconWrapper = styled.span` margin-top: 3px; - ${rtl( { marginLeft: 16 } )} + ${ rtl( { marginLeft: 16 } ) } `; const railBackgroundColor = ( { disabled, railColor } ) => { @@ -71,7 +71,7 @@ const railBackgroundColor = ( { disabled, railColor } ) => { }; export const Rail = styled.span` - background-color: ${color( 'lightGray.600' )}; + background-color: ${ color( 'lightGray.600' ) }; box-sizing: border-box; left: 0; pointer-events: none; @@ -82,7 +82,7 @@ export const Rail = styled.span` margin-top: 14px; top: 0; - ${railBackgroundColor}; + ${ railBackgroundColor }; `; const trackBackgroundColor = ( { disabled, trackColor } ) => { @@ -108,7 +108,7 @@ export const Track = styled.span` margin-top: 14px; top: 0; - ${trackBackgroundColor}; + ${ trackBackgroundColor }; `; export const MarksWrapper = styled.span` @@ -139,7 +139,7 @@ export const Mark = styled.span` top: -4px; width: 1px; - ${markFill}; + ${ markFill }; `; const markLabelFill = ( { isFilled } ) => { @@ -150,7 +150,7 @@ const markLabelFill = ( { isFilled } ) => { export const MarkLabel = styled.span` box-sizing: border-box; - color: ${color( 'lightGray.600' )}; + color: ${ color( 'lightGray.600' ) }; left: 0; font-size: 11px; position: absolute; @@ -158,7 +158,7 @@ export const MarkLabel = styled.span` transform: translateX( -50% ); white-space: nowrap; - ${markLabelFill}; + ${ markLabelFill }; `; export const ThumbWrapper = styled.span` @@ -175,7 +175,7 @@ export const ThumbWrapper = styled.span` user-select: none; width: 20px; - ${rtl( { marginLeft: -10 } )} + ${ rtl( { marginLeft: -10 } ) } `; const thumbFocus = ( { isFocused } ) => { @@ -197,7 +197,7 @@ export const Thumb = styled.span` align-items: center; background-color: white; border-radius: 50%; - border: 1px solid ${color( 'darkGray.200' )}; + border: 1px solid ${ color( 'darkGray.200' ) }; box-sizing: border-box; height: 100%; outline: 0; @@ -206,7 +206,7 @@ export const Thumb = styled.span` user-select: none; width: 100%; - ${thumbFocus}; + ${ thumbFocus }; `; export const InputRange = styled.input` @@ -245,7 +245,7 @@ const tooltipPosition = ( { position } ) => { }; export const Tooltip = styled.span` - background: ${color( 'ui.border' )}; + background: ${ color( 'ui.border' ) }; border-radius: 2px; box-sizing: border-box; color: white; @@ -261,13 +261,13 @@ export const Tooltip = styled.span` user-select: none; line-height: 1.4; - ${tooltipShow}; - ${tooltipPosition}; - ${reduceMotion( 'transition' )}; - ${rtl( + ${ tooltipShow }; + ${ tooltipPosition }; + ${ reduceMotion( 'transition' ) }; + ${ rtl( { transform: 'translateX(-50%)' }, { transform: 'translateX(50%)' } - )} + ) } `; export const InputNumber = styled( NumberControl )` @@ -275,13 +275,13 @@ export const InputNumber = styled( NumberControl )` display: inline-block; font-size: 13px; margin-top: 0; - width: ${space( 8 )}; + width: ${ space( 8 ) }; input[type='number']& { - ${rangeHeight}; + ${ rangeHeight }; } - ${rtl( { marginLeft: space( 2 ) } )} + ${ rtl( { marginLeft: space( 2 ) } ) } `; export const ActionRightWrapper = styled.span` @@ -292,8 +292,8 @@ export const ActionRightWrapper = styled.span` button, button.is-small { margin-left: 0; - ${rangeHeight}; + ${ rangeHeight }; } - ${rtl( { marginLeft: 8 } )} + ${ rtl( { marginLeft: 8 } ) } `; diff --git a/packages/components/src/resizable-box/resize-tooltip/styles/resize-tooltip.styles.js b/packages/components/src/resizable-box/resize-tooltip/styles/resize-tooltip.styles.js index b143c904c4f25..203bee6b3c439 100644 --- a/packages/components/src/resizable-box/resize-tooltip/styles/resize-tooltip.styles.js +++ b/packages/components/src/resizable-box/resize-tooltip/styles/resize-tooltip.styles.js @@ -31,11 +31,11 @@ export const TooltipWrapper = styled.div` `; export const Tooltip = styled.div` - background: ${color( 'ui.border' )}; + background: ${ color( 'ui.border' ) }; border-radius: 2px; box-sizing: border-box; font-size: 12px; - color: ${color( 'ui.textDark' )}; + color: ${ color( 'ui.textDark' ) }; padding: 4px 8px; position: relative; `; @@ -45,7 +45,7 @@ export const Tooltip = styled.div` export const LabelText = styled( Text )` &&& { - ${text}; + ${ text }; display: block; font-size: 13px; line-height: 1.4; diff --git a/packages/components/src/unit-control/styles/unit-control-styles.js b/packages/components/src/unit-control/styles/unit-control-styles.js index 2af691e451fb8..3c38a49685f1b 100644 --- a/packages/components/src/unit-control/styles/unit-control-styles.js +++ b/packages/components/src/unit-control/styles/unit-control-styles.js @@ -18,7 +18,7 @@ const paddingStyles = ( { disableUnits } ) => { const value = disableUnits ? 3 : 24; return css` - ${rtl( { paddingRight: value } )()}; + ${ rtl( { paddingRight: value } )() }; `; }; @@ -45,8 +45,8 @@ export const ValueInput = styled( NumberControl )` display: block; width: 100%; - ${arrowStyles}; - ${paddingStyles}; + ${ arrowStyles }; + ${ paddingStyles }; } } `; @@ -99,22 +99,22 @@ export const UnitLabel = styled.div` &&& { pointer-events: none; - ${baseUnitLabelStyles}; + ${ baseUnitLabelStyles }; } `; export const UnitSelect = styled.select` &&& { - ${baseUnitLabelStyles}; + ${ baseUnitLabelStyles }; cursor: pointer; border: 1px solid transparent; &:hover { - background-color: ${color( 'lightGray.300' )}; + background-color: ${ color( 'lightGray.300' ) }; } &:focus { - border-color: ${color( 'ui.borderFocus' )}; + border-color: ${ color( 'ui.borderFocus' ) }; outline: 2px solid transparent; outline-offset: 0; } diff --git a/packages/dependency-extraction-webpack-plugin/lib/index.js b/packages/dependency-extraction-webpack-plugin/lib/index.js index ae7b1a3d4f454..bd4c0ad992fc9 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/index.js +++ b/packages/dependency-extraction-webpack-plugin/lib/index.js @@ -175,9 +175,8 @@ class DependencyExtractionWebpackPlugin { // The type indicates the option may be `undefined`. // However, at this point in compilation, webpack has filled the options in if // they were not provided. - const outputFilename = - /** @type {{filename:string}} */ ( compiler.options.output ) - .filename; + const outputFilename = /** @type {{filename:string}} */ ( compiler + .options.output ).filename; compiler.hooks.emit.tap( this.constructor.name, ( compilation ) => { const { @@ -262,9 +261,8 @@ class DependencyExtractionWebpackPlugin { // The type indicates the option may be `undefined`. // However, at this point in compilation, webpack has filled the options in if // they were not provided. - const outputFolder = - /** @type {{path:string}} */ ( compiler.options.output ) - .path; + const outputFolder = /** @type {{path:string}} */ ( compiler + .options.output ).path; const assetsFilePath = path.resolve( outputFolder, diff --git a/packages/edit-navigation/src/store/actions.js b/packages/edit-navigation/src/store/actions.js index 5423bb002a78a..d17f03845b558 100644 --- a/packages/edit-navigation/src/store/actions.js +++ b/packages/edit-navigation/src/store/actions.js @@ -30,7 +30,7 @@ import { menuItemsQuery } from './utils'; * @param {Object} post A navigation post to process * @return {Function} An action creator */ -export const createMissingMenuItems = serializeProcessing( function*( post ) { +export const createMissingMenuItems = serializeProcessing( function* ( post ) { const menuId = post.meta.menuId; const mapping = yield { @@ -81,7 +81,7 @@ export const createMissingMenuItems = serializeProcessing( function*( post ) { * @param {Object} post A navigation post to process * @return {Function} An action creator */ -export const saveNavigationPost = serializeProcessing( function*( post ) { +export const saveNavigationPost = serializeProcessing( function* ( post ) { const menuId = post.meta.menuId; const menuItemsByClientId = mapMenuItemsByClientId( yield resolveMenuItems( menuId ), @@ -228,7 +228,7 @@ function computeCustomizedAttribute( blocks, menuId, menuItemsByClientId ) { * @return {Function} Original callback wrapped in a serial execution context */ function serializeProcessing( callback ) { - return function*( post ) { + return function* ( post ) { const postId = post.id; const isProcessing = yield isProcessingPost( postId ); diff --git a/packages/env/lib/config.js b/packages/env/lib/config.js index c790b178bd2e8..23cf929423fe5 100644 --- a/packages/env/lib/config.js +++ b/packages/env/lib/config.js @@ -417,8 +417,5 @@ async function getHomeDirectory() { * @return {string} An MD5 hash string. */ function md5( data ) { - return crypto - .createHash( 'md5' ) - .update( data ) - .digest( 'hex' ); + return crypto.createHash( 'md5' ).update( data ).digest( 'hex' ); } diff --git a/packages/eslint-plugin/rules/dependency-group.js b/packages/eslint-plugin/rules/dependency-group.js index 311a2bf37c37f..eaaf716ccade5 100644 --- a/packages/eslint-plugin/rules/dependency-group.js +++ b/packages/eslint-plugin/rules/dependency-group.js @@ -183,8 +183,8 @@ module.exports = /** @type {import('eslint').Rule.RuleModule} */ ( { let source; switch ( child.type ) { case 'ImportDeclaration': - source = - /** @type {string} */ ( child.source.value ); + source = /** @type {string} */ ( child.source + .value ); candidates.push( [ child, source ] ); break; @@ -196,8 +196,8 @@ module.exports = /** @type {import('eslint').Rule.RuleModule} */ ( { init.type !== 'CallExpression' || /** @type {import('estree').CallExpression} */ ( init ) .callee.type !== 'Identifier' || - /** @type {import('estree').Identifier} */ ( init - .callee ).name !== 'require' + /** @type {import('estree').Identifier} */ ( init.callee ) + .name !== 'require' ) { return; } diff --git a/packages/lazy-import/lib/index.js b/packages/lazy-import/lib/index.js index 4e56095909c46..bb68fd7936bce 100644 --- a/packages/lazy-import/lib/index.js +++ b/packages/lazy-import/lib/index.js @@ -21,9 +21,7 @@ const { createHash } = require( 'crypto' ); * @return {string} md5 hash of string. */ function md5( text ) { - return createHash( 'md5' ) - .update( text ) - .digest( 'hex' ); + return createHash( 'md5' ).update( text ).digest( 'hex' ); } /** diff --git a/packages/project-management-automation/lib/tasks/first-time-contributor/index.js b/packages/project-management-automation/lib/tasks/first-time-contributor/index.js index 57169524a1502..80c200cc54de5 100644 --- a/packages/project-management-automation/lib/tasks/first-time-contributor/index.js +++ b/packages/project-management-automation/lib/tasks/first-time-contributor/index.js @@ -47,8 +47,8 @@ async function firstTimeContributor( payload, octokit ) { return; } - const commit = - /** @type {WebhookPayloadPushCommit} */ ( payload.commits[ 0 ] ); + const commit = /** @type {WebhookPayloadPushCommit} */ ( payload + .commits[ 0 ] ); const pullRequest = getAssociatedPullRequest( commit ); if ( ! pullRequest ) { debug( diff --git a/packages/react-native-editor/babel.config.js b/packages/react-native-editor/babel.config.js index cfd0667bc6407..0fd51ac0d1006 100644 --- a/packages/react-native-editor/babel.config.js +++ b/packages/react-native-editor/babel.config.js @@ -1,4 +1,4 @@ -module.exports = function( api ) { +module.exports = function ( api ) { api.cache( true ); return { presets: [ 'module:metro-react-native-babel-preset' ], diff --git a/packages/react-native-editor/sass-transformer.js b/packages/react-native-editor/sass-transformer.js index afba17dac8601..978c645692b24 100644 --- a/packages/react-native-editor/sass-transformer.js +++ b/packages/react-native-editor/sass-transformer.js @@ -140,7 +140,7 @@ function transform( src, filename, options ) { return upstreamTransformer.transform( { src, filename, options } ); } -module.exports.transform = function( { src, filename, options } ) { +module.exports.transform = function ( { src, filename, options } ) { if ( filename.endsWith( '.scss' ) || filename.endsWith( '.sass' ) ) { // "auto-import" the stylesheets the GB webpack config imports src = imports + src; diff --git a/packages/react-native-editor/src/globals.js b/packages/react-native-editor/src/globals.js index c3da516884d1f..4cfebd0150f4f 100644 --- a/packages/react-native-editor/src/globals.js +++ b/packages/react-native-editor/src/globals.js @@ -34,7 +34,7 @@ global.wp = { const doc = jsdom.html( '', null, null ); // inject a simple version of the missing createHTMLDocument method that `hpq` depends on -doc.implementation.createHTMLDocument = function( html ) { +doc.implementation.createHTMLDocument = function ( html ) { return jsdom.html( html, null, null ); }; diff --git a/packages/react-native-editor/src/jsdom-patches.js b/packages/react-native-editor/src/jsdom-patches.js index 37e233a18c07c..3388a74488a44 100644 --- a/packages/react-native-editor/src/jsdom-patches.js +++ b/packages/react-native-editor/src/jsdom-patches.js @@ -45,7 +45,7 @@ const { ATTRIBUTE_NODE, DOCUMENT_FRAGMENT_NODE } = Node; * paths that make use of functions in the Gutenberg (web) project, which has * expectation that this is implemented (as it is in the browser environment). */ -Node.prototype.contains = function( otherNode ) { +Node.prototype.contains = function ( otherNode ) { return ( this === otherNode || Array.prototype.some.call( this._childNodes, ( childNode ) => { @@ -67,7 +67,7 @@ Node.prototype.contains = function( otherNode ) { * see: https://github.com/jsdom/jsdom/issues/717 for more information, * and: * https://dom.spec.whatwg.org/#dom-node-insertbefore for the latest spec. */ -Node.prototype.insertBefore = function( +Node.prototype.insertBefore = function ( /* Node */ newChild, /* Node*/ refChild ) { @@ -164,7 +164,7 @@ Element.prototype.matches = Element.prototype.matchesSelector; * Implementation of Element.prototype.closest that it's missing from the jsdom-jscore fork we're using. * See https://github.com/wordpress-mobile/gutenberg-mobile/issues/1625 */ -Element.prototype.closest = function( selector ) { +Element.prototype.closest = function ( selector ) { let el = this; while ( el ) { if ( el.matches( selector ) ) { diff --git a/packages/rich-text/src/component/index.native.js b/packages/rich-text/src/component/index.native.js index 502a6f9dcfc06..b3dfc7e1c482a 100644 --- a/packages/rich-text/src/component/index.native.js +++ b/packages/rich-text/src/component/index.native.js @@ -840,29 +840,34 @@ export class RichText extends Component { onFocus={ () => {} } /> - { // eslint-disable-next-line no-undef - __DEV__ && isMentionsSupported( capabilities ) && ( - - } - onClick={ () => { - addMention() - .then( ( mentionUserId ) => { - let stringToInsert = `@${ mentionUserId }`; - if ( this.isIOS ) { - stringToInsert += ' '; - } - this.insertString( - record, - stringToInsert - ); - } ) - .catch( () => {} ); - } } - /> - - ) } + { + // eslint-disable-next-line no-undef + __DEV__ && isMentionsSupported( capabilities ) && ( + + } + onClick={ () => { + addMention() + .then( + ( mentionUserId ) => { + let stringToInsert = `@${ mentionUserId }`; + if ( this.isIOS ) { + stringToInsert += + ' '; + } + this.insertString( + record, + stringToInsert + ); + } + ) + .catch( () => {} ); + } } + /> + + ) + } ) } From f44987d4047eef1655d40b8c6bd1988fe76f5314 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 26 Jun 2020 13:56:50 -0600 Subject: [PATCH 20/66] merge --- .../developers/data/data-core-block-editor.md | 2 +- .../developers/data/data-core.md | 24 ----------- .../downloadable-block-info/index.js | 6 ++- .../block-list/block-invalid-warning.js | 6 ++- .../components/contrast-checker/test/index.js | 42 +++---------------- .../src/components/gradient-picker/index.js | 2 +- .../src/utils/transform-styles/ast/parse.js | 12 +++--- .../ast/stringify/compiler.js | 6 +-- .../ast/stringify/compress.js | 32 +++++++------- .../ast/stringify/identity.js | 38 ++++++++--------- .../transform-styles/ast/stringify/index.js | 2 +- .../src/utils/transform-styles/traverse.js | 2 +- .../block-library/src/cover/deprecated.js | 10 +++-- .../block-library/src/post-excerpt/edit.js | 5 +-- .../alignment-matrix-control-icon-styles.js | 12 +++--- .../styles/alignment-matrix-control-styles.js | 20 ++++----- .../components/src/disabled/test/index.js | 2 +- .../components/src/external-link/index.js | 6 ++- .../src/focal-point-picker/index.js | 4 +- .../components/src/guide/test/page-control.js | 5 +-- packages/components/src/panel/test/body.js | 7 +--- packages/components/src/panel/test/header.js | 15 ++----- packages/components/src/panel/test/index.js | 36 ++++++---------- .../components/src/text/styles/text-mixins.js | 34 +++++++-------- packages/components/src/tooltip/test/index.js | 7 +--- packages/core-data/README.md | 24 ----------- .../src/utils/test/if-not-resolved.js | 8 +++- .../data/src/namespace-store/test/index.js | 2 +- packages/data/src/registry.js | 2 +- .../default-function-anonymous/code.js | 2 +- .../default-undocumented-nocomments/code.js | 2 +- .../default-undocumented-oneliner/code.js | 2 +- .../named-default-exported/module-code.js | 2 +- .../fixtures/named-default/module-code.js | 2 +- packages/dom/src/test/utils/create-element.js | 2 +- .../manage-blocks-modal/show-all.js | 6 ++- .../options/test/enable-custom-fields.js | 6 +-- .../template-switcher/theme-preview.js | 6 ++- .../src/components/document-outline/item.js | 16 +++---- .../components/post-preview-button/index.js | 6 ++- .../src/link/test/modal.native.js | 5 +-- packages/hooks/src/test/index.test.js | 2 +- .../src/components/media-upload/index.js | 5 +-- .../redux-routine/src/test/is-generator.js | 4 +- packages/shortcode/src/index.js | 4 +- 45 files changed, 172 insertions(+), 273 deletions(-) diff --git a/docs/designers-developers/developers/data/data-core-block-editor.md b/docs/designers-developers/developers/data/data-core-block-editor.md index 429f2f0fda4d8..ed2a8e15ff6fc 100644 --- a/docs/designers-developers/developers/data/data-core-block-editor.md +++ b/docs/designers-developers/developers/data/data-core-block-editor.md @@ -952,7 +952,6 @@ _Returns_ - `?boolean`: Whether the template is valid or not. - ## Actions @@ -1481,4 +1480,5 @@ _Returns_ - `Object`: Action object + diff --git a/docs/designers-developers/developers/data/data-core.md b/docs/designers-developers/developers/data/data-core.md index 905c7cb0d712b..3372d7eeab728 100644 --- a/docs/designers-developers/developers/data/data-core.md +++ b/docs/designers-developers/developers/data/data-core.md @@ -27,18 +27,6 @@ _Returns_ - `(boolean|undefined)`: Whether or not the user can perform the action, or `undefined` if the OPTIONS request is still being made. -# **getAuthor** - -Returns an Author by ID. - -_Parameters_ - -- _state_ `Object`: Data state. - -_Returns_ - -- `Array`: Authors list. - # **getAuthors** Returns all available authors. @@ -465,18 +453,6 @@ _Returns_ - `boolean`: Whether the entity record is saving or not. -# **searchAuthors** - -Returns searched authors. - -_Parameters_ - -- _state_ `Object`: Data state. - -_Returns_ - -- `Array`: Authors list. - ## Actions diff --git a/packages/block-directory/src/components/downloadable-block-info/index.js b/packages/block-directory/src/components/downloadable-block-info/index.js index d99f99524b1e3..ed4f753ec58d2 100644 --- a/packages/block-directory/src/components/downloadable-block-info/index.js +++ b/packages/block-directory/src/components/downloadable-block-info/index.js @@ -35,8 +35,10 @@ function DownloadableBlockInfo( { className="block-directory-downloadable-block-info__icon" icon={ update } /> - { // translators: %s: Humanized date of last update e.g: "2 months ago". - sprintf( __( 'Updated %s' ), humanizedUpdated ) } + { + // translators: %s: Humanized date of last update e.g: "2 months ago". + sprintf( __( 'Updated %s' ), humanizedUpdated ) + } ); diff --git a/packages/block-editor/src/components/block-list/block-invalid-warning.js b/packages/block-editor/src/components/block-list/block-invalid-warning.js index 1fa98168e96ed..73c82ae6d1b5f 100644 --- a/packages/block-editor/src/components/block-list/block-invalid-warning.js +++ b/packages/block-editor/src/components/block-list/block-invalid-warning.js @@ -62,8 +62,10 @@ export class BlockInvalidWarning extends Component { isSecondary={ hasHTMLBlock } isPrimary={ ! hasHTMLBlock } > - { // translators: Button to fix block content - _x( 'Resolve', 'imperative verb' ) } + { + // translators: Button to fix block content + _x( 'Resolve', 'imperative verb' ) + } , hasHTMLBlock && ( ); diff --git a/packages/format-library/src/link/test/modal.native.js b/packages/format-library/src/link/test/modal.native.js index d08f88a9879d3..616251f60e8d8 100644 --- a/packages/format-library/src/link/test/modal.native.js +++ b/packages/format-library/src/link/test/modal.native.js @@ -46,10 +46,7 @@ describe( 'LinksUI', () => { // When // Simulate user typing on the URL Cell. - const bottomSheet = wrapper - .dive() - .find( 'BottomSheet' ) - .first(); + const bottomSheet = wrapper.dive().find( 'BottomSheet' ).first(); const cell = bottomSheet .dive() .find( 'WithPreferredColorScheme(BottomSheetCell)' ) diff --git a/packages/hooks/src/test/index.test.js b/packages/hooks/src/test/index.test.js index 15ab466608b60..c428c1cd59dc6 100644 --- a/packages/hooks/src/test/index.test.js +++ b/packages/hooks/src/test/index.test.js @@ -716,7 +716,7 @@ test( 'Test `this` context via composition', () => { testObject.hooks = createHooks(); - const theCallback = function() { + const theCallback = function () { expect( this.test ).toBe( 'test this' ); }; addAction( 'test.action', 'my_callback', theCallback.bind( testObject ) ); diff --git a/packages/media-utils/src/components/media-upload/index.js b/packages/media-utils/src/components/media-upload/index.js index 3002864d6a46d..07fa5c0262fd2 100644 --- a/packages/media-utils/src/components/media-upload/index.js +++ b/packages/media-utils/src/components/media-upload/index.js @@ -370,10 +370,7 @@ class MediaUpload extends Component { onSelect() { const { onSelect, multiple = false } = this.props; // Get media attachment details from the frame state - const attachment = this.frame - .state() - .get( 'selection' ) - .toJSON(); + const attachment = this.frame.state().get( 'selection' ).toJSON(); onSelect( multiple ? attachment : attachment[ 0 ] ); } diff --git a/packages/redux-routine/src/test/is-generator.js b/packages/redux-routine/src/test/is-generator.js index d3b52e529596c..1c3411fb86f52 100644 --- a/packages/redux-routine/src/test/is-generator.js +++ b/packages/redux-routine/src/test/is-generator.js @@ -23,13 +23,13 @@ describe( 'isGenerator', () => { } ); it( 'should return false if an async generator', () => { - const value = ( async function*() {} )(); + const value = ( async function* () {} )(); expect( isGenerator( value ) ).toBe( false ); } ); it( 'should return true if a generator', () => { - const value = ( function*() {} )(); + const value = ( function* () {} )(); expect( isGenerator( value ) ).toBe( true ); } ); diff --git a/packages/shortcode/src/index.js b/packages/shortcode/src/index.js index 6c12810fce70d..429b2eb722175 100644 --- a/packages/shortcode/src/index.js +++ b/packages/shortcode/src/index.js @@ -90,7 +90,7 @@ export function next( tag, text, index = 0 ) { * @return {string} Text with shortcodes replaced. */ export function replace( tag, text, callback ) { - return text.replace( regexp( tag ), function( + return text.replace( regexp( tag ), function ( match, left, $3, @@ -266,7 +266,7 @@ export function fromMatch( match ) { * @return {WPShortcode} Shortcode instance. */ const shortcode = extend( - function( options ) { + function ( options ) { extend( this, pick( options || {}, 'tag', 'attrs', 'type', 'content' ) From 33c3259b936ecdcb6028ab2c39dafd8caa74d54b Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 26 Jun 2020 17:44:28 -0600 Subject: [PATCH 21/66] Simplify. --- .../developers/data/data-core.md | 12 ++ .../components/src/combobox-control/index.js | 6 +- packages/core-data/README.md | 12 ++ packages/core-data/src/resolvers.js | 18 +- packages/core-data/src/selectors.js | 15 +- .../src/components/post-author/check.js | 4 +- .../post-author/enhanced-post-author.js | 91 --------- .../src/components/post-author/index.js | 181 ++++++++++-------- 8 files changed, 141 insertions(+), 198 deletions(-) delete mode 100644 packages/editor/src/components/post-author/enhanced-post-author.js diff --git a/docs/designers-developers/developers/data/data-core.md b/docs/designers-developers/developers/data/data-core.md index 3372d7eeab728..ab191451cec0a 100644 --- a/docs/designers-developers/developers/data/data-core.md +++ b/docs/designers-developers/developers/data/data-core.md @@ -27,6 +27,18 @@ _Returns_ - `(boolean|undefined)`: Whether or not the user can perform the action, or `undefined` if the OPTIONS request is still being made. +# **getAuthor** + +Returns an Author by ID. + +_Parameters_ + +- _state_ `Object`: Data state. + +_Returns_ + +- `Array`: Authors list. + # **getAuthors** Returns all available authors. diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js index a8befe7416e5a..e80a577572943 100644 --- a/packages/components/src/combobox-control/index.js +++ b/packages/components/src/combobox-control/index.js @@ -18,6 +18,8 @@ export default function ComboboxControl( { onInputValueChange: onInputValueChange, onChange: onSelectedItemChange, value: _selectedItem, + initialInputValue, + initialHighlightedIndex, } ) { const { getLabelProps, @@ -30,12 +32,14 @@ export default function ComboboxControl( { highlightedIndex, selectedItem, } = useCombobox( { - initialSelectedItem: items[ 0 ], + initialSelectedItem: items[ initialHighlightedIndex || 0 ], + initialInputValue, items, itemToString, onInputValueChange, onSelectedItemChange, selectedItem: _selectedItem, + initialHighlightedIndex, } ); const menuProps = getMenuProps( { className: 'components-combobox-control__menu', diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 6b8c3481de0c2..4cd782e5416d0 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -253,6 +253,18 @@ _Returns_ - `(boolean|undefined)`: Whether or not the user can perform the action, or `undefined` if the OPTIONS request is still being made. +# **getAuthor** + +Returns an Author by ID. + +_Parameters_ + +- _state_ `Object`: Data state. + +_Returns_ + +- `Array`: Authors list. + # **getAuthors** Returns all available authors. diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 4749c95ce6eb4..7481436eb80b9 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -29,24 +29,16 @@ import { ifNotResolved } from './utils'; /** * Requests authors from the REST API. */ -export function* getAuthors() { - const users = yield apiFetch( { - path: '/wp/v2/users/?who=authors&per_page=100', +export function* getAuthors( query = {} ) { + const path = addQueryArgs( '/wp/v2/users/?who=authors&per_page=100', { + ...query, } ); - yield receiveUserQuery( 'authors', users ); -} -/** - * Searches for authors from the REST API. - * - * @param {string} search A search query string. - */ -export function* searchAuthors( search = '' ) { const users = yield apiFetch( { - path: `/wp/v2/users/?who=authors&per_page=100&search=${ search }`, + path, } ); - yield receiveUserQuery( 'searchAuthors', users ); + yield receiveUserQuery( `authors::${ query?.search }`, users ); } /** diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index 5c1dfab26f693..32e8b7c3773d4 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -43,19 +43,8 @@ export const isRequestingEmbedPreview = createRegistrySelector( * * @return {Array} Authors list. */ -export function getAuthors( state ) { - return getUserQueryResults( state, 'authors' ); -} - -/** - * Returns searched authors. - * - * @param {Object} state Data state. - * - * @return {Array} Authors list. - */ -export function searchAuthors( state ) { - return getUserQueryResults( state, 'searchAuthors' ); +export function getAuthors( state, query = {} ) { + return getUserQueryResults( state, `authors::${ query?.search }` ); } /** diff --git a/packages/editor/src/components/post-author/check.js b/packages/editor/src/components/post-author/check.js index 45475476545a0..4597fb6ac9c9c 100644 --- a/packages/editor/src/components/post-author/check.js +++ b/packages/editor/src/components/post-author/check.js @@ -16,10 +16,9 @@ import PostTypeSupportCheck from '../post-type-support-check'; export function PostAuthorCheck( { hasAssignAuthorAction, - authors, children, } ) { - if ( ! hasAssignAuthorAction || authors.length < 2 ) { + if ( ! hasAssignAuthorAction ) { return null; } @@ -40,7 +39,6 @@ export default compose( [ false ), postType: select( 'core/editor' ).getCurrentPostType(), - authors: select( 'core' ).getAuthors(), }; } ), withInstanceId, diff --git a/packages/editor/src/components/post-author/enhanced-post-author.js b/packages/editor/src/components/post-author/enhanced-post-author.js deleted file mode 100644 index 03ce259b6b4ef..0000000000000 --- a/packages/editor/src/components/post-author/enhanced-post-author.js +++ /dev/null @@ -1,91 +0,0 @@ -/** - * External dependencies - */ -import { debounce } from 'lodash'; - -/** - * WordPress dependencies - */ -import { useState, useMemo } from '@wordpress/element'; -import { useSelect } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import ComboboxControl from '../../../../components/build/combobox-control/'; - -function EnhancedPostAuthor( { postAuthor, authors, onUpdateAuthor } ) { - const initialAuthors = useMemo( () => { - return authors.map( ( author ) => { - return { - key: author.id, - name: author.name, - id: author.id, - }; - } ); - }, [ authors ] ); - - // Ensure the current author is included in the initial dropdown list. - let foundAuthor = initialAuthors.findIndex( - ( author ) => postAuthor?.id === author.id - ); - - if ( foundAuthor < 0 ) { - postAuthor.key = initialAuthors.length; - initialAuthors.unshift( postAuthor ); - foundAuthor = 0; - } - - // The currently field value. - const [ fieldValue, setFieldValue ] = useState( postAuthor.name ); - - /** - * Handle author selection. - * - * @param {Object} selectedItem The selected Author. - */ - const handleSelect = ( { selectedItem } ) => { - if ( ! selectedItem ) { - return; - } - setFieldValue( selectedItem.name ); - onUpdateAuthor( selectedItem.id ); - }; - - /** - * Handle user input. - * - * @param {string} inputValue The current value of the input field. - */ - const handleKeydown = ( { inputValue } ) => { - setFieldValue( inputValue ); - }; - - const availableAuthors = useSelect( - ( select ) => { - if ( '' === fieldValue || fieldValue === postAuthor.name ) { - return initialAuthors; - } - return select( 'core' ) - .searchAuthors( fieldValue ) - .map( ( author ) => ( { - key: author.id, - name: author.name, - id: author.id, - } ) ); - }, - [ fieldValue, postAuthor ] - ); - - return ( - - ); -} - -export default EnhancedPostAuthor; diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index e796830b22a9f..95f008babf2f5 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -1,95 +1,122 @@ +/** + * External dependencies + */ +import { debounce } from 'lodash'; + /** * WordPress dependencies */ +import { useState, useMemo } from '@wordpress/element'; +import { useSelect, useDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; -import { withInstanceId, compose } from '@wordpress/compose'; -import { Component } from '@wordpress/element'; -import { withSelect, withDispatch } from '@wordpress/data'; -import { decodeEntities } from '@wordpress/html-entities'; + /** * Internal dependencies */ +import ComboboxControl from '../../../../components/build/combobox-control/'; import PostAuthorCheck from './check'; -import EnhancedPostAuthor from './enhanced-post-author'; -export class PostAuthor extends Component { - constructor() { - super( ...arguments ); +function PostAuthor() { + const authors = useSelect( ( select ) => select( 'core' ).getAuthors() ); + const postAuthor = useSelect( ( select ) => + select( 'core' ).getAuthor( + select( 'core/editor' ).getEditedPostAttribute( 'author' ) + ) + ); - this.setAuthorId = this.setAuthorId.bind( this ); - } + const dispatch = useDispatch(); + + const authorsForField = useMemo( () => { + return authors.map( ( author ) => { + return { + key: author.id, + name: author.name, + id: author.id, + }; + } ); + }, [ authors ] ); + + // Ensure the current author is included in the initial dropdown list. + let foundAuthor = authorsForField.findIndex( + ( author ) => postAuthor?.id === author.id + ); + + // The currently field value. + const [ fieldValue, setFieldValue ] = useState( postAuthor?.name ); - setAuthorId( event ) { - const { onUpdateAuthor } = this.props; - const { value } = event.target; - onUpdateAuthor( Number( value ) ); + if ( authors?.length > 0 && foundAuthor < 0 && postAuthor ) { + postAuthor.key = authorsForField.length; + authors.unshift( postAuthor ); + foundAuthor = 0; } - render() { - const { - postAuthor, - postAuthorID, - instanceId, - authors, - onUpdateAuthor, - } = this.props; - const selectId = 'post-author-selector-' + instanceId; - - // Wait until we have the post author before displaying the component. - if ( ! postAuthor || 0 === postAuthor.length ) { - return null; + /** + * Handle author selection. + * + * @param {Object} selectedItem The selected Author. + */ + const handleSelect = ( { selectedItem } ) => { + if ( ! selectedItem ) { + return; } + setFieldValue( selectedItem.name ); + dispatch( 'core/editor' ).editPost( { author: selectedItem.id } ); + }; - // Disable reason: A select with an onchange throws a warning - - /* eslint-disable jsx-a11y/no-onchange */ - return ( - - - { authors.length > 50 ? ( - - ) : ( - - ) } - - ); - /* eslint-enable jsx-a11y/no-onchange */ + /** + * Handle user input. + * + * @param {string} inputValue The current value of the input field. + */ + const handleKeydown = ( { inputValue } ) => { + setFieldValue( inputValue ); + }; + + const availableAuthors = useSelect( + ( select ) => { + if ( + ! fieldValue || + '' === fieldValue || + fieldValue === postAuthor?.name + ) { + return select( 'core' ) + .getAuthors() + .map( ( author ) => ( { + key: author.id, + name: author.name, + id: author.id, + } ) ); + } + + return select( 'core' ) + .getAuthors( { search: fieldValue } ) + .map( ( author ) => ( { + key: author.id, + name: author.name, + id: author.id, + } ) ); + }, + [ fieldValue, postAuthor ] + ); + + if ( ! postAuthor ) { + return null; } + + const selectId = 'post-author-selector'; + + return ( + + + + + ); } -export default compose( [ - withSelect( ( select ) => { - return { - postAuthorID: select( 'core/editor' ).getEditedPostAttribute( - 'author' - ), - postAuthor: select( 'core' ).getAuthor( - select( 'core/editor' ).getEditedPostAttribute( 'author' ) - ), - authors: select( 'core' ).getAuthors(), - }; - } ), - withDispatch( ( dispatch ) => ( { - onUpdateAuthor( author ) { - dispatch( 'core/editor' ).editPost( { author } ); - }, - } ) ), - withInstanceId, -] )( PostAuthor ); +export default PostAuthor; From e55d62ef976652c6807a1e446af4576ac543608a Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 3 Jul 2020 12:34:11 -0600 Subject: [PATCH 22/66] Use state.users.byId in getAuthor. --- docs/designers-developers/developers/data/data-core.md | 2 ++ packages/core-data/README.md | 2 ++ packages/core-data/src/selectors.js | 8 +++++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/designers-developers/developers/data/data-core.md b/docs/designers-developers/developers/data/data-core.md index ab191451cec0a..3367835be102b 100644 --- a/docs/designers-developers/developers/data/data-core.md +++ b/docs/designers-developers/developers/data/data-core.md @@ -34,6 +34,7 @@ Returns an Author by ID. _Parameters_ - _state_ `Object`: Data state. +- _queryID_ `string`: Query ID. _Returns_ @@ -46,6 +47,7 @@ Returns all available authors. _Parameters_ - _state_ `Object`: Data state. +- _query_ `string`: Query. _Returns_ diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 4cd782e5416d0..03202e34831e2 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -260,6 +260,7 @@ Returns an Author by ID. _Parameters_ - _state_ `Object`: Data state. +- _queryID_ `string`: Query ID. _Returns_ @@ -272,6 +273,7 @@ Returns all available authors. _Parameters_ - _state_ `Object`: Data state. +- _query_ `string`: Query. _Returns_ diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index 32e8b7c3773d4..873fc962f9b70 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -40,6 +40,7 @@ export const isRequestingEmbedPreview = createRegistrySelector( * Returns all available authors. * * @param {Object} state Data state. + * @param {string} query Query. * * @return {Array} Authors list. */ @@ -78,12 +79,13 @@ export const getUserQueryResults = createSelector( /** * Returns an Author by ID. * - * @param {Object} state Data state. + * @param {Object} state Data state. + * @param {string} queryID Query ID. * * @return {Array} Authors list. */ -export function getAuthor( state ) { - return getUserQueryResults( state, 'author' )[ 0 ]; +export function getAuthor( state, queryID ) { + return state.users.byId[ queryID ]; } /** From 9024b22a9fee32231abf568f4ccb4060b4f76c07 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 3 Jul 2020 15:39:05 -0600 Subject: [PATCH 23/66] Track isLoading and latest available authors: grey out existing list during load. --- .../editor/src/components/post-author/index.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index 95f008babf2f5..e500e88d5c0ff 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -16,6 +16,7 @@ import { __ } from '@wordpress/i18n'; import ComboboxControl from '../../../../components/build/combobox-control/'; import PostAuthorCheck from './check'; +let latestAvailableAuthors; function PostAuthor() { const authors = useSelect( ( select ) => select( 'core' ).getAuthors() ); const postAuthor = useSelect( ( select ) => @@ -96,9 +97,17 @@ function PostAuthor() { id: author.id, } ) ); }, - [ fieldValue, postAuthor ] + [ fieldValue, postAuthor, isLoading ] ); + const isLoading = useSelect( ( select ) => { + return select( 'core/data' ).isResolving( 'core', 'getAuthors', [ { search: fieldValue } ] ); + }, [ availableAuthors, fieldValue ] ); + + if ( ! isLoading ) { + latestAvailableAuthors = availableAuthors; + } + if ( ! postAuthor ) { return null; } @@ -109,11 +118,12 @@ function PostAuthor() { ); From 828662a1d1e840520c5926054412e4f427768d53 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 3 Jul 2020 15:39:51 -0600 Subject: [PATCH 24/66] Use stableKey from getQueryParts. --- packages/core-data/src/resolvers.js | 4 +++- packages/core-data/src/selectors.js | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 7481436eb80b9..eb41062efcf6b 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -25,6 +25,7 @@ import { import { getKindEntities } from './entities'; import { apiFetch, resolveSelect } from './controls'; import { ifNotResolved } from './utils'; +import getQueryParts from './queried-data/get-query-parts'; /** * Requests authors from the REST API. @@ -37,8 +38,9 @@ export function* getAuthors( query = {} ) { const users = yield apiFetch( { path, } ); + const { stableKey } = getQueryParts( query ); - yield receiveUserQuery( `authors::${ query?.search }`, users ); + yield receiveUserQuery( `authors::${ stableKey }`, users ); } /** diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index 873fc962f9b70..5ee948c8f3a73 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -16,7 +16,7 @@ import deprecated from '@wordpress/deprecated'; import { REDUCER_KEY } from './name'; import { getQueriedItems } from './queried-data'; import { DEFAULT_ENTITY_KEY } from './entities'; - +import getQueryParts from './queried-data/get-query-parts'; /** * Returns true if a request is in progress for embed preview data, or false * otherwise. @@ -45,7 +45,8 @@ export const isRequestingEmbedPreview = createRegistrySelector( * @return {Array} Authors list. */ export function getAuthors( state, query = {} ) { - return getUserQueryResults( state, `authors::${ query?.search }` ); + const { stableKey } = getQueryParts( query ); + return getUserQueryResults( state, `authors::${ stableKey }` ); } /** From a89919ae19361acf68825f866c7beccd94aaf80d Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 3 Jul 2020 15:40:17 -0600 Subject: [PATCH 25/66] Add isLoading with useSelect.. --- packages/editor/src/components/post-author/index.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index e500e88d5c0ff..426a62f8c8294 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -100,9 +100,14 @@ function PostAuthor() { [ fieldValue, postAuthor, isLoading ] ); - const isLoading = useSelect( ( select ) => { - return select( 'core/data' ).isResolving( 'core', 'getAuthors', [ { search: fieldValue } ] ); - }, [ availableAuthors, fieldValue ] ); + const isLoading = useSelect( + ( select ) => { + return select( 'core/data' ).isResolving( 'core', 'getAuthors', [ + { search: fieldValue }, + ] ); + }, + [ availableAuthors, fieldValue ] + ); if ( ! isLoading ) { latestAvailableAuthors = availableAuthors; From 7f07fec4b1b55f7d0bc2bd048772a7bd836d1f8b Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 3 Jul 2020 15:40:34 -0600 Subject: [PATCH 26/66] Add they grayed out style. --- packages/components/src/combobox-control/style.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/components/src/combobox-control/style.scss b/packages/components/src/combobox-control/style.scss index 4ed994bc2af73..562859bcc33fa 100644 --- a/packages/components/src/combobox-control/style.scss +++ b/packages/components/src/combobox-control/style.scss @@ -44,6 +44,10 @@ top: 0; } } +.components-combobox-control__menu.is-loading { + color: $gray-200; + pointer-events: none; +} .components-combobox-control__menu { background: $white; From 6364458ef791edfd68303410322a6f0cf543a3af Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 3 Jul 2020 15:40:59 -0600 Subject: [PATCH 27/66] add an is-loading class when cobocox data is loading. --- packages/components/src/combobox-control/index.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js index e80a577572943..af4ca2306e5a9 100644 --- a/packages/components/src/combobox-control/index.js +++ b/packages/components/src/combobox-control/index.js @@ -14,6 +14,7 @@ export default function ComboboxControl( { className, hideLabelFromVision, label, + isLoading, options: items, onInputValueChange: onInputValueChange, onChange: onSelectedItemChange, @@ -42,7 +43,12 @@ export default function ComboboxControl( { initialHighlightedIndex, } ); const menuProps = getMenuProps( { - className: 'components-combobox-control__menu', + className: classnames( + 'components-combobox-control__menu', + { + 'is-loading': isLoading, + } + ), } ); // We need this here, because the null active descendant is not // fully ARIA compliant. From 66309974e740f6005280e126cca4415b74511dd8 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 3 Jul 2020 15:52:13 -0600 Subject: [PATCH 28/66] Add an is-loading class when loading --- packages/components/src/combobox-control/index.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js index af4ca2306e5a9..2e05292f30080 100644 --- a/packages/components/src/combobox-control/index.js +++ b/packages/components/src/combobox-control/index.js @@ -43,12 +43,9 @@ export default function ComboboxControl( { initialHighlightedIndex, } ); const menuProps = getMenuProps( { - className: classnames( - 'components-combobox-control__menu', - { - 'is-loading': isLoading, - } - ), + className: classnames( 'components-combobox-control__menu', { + 'is-loading': isLoading, + } ), } ); // We need this here, because the null active descendant is not // fully ARIA compliant. From 94f07f82521a0d2a9e56556d5949afdf583a4afb Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 3 Jul 2020 15:52:37 -0600 Subject: [PATCH 29/66] Improve component import. --- packages/components/src/index.js | 1 + packages/editor/src/components/post-author/index.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/components/src/index.js b/packages/components/src/index.js index 7c1ec414adbae..d18ba5cd07408 100644 --- a/packages/components/src/index.js +++ b/packages/components/src/index.js @@ -30,6 +30,7 @@ export { default as ClipboardButton } from './clipboard-button'; export { default as ColorIndicator } from './color-indicator'; export { default as ColorPalette } from './color-palette'; export { default as ColorPicker } from './color-picker'; +export { default as ComboboxControl } from './combobox-control'; export { default as CustomSelectControl } from './custom-select-control'; export { default as Dashicon } from './dashicon'; export { DateTimePicker, DatePicker, TimePicker } from './date-time'; diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index 426a62f8c8294..cad51d1f00d6b 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -9,11 +9,11 @@ import { debounce } from 'lodash'; import { useState, useMemo } from '@wordpress/element'; import { useSelect, useDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; +import { ComboboxControl } from '@wordpress/components'; /** * Internal dependencies */ -import ComboboxControl from '../../../../components/build/combobox-control/'; import PostAuthorCheck from './check'; let latestAvailableAuthors; From 33f5cf8908b547ccc2e41fbe1e5c8115e0e8c7d9 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 9 Jul 2020 08:48:21 -0600 Subject: [PATCH 30/66] Keys can be empty. --- packages/core-data/src/resolvers.js | 2 +- packages/core-data/src/selectors.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index eb41062efcf6b..b8692a5dae82f 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -40,7 +40,7 @@ export function* getAuthors( query = {} ) { } ); const { stableKey } = getQueryParts( query ); - yield receiveUserQuery( `authors::${ stableKey }`, users ); + yield receiveUserQuery( stableKey, users ); } /** diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index 5ee948c8f3a73..27abd9839c3b3 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -46,7 +46,7 @@ export const isRequestingEmbedPreview = createRegistrySelector( */ export function getAuthors( state, query = {} ) { const { stableKey } = getQueryParts( query ); - return getUserQueryResults( state, `authors::${ stableKey }` ); + return getUserQueryResults( state, stableKey ); } /** From a5c4ef222b0b3a43a8f0060ebc11729e743187da Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 9 Jul 2020 09:52:26 -0600 Subject: [PATCH 31/66] Remove extraneous spread --- packages/core-data/src/resolvers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index b8692a5dae82f..1dc18d93dde7c 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -32,7 +32,7 @@ import getQueryParts from './queried-data/get-query-parts'; */ export function* getAuthors( query = {} ) { const path = addQueryArgs( '/wp/v2/users/?who=authors&per_page=100', { - ...query, + query, } ); const users = yield apiFetch( { From 254c07a5d2f6e719158398b9c2a8a3e79c3b4620 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 9 Jul 2020 09:58:22 -0600 Subject: [PATCH 32/66] Update naming to authorID, restore spread. --- docs/designers-developers/developers/data/data-core.md | 2 +- packages/core-data/README.md | 2 +- packages/core-data/src/resolvers.js | 2 +- packages/core-data/src/selectors.js | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/designers-developers/developers/data/data-core.md b/docs/designers-developers/developers/data/data-core.md index 3367835be102b..f78ab9507cf9c 100644 --- a/docs/designers-developers/developers/data/data-core.md +++ b/docs/designers-developers/developers/data/data-core.md @@ -34,7 +34,7 @@ Returns an Author by ID. _Parameters_ - _state_ `Object`: Data state. -- _queryID_ `string`: Query ID. +- _authorID_ `string`: The Author ID. _Returns_ diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 03202e34831e2..0a8d96da2a2e3 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -260,7 +260,7 @@ Returns an Author by ID. _Parameters_ - _state_ `Object`: Data state. -- _queryID_ `string`: Query ID. +- _authorID_ `string`: The Author ID. _Returns_ diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 1dc18d93dde7c..b8692a5dae82f 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -32,7 +32,7 @@ import getQueryParts from './queried-data/get-query-parts'; */ export function* getAuthors( query = {} ) { const path = addQueryArgs( '/wp/v2/users/?who=authors&per_page=100', { - query, + ...query, } ); const users = yield apiFetch( { diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index 27abd9839c3b3..f9a05d7d744f5 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -80,13 +80,13 @@ export const getUserQueryResults = createSelector( /** * Returns an Author by ID. * - * @param {Object} state Data state. - * @param {string} queryID Query ID. + * @param {Object} state Data state. + * @param {string} authorID The Author ID. * * @return {Array} Authors list. */ -export function getAuthor( state, queryID ) { - return state.users.byId[ queryID ]; +export function getAuthor( state, authorID ) { + return state.users.byId[ authorID ]; } /** From d700436a80faba003c4cbb7b60f3f64b5d19f885 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 9 Jul 2020 11:09:30 -0600 Subject: [PATCH 33/66] Switch to `initialSelectedItem`; improve selected item matching with `isEqual`. --- .../components/src/combobox-control/index.js | 12 ++++-------- .../editor/src/components/post-author/index.js | 16 ++++++++-------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js index 2e05292f30080..44413a4e23bdc 100644 --- a/packages/components/src/combobox-control/index.js +++ b/packages/components/src/combobox-control/index.js @@ -3,6 +3,7 @@ */ import { useCombobox } from 'downshift'; import classnames from 'classnames'; +import { isEqual } from 'lodash'; /** * Internal dependencies @@ -18,9 +19,7 @@ export default function ComboboxControl( { options: items, onInputValueChange: onInputValueChange, onChange: onSelectedItemChange, - value: _selectedItem, - initialInputValue, - initialHighlightedIndex, + initialSelectedItem, } ) { const { getLabelProps, @@ -33,14 +32,11 @@ export default function ComboboxControl( { highlightedIndex, selectedItem, } = useCombobox( { - initialSelectedItem: items[ initialHighlightedIndex || 0 ], - initialInputValue, + initialSelectedItem, items, itemToString, onInputValueChange, onSelectedItemChange, - selectedItem: _selectedItem, - initialHighlightedIndex, } ); const menuProps = getMenuProps( { className: classnames( 'components-combobox-control__menu', { @@ -118,7 +114,7 @@ export default function ComboboxControl( { style: item.style, } ) } > - { item === selectedItem && ( + { isEqual( item, selectedItem ) && ( postAuthor?.id === author.id + ( author ) => postAuthor?.id === author.key ); - // The currently field value. const [ fieldValue, setFieldValue ] = useState( postAuthor?.name ); @@ -50,7 +48,6 @@ function PostAuthor() { authors.unshift( postAuthor ); foundAuthor = 0; } - /** * Handle author selection. * @@ -61,7 +58,7 @@ function PostAuthor() { return; } setFieldValue( selectedItem.name ); - dispatch( 'core/editor' ).editPost( { author: selectedItem.id } ); + dispatch( 'core/editor' ).editPost( { author: selectedItem.key } ); }; /** @@ -85,7 +82,6 @@ function PostAuthor() { .map( ( author ) => ( { key: author.id, name: author.name, - id: author.id, } ) ); } @@ -94,7 +90,6 @@ function PostAuthor() { .map( ( author ) => ( { key: author.id, name: author.name, - id: author.id, } ) ); }, [ fieldValue, postAuthor, isLoading ] @@ -119,6 +114,11 @@ function PostAuthor() { const selectId = 'post-author-selector'; + const postAuthorEntry = { + key: postAuthor.id, + name: postAuthor.name, + }; + return ( @@ -127,7 +127,7 @@ function PostAuthor() { initialInputValue={ postAuthor?.name } onInputValueChange={ debounce( handleKeydown, 300 ) } onChange={ handleSelect } - initialHighlightedIndex={ foundAuthor } + initialSelectedItem={ postAuthorEntry } isLoading={ isLoading } /> From f92239e1ceaa286cc6c194d82d54257aa6a6fe2d Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 9 Jul 2020 11:15:55 -0600 Subject: [PATCH 34/66] Revert changes to post-author check. --- packages/editor/src/components/post-author/check.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-author/check.js b/packages/editor/src/components/post-author/check.js index 4597fb6ac9c9c..45475476545a0 100644 --- a/packages/editor/src/components/post-author/check.js +++ b/packages/editor/src/components/post-author/check.js @@ -16,9 +16,10 @@ import PostTypeSupportCheck from '../post-type-support-check'; export function PostAuthorCheck( { hasAssignAuthorAction, + authors, children, } ) { - if ( ! hasAssignAuthorAction ) { + if ( ! hasAssignAuthorAction || authors.length < 2 ) { return null; } @@ -39,6 +40,7 @@ export default compose( [ false ), postType: select( 'core/editor' ).getCurrentPostType(), + authors: select( 'core' ).getAuthors(), }; } ), withInstanceId, From 2f48155b48c7dfebabdd2d350f73eeeb36d7f599 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 9 Jul 2020 11:46:17 -0600 Subject: [PATCH 35/66] Remove latestAvailableAuthors and use spinner instead for load. --- packages/components/src/combobox-control/index.js | 6 +++++- packages/components/src/combobox-control/style.scss | 4 ---- packages/editor/src/components/post-author/index.js | 7 +------ 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js index 44413a4e23bdc..a9aaacdce93a2 100644 --- a/packages/components/src/combobox-control/index.js +++ b/packages/components/src/combobox-control/index.js @@ -5,10 +5,11 @@ import { useCombobox } from 'downshift'; import classnames from 'classnames'; import { isEqual } from 'lodash'; + /** * Internal dependencies */ -import { Button, Dashicon } from '../'; +import { Button, Dashicon, Spinner} from '../'; const itemToString = ( item ) => item && item.name; export default function ComboboxControl( { @@ -71,6 +72,9 @@ export default function ComboboxControl( { > { label } + { isLoading && ( + + ) }
select( 'core' ).getAuthors() ); const postAuthor = useSelect( ( select ) => @@ -104,10 +103,6 @@ function PostAuthor() { [ availableAuthors, fieldValue ] ); - if ( ! isLoading ) { - latestAvailableAuthors = availableAuthors; - } - if ( ! postAuthor ) { return null; } @@ -123,7 +118,7 @@ function PostAuthor() { Date: Thu, 9 Jul 2020 15:10:52 -0600 Subject: [PATCH 36/66] cleanup --- packages/components/src/combobox-control/index.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js index a9aaacdce93a2..122e2cff4504e 100644 --- a/packages/components/src/combobox-control/index.js +++ b/packages/components/src/combobox-control/index.js @@ -5,11 +5,10 @@ import { useCombobox } from 'downshift'; import classnames from 'classnames'; import { isEqual } from 'lodash'; - /** * Internal dependencies */ -import { Button, Dashicon, Spinner} from '../'; +import { Button, Dashicon, Spinner } from '../'; const itemToString = ( item ) => item && item.name; export default function ComboboxControl( { @@ -72,9 +71,7 @@ export default function ComboboxControl( { > { label } - { isLoading && ( - - ) } + { isLoading && }
Date: Tue, 7 Jul 2020 13:42:43 -0700 Subject: [PATCH 37/66] Editor still loads if page or template type is not set --- .../edit-site/src/components/editor/index.js | 38 +++++++++++-------- .../src/components/page-switcher/index.js | 10 ++--- .../src/components/save-button/index.js | 1 - .../src/components/template-switcher/index.js | 25 ++++-------- 4 files changed, 35 insertions(+), 39 deletions(-) diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index f61e30ecf34f3..94a909bed1eaa 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -82,11 +82,15 @@ function Editor() { templatePartId: _templatePartId, templateType: _templateType, page: getPage(), - template: _select( 'core' ).getEntityRecord( - 'postType', - _templateType, - _templateType === 'wp_template' ? _templateId : _templatePartId - ), + template: _templateType + ? _select( 'core' ).getEntityRecord( + 'postType', + _templateType, + _templateType === 'wp_template' + ? _templateId + : _templatePartId + ) + : null, select: _select, }; }, [] ); @@ -125,25 +129,31 @@ function Editor() { // and Query Pagination blocks. const blockContext = useMemo( () => ( { - ...page.context, - query: page.context.query || { categoryIds: [] }, + ...page?.context, + query: page?.context.query || { categoryIds: [] }, queryContext: [ - page.context.queryContext || { page: 1 }, + page?.context.queryContext || { page: 1 }, ( newQueryContext ) => setPage( { ...page, context: { - ...page.context, + ...page?.context, queryContext: { - ...page.context.queryContext, + ...page?.context.queryContext, ...newQueryContext, }, }, } ), ], } ), - [ page.context ] + [ page?.context ] ); + + let entityId; + if ( templateType ) { + entityId = templateType === 'wp_template' ? templateId : templatePartId; + } + return ( <> @@ -154,11 +164,7 @@ function Editor() { diff --git a/packages/edit-site/src/components/page-switcher/index.js b/packages/edit-site/src/components/page-switcher/index.js index 53629bd88ea7a..5200ee9d95eee 100644 --- a/packages/edit-site/src/components/page-switcher/index.js +++ b/packages/edit-site/src/components/page-switcher/index.js @@ -111,8 +111,8 @@ export default function PageSwitcher( { toggleProps={ { children: [ ...pages, ...categories, ...posts ].find( - ( choice ) => choice.value === activePage.path - )?.label || activePage.path, + ( choice ) => choice.value === activePage?.path + )?.label || activePage?.path, } } menuProps={ { className: 'edit-site-page-switcher__menu' } } > @@ -121,21 +121,21 @@ export default function PageSwitcher( { isSavingEntityRecord( record.kind, record.name, record.key ) ), - templateType: select( 'core/edit-site' ).getTemplateType(), }; } ); diff --git a/packages/edit-site/src/components/template-switcher/index.js b/packages/edit-site/src/components/template-switcher/index.js index e713cbaf8c1ab..a1537253dbe0b 100644 --- a/packages/edit-site/src/components/template-switcher/index.js +++ b/packages/edit-site/src/components/template-switcher/index.js @@ -2,8 +2,8 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { useRegistry, useSelect } from '@wordpress/data'; -import { useEffect, useState } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; +import { useState } from '@wordpress/element'; import { Tooltip, DropdownMenu, @@ -16,7 +16,6 @@ import { Icon, home, plus, undo } from '@wordpress/icons'; /** * Internal dependencies */ -import { findTemplate } from '../../utils'; import TemplatePreview from './template-preview'; import ThemePreview from './theme-preview'; @@ -69,20 +68,7 @@ export default function TemplateSwitcher( { setThemePreviewVisible( () => false ); }; - const registry = useRegistry(); - const [ homeId, setHomeId ] = useState(); - - useEffect( () => { - findTemplate( - '/', - registry.__experimentalResolveSelect( 'core' ).getEntityRecords - ).then( - ( newHomeId ) => setHomeId( newHomeId ), - () => setHomeId( null ) - ); - }, [ registry ] ); - - const { currentTheme, template, templateParts } = useSelect( + const { currentTheme, template, templateParts, homeId } = useSelect( ( select ) => { const { getCurrentTheme, @@ -96,6 +82,8 @@ export default function TemplateSwitcher( { activeId ); + const { getHomeTemplateId } = select( 'core/edit-site' ); + return { currentTheme: getCurrentTheme(), template: _template, @@ -105,6 +93,7 @@ export default function TemplateSwitcher( { template: _template.slug, } ) : null, + homeId: getHomeTemplateId(), }; }, [ activeId ] @@ -128,9 +117,11 @@ export default function TemplateSwitcher( { } ) ); const overwriteSlug = + page && TEMPLATE_OVERRIDES[ page.type ] && page.slug && TEMPLATE_OVERRIDES[ page.type ]( page.slug ); + const overwriteTemplate = () => onAddTemplate( { slug: overwriteSlug, From a379413d738a01d9b57d39d56dd072a5383b7cbe Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Tue, 7 Jul 2020 13:46:06 -0700 Subject: [PATCH 38/66] Create homepage state reducer --- packages/edit-site/src/store/reducer.js | 34 ++++++++++++----------- packages/edit-site/src/store/selectors.js | 14 +++++----- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/packages/edit-site/src/store/reducer.js b/packages/edit-site/src/store/reducer.js index bd7cfd8740eb1..1423397bf44c3 100644 --- a/packages/edit-site/src/store/reducer.js +++ b/packages/edit-site/src/store/reducer.js @@ -85,17 +85,6 @@ export function settings( state = {}, action ) { return state; } -/** - * Reducer returning the home template ID. - * - * @param {Object} state Current state. - * - * @return {Object} Updated state. - */ -export function homeTemplateId( state ) { - return state; -} - /** * Reducer returning the template ID. * @@ -159,7 +148,7 @@ export function templateType( state, action ) { * * @return {Object} Updated state. */ -export function page( state = {}, action ) { +export function page( state, action ) { switch ( action.type ) { case 'SET_PAGE': return action.page; @@ -169,13 +158,27 @@ export function page( state = {}, action ) { } /** - * Reducer returning the site's `show_on_front` setting. + * Reducer for information about the site's homepage. * * @param {Object} state Current state. + * @param {Object} action Dispatched action. * * @return {Object} Updated state. */ -export function showOnFront( state ) { +export function home( state = {}, action ) { + switch ( action.type ) { + case 'SET_HOME_TEMPLATE': + return { + ...state, + templateId: action.templateId, + }; + case 'SET_SHOW_ON_FRONT': + return { + ...state, + showOnFront: action.showOnFront, + }; + } + return state; } @@ -183,10 +186,9 @@ export default combineReducers( { preferences, deviceType, settings, - homeTemplateId, templateId, templatePartId, templateType, page, - showOnFront, + home, } ); diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js index 9e98f3ba36191..49fce90bd9747 100644 --- a/packages/edit-site/src/store/selectors.js +++ b/packages/edit-site/src/store/selectors.js @@ -88,10 +88,10 @@ export const getSettings = createSelector( * * @param {Object} state Global application state. * - * @return {number} Home template ID. + * @return {number?} Home template ID. */ export function getHomeTemplateId( state ) { - return state.homeTemplateId; + return state.home.templateId; } /** @@ -99,7 +99,7 @@ export function getHomeTemplateId( state ) { * * @param {Object} state Global application state. * - * @return {number} Template ID. + * @return {number?} Template ID. */ export function getTemplateId( state ) { return state.templateId; @@ -110,7 +110,7 @@ export function getTemplateId( state ) { * * @param {Object} state Global application state. * - * @return {number} Template part ID. + * @return {number?} Template part ID. */ export function getTemplatePartId( state ) { return state.templatePartId; @@ -121,7 +121,7 @@ export function getTemplatePartId( state ) { * * @param {Object} state Global application state. * - * @return {string} Template type. + * @return {string?} Template type. */ export function getTemplateType( state ) { return state.templateType; @@ -143,8 +143,8 @@ export function getPage( state ) { * * @param {Object} state Global application state. * - * @return {Object} The setting. + * @return {string?} The setting. */ export function getShowOnFront( state ) { - return state.showOnFront; + return state.home.showOnFront; } From 62b37d7066da1fbe7251890436a0085901396eb8 Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Tue, 7 Jul 2020 13:46:32 -0700 Subject: [PATCH 39/66] Remove initial state from PHP --- lib/edit-site-page.php | 12 ------------ packages/edit-site/src/index.js | 5 +---- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/lib/edit-site-page.php b/lib/edit-site-page.php index a811770b3eef3..1558e52f6b5d1 100644 --- a/lib/edit-site-page.php +++ b/lib/edit-site-page.php @@ -145,18 +145,6 @@ function gutenberg_edit_site_init( $hook ) { } $settings['styles'] = gutenberg_get_editor_styles(); - $settings['editSiteInitialState'] = array(); - - $settings['editSiteInitialState']['templateType'] = 'wp_template'; - $settings['editSiteInitialState']['showOnFront'] = get_option( 'show_on_front' ); - $settings['editSiteInitialState']['page'] = array( - 'path' => '/', - 'context' => 'page' === $settings['editSiteInitialState']['showOnFront'] ? array( - 'postType' => 'page', - 'postId' => get_option( 'page_on_front' ), - ) : array(), - ); - // This is so other parts of the code can hook their own settings. // Example: Global Styles. global $post; diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 3607eae790820..08a0e3993f0e9 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -54,10 +54,7 @@ const fetchLinkSuggestions = ( search, { perPage = 20 } = {} ) => export function initialize( id, settings ) { settings.__experimentalFetchLinkSuggestions = fetchLinkSuggestions; - const initialState = settings.editSiteInitialState; - delete settings.editSiteInitialState; - initialState.settings = settings; - registerEditSiteStore( initialState ); + registerEditSiteStore( { settings } ); registerCoreBlocks(); if ( process.env.GUTENBERG_PHASE === 2 ) { From 4af2c1c107bbb3bfcbcb63157f3f1326db3a3129 Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Tue, 7 Jul 2020 16:00:09 -0700 Subject: [PATCH 40/66] Move home page resolution to client --- lib/edit-site-page.php | 3 ++ packages/edit-site/src/index.js | 10 ++++++- packages/edit-site/src/store/actions.js | 36 ++++++++++++++++++----- packages/edit-site/src/store/index.js | 14 ++++++++- packages/edit-site/src/store/reducer.js | 5 ---- packages/edit-site/src/store/selectors.js | 11 +++++++ 6 files changed, 64 insertions(+), 15 deletions(-) diff --git a/lib/edit-site-page.php b/lib/edit-site-page.php index 1558e52f6b5d1..8e3434fd47d7c 100644 --- a/lib/edit-site-page.php +++ b/lib/edit-site-page.php @@ -145,6 +145,9 @@ function gutenberg_edit_site_init( $hook ) { } $settings['styles'] = gutenberg_get_editor_styles(); + $settings['showOnFront'] = get_option( 'show_on_front' ); + $settings['pageOnFront'] = get_option( 'page_on_front' ); + // This is so other parts of the code can hook their own settings. // Example: Global Styles. global $post; diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 08a0e3993f0e9..217bd604fd0f2 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -54,7 +54,15 @@ const fetchLinkSuggestions = ( search, { perPage = 20 } = {} ) => export function initialize( id, settings ) { settings.__experimentalFetchLinkSuggestions = fetchLinkSuggestions; - registerEditSiteStore( { settings } ); + const initialState = { + settings, + home: { + showOnFront: settings.showOnFront, + pageOnFront: settings.pageOnFront, + }, + }; + + registerEditSiteStore( initialState ); registerCoreBlocks(); if ( process.env.GUTENBERG_PHASE === 2 ) { diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index c68baf50a5509..ed358c1b25f49 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -107,19 +107,39 @@ export function setTemplatePart( templatePartId ) { /** * Resolves the template for a page and sets them. * - * @param {Object} page The page object. - * @param {string} page.type The page type. - * @param {string} page.slug The page slug. - * @param {string} page.path The page path. - * @param {Object} page.context The page context. + * @param {Object} page The page object. + * @param {string} page.type The page type. + * @param {string} page.slug The page slug. + * @param {string} page.path The page path. + * @param {Object} page.context The page context. + * @param {number?} templateId An optional template ID for the page to avoid a second fetch if we already know it. * * @return {Object} Action object. */ -export function* setPage( page ) { - const templateId = yield findTemplate( page.path ); +export function* setPage( page, templateId ) { + const resolvedTemplate = templateId ?? ( yield findTemplate( page.path ) ); return { type: 'SET_PAGE', page, - templateId, + templateId: resolvedTemplate, }; } + +/** + * Sets up the initial template and page for edit site, and fetches other + * information it needs. + * + * @param {Object} initialPage The initial page to load in the site editor. + */ +export function* setupState( initialPage ) { + const homeTemplateId = yield findTemplate( '/' ); + dispatch( { + type: 'SET_HOME_TEMPLATE', + homeTemplateId, + } ); + + yield setPage( + initialPage, + initialPage.path === '/' ? homeTemplateId : null + ); +} diff --git a/packages/edit-site/src/store/index.js b/packages/edit-site/src/store/index.js index 06bcf529febe1..d3d29f4d1ae26 100644 --- a/packages/edit-site/src/store/index.js +++ b/packages/edit-site/src/store/index.js @@ -23,8 +23,20 @@ export default function registerEditSiteStore( initialState ) { initialState, } ); + const { showOnFront, pageOnFront } = initialState.home; + const initialPage = { + path: '/', + context: + showOnFront === 'page' + ? { + postType: 'page', + postId: pageOnFront, + } + : {}, + }; + // We set the initial page here to include the template fetch which will // resolve the correct homepage template. - store.dispatch( actions.setPage( initialState.page ) ); + store.dispatch( actions.setupState( initialPage ) ); return store; } diff --git a/packages/edit-site/src/store/reducer.js b/packages/edit-site/src/store/reducer.js index 1423397bf44c3..37e291a7b0aec 100644 --- a/packages/edit-site/src/store/reducer.js +++ b/packages/edit-site/src/store/reducer.js @@ -172,11 +172,6 @@ export function home( state = {}, action ) { ...state, templateId: action.templateId, }; - case 'SET_SHOW_ON_FRONT': - return { - ...state, - showOnFront: action.showOnFront, - }; } return state; diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js index 49fce90bd9747..7eb993003ed63 100644 --- a/packages/edit-site/src/store/selectors.js +++ b/packages/edit-site/src/store/selectors.js @@ -148,3 +148,14 @@ export function getPage( state ) { export function getShowOnFront( state ) { return state.home.showOnFront; } + +/** + * Returns the site's current `page_on_front` setting. + * + * @param {Object} state Global application state. + * + * @return {number?} The setting. + */ +export function getPageOnFront( state ) { + return state.home.pageOnFront; +} From 95124bf52770f537be420d795b9429b2ba13eb67 Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Thu, 9 Jul 2020 11:46:49 -0700 Subject: [PATCH 41/66] Consolidate entityId logic --- .../edit-site/src/components/editor/index.js | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 94a909bed1eaa..e67aaa4b73823 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -52,8 +52,7 @@ function Editor() { deviceType, sidebarIsOpened, settings, - templateId, - templatePartId, + entityId, templateType, page, template, @@ -71,6 +70,14 @@ function Editor() { const _templateId = getTemplateId(); const _templatePartId = getTemplatePartId(); const _templateType = getTemplateType(); + + // The currently selected entity to display. Typically template or template part. + let _entityId; + if ( _templateType ) { + _entityId = + _templateType === 'wp_template' ? _templateId : _templatePartId; + } + return { isFullscreenActive: isFeatureActive( 'fullscreenMode' ), deviceType: __experimentalGetPreviewDeviceType(), @@ -78,20 +85,17 @@ function Editor() { 'core/interface' ).getActiveComplementaryArea( 'core/edit-site' ), settings: getSettings(), - templateId: _templateId, - templatePartId: _templatePartId, templateType: _templateType, page: getPage(), template: _templateType ? _select( 'core' ).getEntityRecord( 'postType', _templateType, - _templateType === 'wp_template' - ? _templateId - : _templatePartId + _entityId ) : null, select: _select, + entityId: _entityId, }; }, [] ); const { editEntityRecord } = useDispatch( 'core' ); @@ -149,11 +153,6 @@ function Editor() { [ page?.context ] ); - let entityId; - if ( templateType ) { - entityId = templateType === 'wp_template' ? templateId : templatePartId; - } - return ( <> From 9fe3fea9a36ddc837b111837f6891bae10bae9a7 Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Thu, 9 Jul 2020 11:49:22 -0700 Subject: [PATCH 42/66] Consolidate activePage?.path --- .../edit-site/src/components/page-switcher/index.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/edit-site/src/components/page-switcher/index.js b/packages/edit-site/src/components/page-switcher/index.js index 5200ee9d95eee..ffef44bc45dc2 100644 --- a/packages/edit-site/src/components/page-switcher/index.js +++ b/packages/edit-site/src/components/page-switcher/index.js @@ -97,6 +97,7 @@ export default function PageSwitcher( { ].find( ( choice ) => choice.value === newPath ); onActivePageChange( { ...rest, path } ); }; + const onPostSelect = ( post ) => onActivePageChange( { type: 'post', @@ -104,6 +105,8 @@ export default function PageSwitcher( { path: getPathAndQueryString( post.url ), context: { postType: post.type, postId: post.id }, } ); + + const activePath = activePage?.path; return ( choice.value === activePage?.path - )?.label || activePage?.path, + ( choice ) => choice.value === activePath + )?.label || activePath, } } menuProps={ { className: 'edit-site-page-switcher__menu' } } > @@ -121,21 +124,21 @@ export default function PageSwitcher( { Date: Thu, 9 Jul 2020 12:00:24 -0700 Subject: [PATCH 43/66] Rework setupstate --- packages/edit-site/src/store/actions.js | 40 +++++++++++-------------- packages/edit-site/src/store/index.js | 7 +++-- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index ed358c1b25f49..c7bd24fca45f3 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -104,6 +104,20 @@ export function setTemplatePart( templatePartId ) { }; } +/** + * Updates the homeTemplateId state with the templateId of the page resolved + * from the given path. + * + * @param {string} path The path to the page which should be set as the homepage. + */ +export function* setHomeTemplatePath( path ) { + const homeTemplateId = yield findTemplate( path ); + dispatch( { + type: 'SET_HOME_TEMPLATE', + homeTemplateId, + } ); +} + /** * Resolves the template for a page and sets them. * @@ -112,34 +126,14 @@ export function setTemplatePart( templatePartId ) { * @param {string} page.slug The page slug. * @param {string} page.path The page path. * @param {Object} page.context The page context. - * @param {number?} templateId An optional template ID for the page to avoid a second fetch if we already know it. * * @return {Object} Action object. */ -export function* setPage( page, templateId ) { - const resolvedTemplate = templateId ?? ( yield findTemplate( page.path ) ); +export function* setPage( page ) { + const templateId = yield findTemplate( page.path ); return { type: 'SET_PAGE', page, - templateId: resolvedTemplate, + templateId, }; } - -/** - * Sets up the initial template and page for edit site, and fetches other - * information it needs. - * - * @param {Object} initialPage The initial page to load in the site editor. - */ -export function* setupState( initialPage ) { - const homeTemplateId = yield findTemplate( '/' ); - dispatch( { - type: 'SET_HOME_TEMPLATE', - homeTemplateId, - } ); - - yield setPage( - initialPage, - initialPage.path === '/' ? homeTemplateId : null - ); -} diff --git a/packages/edit-site/src/store/index.js b/packages/edit-site/src/store/index.js index d3d29f4d1ae26..a9f3175d57c9f 100644 --- a/packages/edit-site/src/store/index.js +++ b/packages/edit-site/src/store/index.js @@ -35,8 +35,9 @@ export default function registerEditSiteStore( initialState ) { : {}, }; - // We set the initial page here to include the template fetch which will - // resolve the correct homepage template. - store.dispatch( actions.setupState( initialPage ) ); + // Setup async data for the store. + store.dispatch( actions.setHomeTemplatePath( '/' ) ); + store.dispatch( actions.setPage( initialPage ) ); + return store; } From f9b2d5216731a75e4accf734be0677023c23d726 Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Thu, 9 Jul 2020 12:53:10 -0700 Subject: [PATCH 44/66] Load home data over API --- lib/edit-site-page.php | 33 ++++++++++++-- .../edit-site/src/components/header/index.js | 10 ++++- packages/edit-site/src/index.js | 10 +---- packages/edit-site/src/store/actions.js | 45 +++++++++++++++---- packages/edit-site/src/store/index.js | 16 +------ packages/edit-site/src/store/reducer.js | 9 ++-- packages/edit-site/src/store/selectors.js | 24 +--------- 7 files changed, 80 insertions(+), 67 deletions(-) diff --git a/lib/edit-site-page.php b/lib/edit-site-page.php index 8e3434fd47d7c..dee3ef7cdc6ff 100644 --- a/lib/edit-site-page.php +++ b/lib/edit-site-page.php @@ -145,9 +145,6 @@ function gutenberg_edit_site_init( $hook ) { } $settings['styles'] = gutenberg_get_editor_styles(); - $settings['showOnFront'] = get_option( 'show_on_front' ); - $settings['pageOnFront'] = get_option( 'page_on_front' ); - // This is so other parts of the code can hook their own settings. // Example: Global Styles. global $post; @@ -216,3 +213,33 @@ function gutenberg_edit_site_init( $hook ) { wp_enqueue_style( 'wp-format-library' ); } add_action( 'admin_enqueue_scripts', 'gutenberg_edit_site_init' ); + +/** + * Register a core site setting for front page information. + */ +function register_site_editor_homepage_settings() { + register_setting( + 'general', + 'show_on_front', + array( + 'show_in_rest' => array( + 'name' => 'show_on_front', + ), + 'type' => 'string', + 'description' => __( 'Whether to show posts or a static page for the front page.' ), + ) + ); + + register_setting( + 'general', + 'page_on_front', + array( + 'show_in_rest' => array( + 'name' => 'page_on_front', + ), + 'type' => 'number', + 'description' => __( 'The page ID to show on the front page.' ), + ) + ); +} +add_action( 'rest_api_init', 'register_site_editor_homepage_settings', 10 ); diff --git a/packages/edit-site/src/components/header/index.js b/packages/edit-site/src/components/header/index.js index fe9eb71ada311..2ab4b1d84d304 100644 --- a/packages/edit-site/src/components/header/index.js +++ b/packages/edit-site/src/components/header/index.js @@ -49,8 +49,14 @@ export default function Header( { getTemplatePartId, getTemplateType, getPage, - getShowOnFront, } = select( 'core/edit-site' ); + + // eslint-disable-next-line camelcase + const { show_on_front } = select( 'core' ).getEditedEntityRecord( + 'root', + 'site' + ); + return { deviceType: __experimentalGetPreviewDeviceType(), hasFixedToolbar: isFeatureActive( 'fixedToolbar' ), @@ -58,7 +64,7 @@ export default function Header( { templatePartId: getTemplatePartId(), templateType: getTemplateType(), page: getPage(), - showOnFront: getShowOnFront(), + showOnFront: show_on_front, }; }, [] ); diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 217bd604fd0f2..08a0e3993f0e9 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -54,15 +54,7 @@ const fetchLinkSuggestions = ( search, { perPage = 20 } = {} ) => export function initialize( id, settings ) { settings.__experimentalFetchLinkSuggestions = fetchLinkSuggestions; - const initialState = { - settings, - home: { - showOnFront: settings.showOnFront, - pageOnFront: settings.pageOnFront, - }, - }; - - registerEditSiteStore( initialState ); + registerEditSiteStore( { settings } ); registerCoreBlocks(); if ( process.env.GUTENBERG_PHASE === 2 ) { diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index c7bd24fca45f3..236fbb4535d09 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -108,32 +108,59 @@ export function setTemplatePart( templatePartId ) { * Updates the homeTemplateId state with the templateId of the page resolved * from the given path. * - * @param {string} path The path to the page which should be set as the homepage. + * @param {number} homeTemplateId The template ID for the homepage. */ -export function* setHomeTemplatePath( path ) { - const homeTemplateId = yield findTemplate( path ); - dispatch( { +export function setHomeTemplateId( homeTemplateId ) { + return { type: 'SET_HOME_TEMPLATE', homeTemplateId, - } ); + }; } /** - * Resolves the template for a page and sets them. + * Resolves the template for a page if no templateId is passed and sets them. * * @param {Object} page The page object. * @param {string} page.type The page type. * @param {string} page.slug The page slug. * @param {string} page.path The page path. * @param {Object} page.context The page context. + * @param {number?} templateId The template ID for the page if we already know it. * * @return {Object} Action object. */ -export function* setPage( page ) { - const templateId = yield findTemplate( page.path ); +export function* setPage( page, templateId ) { + const id = templateId ?? ( yield findTemplate( page.path ) ); return { type: 'SET_PAGE', page, - templateId, + templateId: id, }; } + +/** + * Displays the site homepage for editing in the editor. + */ +export function* showHomepage() { + const templateId = yield findTemplate( '/' ); + + yield setHomeTemplateId( templateId ); + + const { + show_on_front: showOnFront, + page_on_front: frontpageId, + } = yield select( 'core', 'getEntityRecord', 'root', 'site' ); + + const homePage = { + path: '/', + context: + showOnFront === 'page' + ? { + postType: 'page', + postId: frontpageId, + } + : {}, + }; + + yield setPage( homePage, templateId ); +} diff --git a/packages/edit-site/src/store/index.js b/packages/edit-site/src/store/index.js index a9f3175d57c9f..fa012273201cd 100644 --- a/packages/edit-site/src/store/index.js +++ b/packages/edit-site/src/store/index.js @@ -23,21 +23,7 @@ export default function registerEditSiteStore( initialState ) { initialState, } ); - const { showOnFront, pageOnFront } = initialState.home; - const initialPage = { - path: '/', - context: - showOnFront === 'page' - ? { - postType: 'page', - postId: pageOnFront, - } - : {}, - }; - - // Setup async data for the store. - store.dispatch( actions.setHomeTemplatePath( '/' ) ); - store.dispatch( actions.setPage( initialPage ) ); + store.dispatch( actions.showHomepage() ); return store; } diff --git a/packages/edit-site/src/store/reducer.js b/packages/edit-site/src/store/reducer.js index 37e291a7b0aec..14a33632fda85 100644 --- a/packages/edit-site/src/store/reducer.js +++ b/packages/edit-site/src/store/reducer.js @@ -165,13 +165,10 @@ export function page( state, action ) { * * @return {Object} Updated state. */ -export function home( state = {}, action ) { +export function homeTemplateId( state = {}, action ) { switch ( action.type ) { case 'SET_HOME_TEMPLATE': - return { - ...state, - templateId: action.templateId, - }; + return action.homeTemplateId; } return state; @@ -185,5 +182,5 @@ export default combineReducers( { templatePartId, templateType, page, - home, + homeTemplateId, } ); diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js index 7eb993003ed63..48e67fca292ee 100644 --- a/packages/edit-site/src/store/selectors.js +++ b/packages/edit-site/src/store/selectors.js @@ -91,7 +91,7 @@ export const getSettings = createSelector( * @return {number?} Home template ID. */ export function getHomeTemplateId( state ) { - return state.home.templateId; + return state.homeTemplateId; } /** @@ -137,25 +137,3 @@ export function getTemplateType( state ) { export function getPage( state ) { return state.page; } - -/** - * Returns the site's current `show_on_front` setting. - * - * @param {Object} state Global application state. - * - * @return {string?} The setting. - */ -export function getShowOnFront( state ) { - return state.home.showOnFront; -} - -/** - * Returns the site's current `page_on_front` setting. - * - * @param {Object} state Global application state. - * - * @return {number?} The setting. - */ -export function getPageOnFront( state ) { - return state.home.pageOnFront; -} From 6265ec3402b729778f32824dc216f0abb6f46375 Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Mon, 13 Jul 2020 14:28:30 -0700 Subject: [PATCH 45/66] Rename camelcase --- packages/edit-site/src/components/header/index.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/edit-site/src/components/header/index.js b/packages/edit-site/src/components/header/index.js index 2ab4b1d84d304..2ba155b9d6264 100644 --- a/packages/edit-site/src/components/header/index.js +++ b/packages/edit-site/src/components/header/index.js @@ -51,11 +51,7 @@ export default function Header( { getPage, } = select( 'core/edit-site' ); - // eslint-disable-next-line camelcase - const { show_on_front } = select( 'core' ).getEditedEntityRecord( - 'root', - 'site' - ); + const { getEntityRecord } = select( 'core' ); return { deviceType: __experimentalGetPreviewDeviceType(), @@ -64,7 +60,7 @@ export default function Header( { templatePartId: getTemplatePartId(), templateType: getTemplateType(), page: getPage(), - showOnFront: show_on_front, + showOnFront: getEntityRecord( 'root', 'site' ).show_on_front, }; }, [] ); From 631e81503d2c71e98ca7e6ca747a54500b512055 Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Mon, 13 Jul 2020 14:37:30 -0700 Subject: [PATCH 46/66] Remove templateId from setPage --- packages/edit-site/src/store/actions.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index 236fbb4535d09..48b06dbedc0bb 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -118,23 +118,22 @@ export function setHomeTemplateId( homeTemplateId ) { } /** - * Resolves the template for a page if no templateId is passed and sets them. + * Resolves the template for a page displays both. * * @param {Object} page The page object. * @param {string} page.type The page type. * @param {string} page.slug The page slug. * @param {string} page.path The page path. * @param {Object} page.context The page context. - * @param {number?} templateId The template ID for the page if we already know it. * * @return {Object} Action object. */ -export function* setPage( page, templateId ) { - const id = templateId ?? ( yield findTemplate( page.path ) ); +export function* setPage( page ) { + const templateId = yield findTemplate( page.path ); return { type: 'SET_PAGE', page, - templateId: id, + templateId, }; } @@ -151,7 +150,7 @@ export function* showHomepage() { page_on_front: frontpageId, } = yield select( 'core', 'getEntityRecord', 'root', 'site' ); - const homePage = { + const page = { path: '/', context: showOnFront === 'page' @@ -162,5 +161,9 @@ export function* showHomepage() { : {}, }; - yield setPage( homePage, templateId ); + return { + type: 'SET_PAGE', + templateId, + page, + }; } From 0d30ccaa1eb3e8f9a5f2baed2af66207a28977be Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Mon, 13 Jul 2020 17:30:36 -0700 Subject: [PATCH 47/66] Naive cache results of findTemplate --- packages/edit-site/src/components/header/index.js | 6 ++++-- packages/edit-site/src/store/actions.js | 6 +----- packages/edit-site/src/utils/find-template.js | 9 ++++++++- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/edit-site/src/components/header/index.js b/packages/edit-site/src/components/header/index.js index 2ba155b9d6264..79b66dd93b04c 100644 --- a/packages/edit-site/src/components/header/index.js +++ b/packages/edit-site/src/components/header/index.js @@ -51,7 +51,9 @@ export default function Header( { getPage, } = select( 'core/edit-site' ); - const { getEntityRecord } = select( 'core' ); + const { show_on_front: _showOnFront } = select( + 'core' + ).getEditedEntityRecord( 'root', 'site' ); return { deviceType: __experimentalGetPreviewDeviceType(), @@ -60,7 +62,7 @@ export default function Header( { templatePartId: getTemplatePartId(), templateType: getTemplateType(), page: getPage(), - showOnFront: getEntityRecord( 'root', 'site' ).show_on_front, + showOnFront: _showOnFront, }; }, [] ); diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index 48b06dbedc0bb..dd82f32102ba3 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -161,9 +161,5 @@ export function* showHomepage() { : {}, }; - return { - type: 'SET_PAGE', - templateId, - page, - }; + yield setPage( page ); } diff --git a/packages/edit-site/src/utils/find-template.js b/packages/edit-site/src/utils/find-template.js index 83e2d984ceb6a..b15101cd8df6c 100644 --- a/packages/edit-site/src/utils/find-template.js +++ b/packages/edit-site/src/utils/find-template.js @@ -8,6 +8,10 @@ import { addQueryArgs } from '@wordpress/url'; */ const { fetch } = window; +// Naive cache to avoid running expensive template resolution for the same path +// multiple times. +const TEMPLATE_PATH_CACHE = {}; + /** * Find the template for a given page path. * @@ -17,6 +21,9 @@ const { fetch } = window; * @return {number} The found template ID. */ export default async function findTemplate( path, getEntityRecords ) { + if ( TEMPLATE_PATH_CACHE[ path ] ) { + return TEMPLATE_PATH_CACHE[ path ]; + } const { data } = await fetch( addQueryArgs( path, { '_wp-find-template': true } ) ).then( ( res ) => res.json() ); @@ -30,6 +37,6 @@ export default async function findTemplate( path, getEntityRecords ) { } ) )[ 0 ].id; } - + TEMPLATE_PATH_CACHE[ path ] = newTemplateId; return newTemplateId; } From 3a1da28da7b27c42dfe822c47c2ef996e8b10c95 Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Mon, 13 Jul 2020 17:37:38 -0700 Subject: [PATCH 48/66] Rename cache variable --- packages/edit-site/src/utils/find-template.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/utils/find-template.js b/packages/edit-site/src/utils/find-template.js index b15101cd8df6c..9455100486c42 100644 --- a/packages/edit-site/src/utils/find-template.js +++ b/packages/edit-site/src/utils/find-template.js @@ -10,7 +10,7 @@ const { fetch } = window; // Naive cache to avoid running expensive template resolution for the same path // multiple times. -const TEMPLATE_PATH_CACHE = {}; +const TEMPLATE_ID_CACHE = {}; /** * Find the template for a given page path. @@ -21,8 +21,8 @@ const TEMPLATE_PATH_CACHE = {}; * @return {number} The found template ID. */ export default async function findTemplate( path, getEntityRecords ) { - if ( TEMPLATE_PATH_CACHE[ path ] ) { - return TEMPLATE_PATH_CACHE[ path ]; + if ( TEMPLATE_ID_CACHE[ path ] ) { + return TEMPLATE_ID_CACHE[ path ]; } const { data } = await fetch( addQueryArgs( path, { '_wp-find-template': true } ) @@ -37,6 +37,6 @@ export default async function findTemplate( path, getEntityRecords ) { } ) )[ 0 ].id; } - TEMPLATE_PATH_CACHE[ path ] = newTemplateId; + TEMPLATE_ID_CACHE[ path ] = newTemplateId; return newTemplateId; } From 7e6e1e3864aad2dcac710fdba78794dc1490bd63 Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Mon, 13 Jul 2020 17:56:55 -0700 Subject: [PATCH 49/66] Add text domain to setting translation --- lib/edit-site-page.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/edit-site-page.php b/lib/edit-site-page.php index dee3ef7cdc6ff..99dc2fc944dc7 100644 --- a/lib/edit-site-page.php +++ b/lib/edit-site-page.php @@ -226,7 +226,7 @@ function register_site_editor_homepage_settings() { 'name' => 'show_on_front', ), 'type' => 'string', - 'description' => __( 'Whether to show posts or a static page for the front page.' ), + 'description' => __( 'What to show on the front page', 'gutenberg' ), ) ); @@ -238,7 +238,7 @@ function register_site_editor_homepage_settings() { 'name' => 'page_on_front', ), 'type' => 'number', - 'description' => __( 'The page ID to show on the front page.' ), + 'description' => __( 'The ID of the page that should be displayed on the front page', 'gutenberg' ), ) ); } From f3d2b40283bc9463ce5e964bc9cc1887634dd794 Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Mon, 13 Jul 2020 18:03:52 -0700 Subject: [PATCH 50/66] Fix existing JS unit tests --- packages/edit-site/src/store/reducer.js | 2 +- packages/edit-site/src/store/test/reducer.js | 14 +------------- packages/edit-site/src/store/test/selectors.js | 8 -------- 3 files changed, 2 insertions(+), 22 deletions(-) diff --git a/packages/edit-site/src/store/reducer.js b/packages/edit-site/src/store/reducer.js index 14a33632fda85..c13d792518ddb 100644 --- a/packages/edit-site/src/store/reducer.js +++ b/packages/edit-site/src/store/reducer.js @@ -165,7 +165,7 @@ export function page( state, action ) { * * @return {Object} Updated state. */ -export function homeTemplateId( state = {}, action ) { +export function homeTemplateId( state, action ) { switch ( action.type ) { case 'SET_HOME_TEMPLATE': return action.homeTemplateId; diff --git a/packages/edit-site/src/store/test/reducer.js b/packages/edit-site/src/store/test/reducer.js index c220305c6dd70..3156db15d57db 100644 --- a/packages/edit-site/src/store/test/reducer.js +++ b/packages/edit-site/src/store/test/reducer.js @@ -14,7 +14,6 @@ import { templatePartId, templateType, page, - showOnFront, } from '../reducer'; import { PREFERENCES_DEFAULTS } from '../defaults'; @@ -165,7 +164,7 @@ describe( 'state', () => { describe( 'page()', () => { it( 'should apply default state', () => { - expect( page( undefined, {} ) ).toEqual( {} ); + expect( page( undefined, {} ) ).toEqual( undefined ); } ); it( 'should default to returning the same state', () => { @@ -183,15 +182,4 @@ describe( 'state', () => { ).toBe( newPage ); } ); } ); - - describe( 'showOnFront()', () => { - it( 'should apply default state', () => { - expect( showOnFront( undefined, {} ) ).toEqual( undefined ); - } ); - - it( 'should default to returning the same state', () => { - const state = {}; - expect( showOnFront( state, {} ) ).toBe( state ); - } ); - } ); } ); diff --git a/packages/edit-site/src/store/test/selectors.js b/packages/edit-site/src/store/test/selectors.js index f71e885b6b147..688c6b053fac5 100644 --- a/packages/edit-site/src/store/test/selectors.js +++ b/packages/edit-site/src/store/test/selectors.js @@ -10,7 +10,6 @@ import { getTemplatePartId, getTemplateType, getPage, - getShowOnFront, } from '../selectors'; describe( 'selectors', () => { @@ -142,11 +141,4 @@ describe( 'selectors', () => { expect( getPage( state ) ).toBe( state.page ); } ); } ); - - describe( 'getShowOnFront', () => { - it( 'returns the `show_on_front` setting', () => { - const state = { showOnFront: {} }; - expect( getShowOnFront( state ) ).toBe( state.showOnFront ); - } ); - } ); } ); From 821ced628cae4654f93c9415e0cd346f6261efce Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Tue, 14 Jul 2020 20:54:25 -0700 Subject: [PATCH 51/66] Fix e2e test --- .../e2e-tests/specs/experiments/template-part.test.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/e2e-tests/specs/experiments/template-part.test.js b/packages/e2e-tests/specs/experiments/template-part.test.js index 386b8941c69a0..51873eb0d4df7 100644 --- a/packages/e2e-tests/specs/experiments/template-part.test.js +++ b/packages/e2e-tests/specs/experiments/template-part.test.js @@ -42,9 +42,11 @@ describe( 'Template Part', () => { it( 'Should load customizations when in a template even if only the slug and theme attributes are set.', async () => { // Switch to editing the header template part. - await page.click( - '.components-dropdown-menu__toggle[aria-label="Switch Template"]' - ); + const openDropdownSelector = + 'button.components-dropdown-menu__toggle[aria-label="Switch Template"]'; + await page.waitForSelector( openDropdownSelector ); + await page.click( openDropdownSelector ); + const switchToHeaderTemplatePartButton = await page.waitForXPath( '//button[contains(text(), "header")]' ); From 8a80e6a410609f8c16453f83f99bd1b2cb113e4f Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 14 Aug 2020 09:23:55 -0600 Subject: [PATCH 52/66] update after merge from origin/master --- .../e2e-tests/specs/experiments/template-part.test.js | 8 +++----- packages/edit-site/src/utils/find-template.js | 9 +-------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/packages/e2e-tests/specs/experiments/template-part.test.js b/packages/e2e-tests/specs/experiments/template-part.test.js index 5385e56adc324..cb788345bea1e 100644 --- a/packages/e2e-tests/specs/experiments/template-part.test.js +++ b/packages/e2e-tests/specs/experiments/template-part.test.js @@ -43,11 +43,9 @@ describe( 'Template Part', () => { it( 'Should load customizations when in a template even if only the slug and theme attributes are set.', async () => { // Switch to editing the header template part. - const openDropdownSelector = - 'button.components-dropdown-menu__toggle[aria-label="Switch Template"]'; - await page.waitForSelector( openDropdownSelector ); - await page.click( openDropdownSelector ); - + await page.click( + '.components-dropdown-menu__toggle[aria-label="Switch Template"]' + ); const switchToHeaderTemplatePartButton = await page.waitForXPath( '//button[contains(text(), "header")]' ); diff --git a/packages/edit-site/src/utils/find-template.js b/packages/edit-site/src/utils/find-template.js index 9455100486c42..83e2d984ceb6a 100644 --- a/packages/edit-site/src/utils/find-template.js +++ b/packages/edit-site/src/utils/find-template.js @@ -8,10 +8,6 @@ import { addQueryArgs } from '@wordpress/url'; */ const { fetch } = window; -// Naive cache to avoid running expensive template resolution for the same path -// multiple times. -const TEMPLATE_ID_CACHE = {}; - /** * Find the template for a given page path. * @@ -21,9 +17,6 @@ const TEMPLATE_ID_CACHE = {}; * @return {number} The found template ID. */ export default async function findTemplate( path, getEntityRecords ) { - if ( TEMPLATE_ID_CACHE[ path ] ) { - return TEMPLATE_ID_CACHE[ path ]; - } const { data } = await fetch( addQueryArgs( path, { '_wp-find-template': true } ) ).then( ( res ) => res.json() ); @@ -37,6 +30,6 @@ export default async function findTemplate( path, getEntityRecords ) { } ) )[ 0 ].id; } - TEMPLATE_ID_CACHE[ path ] = newTemplateId; + return newTemplateId; } From a7a79b57c40cb5509beafb57f123ab56316ec704 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 14 Aug 2020 09:26:50 -0600 Subject: [PATCH 53/66] Revert whitespace change. --- packages/editor/src/store/actions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index 788309752a391..89e213f79754d 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -724,7 +724,7 @@ export function updateEditorSettings( settings ) { */ const getBlockEditorAction = ( name ) => - function*( ...args ) { + function* ( ...args ) { deprecated( "`wp.data.dispatch( 'core/editor' )." + name + '`', { alternative: "`wp.data.dispatch( 'core/block-editor' )." + name + '`', From d97d175d75b4ebfa5be6131d3023b5576e837ce1 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 14 Aug 2020 09:54:57 -0600 Subject: [PATCH 54/66] Remove unnecessary spread. --- packages/core-data/src/resolvers.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 5624717b7bf34..76b74c0fc7b1a 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -31,9 +31,7 @@ import getQueryParts from './queried-data/get-query-parts'; * Requests authors from the REST API. */ export function* getAuthors( query = {} ) { - const path = addQueryArgs( '/wp/v2/users/?who=authors&per_page=100', { - ...query, - } ); + const path = addQueryArgs( '/wp/v2/users/?who=authors&per_page=100', query ); const users = yield apiFetch( { path, From 66f023c2daba60aebd793e6de8f8eb5874f4e0cf Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 14 Aug 2020 10:02:10 -0600 Subject: [PATCH 55/66] Simplify to single useSelect. --- .../editor/src/components/post-author/index.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index 05020c3e9acec..c6c6139083363 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -17,12 +17,14 @@ import { ComboboxControl } from '@wordpress/components'; import PostAuthorCheck from './check'; function PostAuthor() { - const authors = useSelect( ( select ) => select( 'core' ).getAuthors() ); - const postAuthor = useSelect( ( select ) => - select( 'core' ).getAuthor( - select( 'core/editor' ).getEditedPostAttribute( 'author' ) - ) - ); + const { authors, postAuthor } = useSelect( ( select ) => { + const { getAuthor, getAuthors } = select( 'core' ); + const { getEditedPostAttribute } = select( 'core/editor' ); + return { + authors: getAuthors(), + postAuthor: getAuthor( getEditedPostAttribute( 'author' ) ), + }; + } ); const dispatch = useDispatch(); From 013496194f8ba99947a2e4a13a1602ad96fa49c0 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 14 Aug 2020 11:21:21 -0600 Subject: [PATCH 56/66] Fixes for js lint. --- packages/core-data/src/resolvers.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 76b74c0fc7b1a..d234b5482cb5a 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -29,9 +29,14 @@ import getQueryParts from './queried-data/get-query-parts'; /** * Requests authors from the REST API. + * + * @param {Object} query Query object. */ export function* getAuthors( query = {} ) { - const path = addQueryArgs( '/wp/v2/users/?who=authors&per_page=100', query ); + const path = addQueryArgs( + '/wp/v2/users/?who=authors&per_page=100', + query + ); const users = yield apiFetch( { path, From 25143454c4c1a6b13c507c9eb38e42af406b3b41 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 14 Aug 2020 13:24:50 -0600 Subject: [PATCH 57/66] Ensure the dropdown list is outlined when non-empty. --- packages/components/src/combobox-control/style.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/components/src/combobox-control/style.scss b/packages/components/src/combobox-control/style.scss index 4ed994bc2af73..636da65e38dc4 100644 --- a/packages/components/src/combobox-control/style.scss +++ b/packages/components/src/combobox-control/style.scss @@ -51,6 +51,10 @@ padding: 0; position: absolute; z-index: z-index(".components-popover"); + + &:not(:empty) { + border: $border-width solid $gray-900; + } } .components-combobox-control__item { From 7ff6bb6be561ad9b6969d9af81c5cabaf2b41394 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Fri, 14 Aug 2020 13:52:58 -0600 Subject: [PATCH 58/66] Restore use of compose. --- .../src/components/post-author/index.js | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index c6c6139083363..bdd9c30596641 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -7,26 +7,17 @@ import { debounce } from 'lodash'; * WordPress dependencies */ import { useState, useMemo } from '@wordpress/element'; -import { useSelect, useDispatch } from '@wordpress/data'; +import { withSelect, withDispatch, useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { ComboboxControl } from '@wordpress/components'; +import { compose, withInstanceId } from '@wordpress/compose'; /** * Internal dependencies */ import PostAuthorCheck from './check'; -function PostAuthor() { - const { authors, postAuthor } = useSelect( ( select ) => { - const { getAuthor, getAuthors } = select( 'core' ); - const { getEditedPostAttribute } = select( 'core/editor' ); - return { - authors: getAuthors(), - postAuthor: getAuthor( getEditedPostAttribute( 'author' ) ), - }; - } ); - - const dispatch = useDispatch(); +function PostAuthor( { authors, postAuthor, onUpdateAuthor } ) { const authorsForField = useMemo( () => { return authors.map( ( author ) => { @@ -59,7 +50,7 @@ function PostAuthor() { return; } setFieldValue( selectedItem.name ); - dispatch( 'core/editor' ).editPost( { author: selectedItem.key } ); + onUpdateAuthor( selectedItem.key ); }; /** @@ -131,4 +122,19 @@ function PostAuthor() { ); } -export default PostAuthor; +export default compose( [ + withSelect( ( select ) => { + const { getAuthor, getAuthors } = select( 'core' ); + const { getEditedPostAttribute } = select( 'core/editor' ); + return { + authors: getAuthors(), + postAuthor: getAuthor( getEditedPostAttribute( 'author' ) ), + }; + } ), + withDispatch( ( dispatch ) => ( { + onUpdateAuthor( author ) { + dispatch( 'core/editor' ).editPost( { author } ); + }, + } ) ), + withInstanceId, +] )( PostAuthor ); From b00e636f920f37f11e3ae2d5b00bbcb09a18cb71 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 8 Sep 2020 11:37:20 +0100 Subject: [PATCH 59/66] Avoid getAuthor and getAuthors --- .../developers/data/data-core.md | 26 --------------- .../block-library/src/post-author/edit.js | 4 +-- packages/core-data/README.md | 26 --------------- packages/core-data/src/resolvers.js | 33 ------------------- packages/core-data/src/selectors.js | 27 +-------------- .../src/components/post-author/check.js | 4 +-- .../src/components/post-author/index.js | 18 +++++----- 7 files changed, 14 insertions(+), 124 deletions(-) diff --git a/docs/designers-developers/developers/data/data-core.md b/docs/designers-developers/developers/data/data-core.md index 8b75956fcefc4..b323aeb232079 100644 --- a/docs/designers-developers/developers/data/data-core.md +++ b/docs/designers-developers/developers/data/data-core.md @@ -27,32 +27,6 @@ _Returns_ - `(boolean|undefined)`: Whether or not the user can perform the action, or `undefined` if the OPTIONS request is still being made. -# **getAuthor** - -Returns an Author by ID. - -_Parameters_ - -- _state_ `Object`: Data state. -- _authorID_ `string`: The Author ID. - -_Returns_ - -- `Array`: Authors list. - -# **getAuthors** - -Returns all available authors. - -_Parameters_ - -- _state_ `Object`: Data state. -- _query_ `string`: Query. - -_Returns_ - -- `Array`: Authors list. - # **getAutosave** Returns the autosave for the post and author. diff --git a/packages/block-library/src/post-author/edit.js b/packages/block-library/src/post-author/edit.js index b875e1499fe1c..ed6a1e889f16c 100644 --- a/packages/block-library/src/post-author/edit.js +++ b/packages/block-library/src/post-author/edit.js @@ -23,7 +23,7 @@ function PostAuthorEdit( { isSelected, context, attributes, setAttributes } ) { const { authorId, authorDetails, authors } = useSelect( ( select ) => { - const { getEditedEntityRecord, getUser, getAuthors } = select( + const { getEditedEntityRecord, getUser, getUsers } = select( 'core' ); const _authorId = getEditedEntityRecord( @@ -35,7 +35,7 @@ function PostAuthorEdit( { isSelected, context, attributes, setAttributes } ) { return { authorId: _authorId, authorDetails: _authorId ? getUser( _authorId ) : null, - authors: getAuthors(), + authors: getUsers( { who: 'authors' } ), }; }, [ postType, postId ] diff --git a/packages/core-data/README.md b/packages/core-data/README.md index bc79fd0be2924..4d8e4012ff558 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -264,32 +264,6 @@ _Returns_ - `(boolean|undefined)`: Whether or not the user can perform the action, or `undefined` if the OPTIONS request is still being made. -# **getAuthor** - -Returns an Author by ID. - -_Parameters_ - -- _state_ `Object`: Data state. -- _authorID_ `string`: The Author ID. - -_Returns_ - -- `Array`: Authors list. - -# **getAuthors** - -Returns all available authors. - -_Parameters_ - -- _state_ `Object`: Data state. -- _query_ `string`: Query. - -_Returns_ - -- `Array`: Authors list. - # **getAutosave** Returns the autosave for the post and author. diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 36ca9bb6f85de..056d2a626d551 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -13,7 +13,6 @@ import deprecated from '@wordpress/deprecated'; * Internal dependencies */ import { - receiveUserQuery, receiveCurrentTheme, receiveCurrentUser, receiveEntityRecords, @@ -25,38 +24,6 @@ import { import { getKindEntities, DEFAULT_ENTITY_KEY } from './entities'; import { apiFetch, select, resolveSelect } from './controls'; import { ifNotResolved, getNormalizedCommaSeparable } from './utils'; -import getQueryParts from './queried-data/get-query-parts'; - -/** - * Requests authors from the REST API. - * - * @param {Object} query Query object. - */ -export function* getAuthors( query = {} ) { - const path = addQueryArgs( - '/wp/v2/users/?who=authors&per_page=100', - query - ); - - const users = yield apiFetch( { - path, - } ); - const { stableKey } = getQueryParts( query ); - - yield receiveUserQuery( stableKey, users ); -} - -/** - * Request a single author from the REST API. - * - * @param {string} id The ID of the author to retrieve. - */ -export function* getAuthor( id = '' ) { - const users = yield apiFetch( { - path: `/wp/v2/users/${ id }?who=authors&per_page=1`, - } ); - yield receiveUserQuery( 'author', users ); -} /** * Requests the current user from the REST API. diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index dee84532ac4bd..d16b713ed9780 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -16,7 +16,7 @@ import deprecated from '@wordpress/deprecated'; import { REDUCER_KEY } from './name'; import { getQueriedItems } from './queried-data'; import { DEFAULT_ENTITY_KEY } from './entities'; -import getQueryParts from './queried-data/get-query-parts'; + /** * Returns true if a request is in progress for embed preview data, or false * otherwise. @@ -36,19 +36,6 @@ export const isRequestingEmbedPreview = createRegistrySelector( } ); -/** - * Returns all available authors. - * - * @param {Object} state Data state. - * @param {string} query Query. - * - * @return {Array} Authors list. - */ -export function getAuthors( state, query = {} ) { - const { stableKey } = getQueryParts( query ); - return getUserQueryResults( state, stableKey ); -} - /** * Returns the current user. * @@ -77,18 +64,6 @@ export const getUserQueryResults = createSelector( ( state, queryID ) => [ state.users.queries[ queryID ], state.users.byId ] ); -/** - * Returns an Author by ID. - * - * @param {Object} state Data state. - * @param {string} authorID The Author ID. - * - * @return {Array} Authors list. - */ -export function getAuthor( state, authorID ) { - return state.users.byId[ authorID ]; -} - /** * Returns whether the entities for the give kind are loaded. * diff --git a/packages/editor/src/components/post-author/check.js b/packages/editor/src/components/post-author/check.js index 45475476545a0..8ee69ff4826c9 100644 --- a/packages/editor/src/components/post-author/check.js +++ b/packages/editor/src/components/post-author/check.js @@ -19,7 +19,7 @@ export function PostAuthorCheck( { authors, children, } ) { - if ( ! hasAssignAuthorAction || authors.length < 2 ) { + if ( ! hasAssignAuthorAction || ! authors || authors.length < 2 ) { return null; } @@ -40,7 +40,7 @@ export default compose( [ false ), postType: select( 'core/editor' ).getCurrentPostType(), - authors: select( 'core' ).getAuthors(), + authors: select( 'core' ).getUsers( { who: 'authors' } ), }; } ), withInstanceId, diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index bdd9c30596641..2fce5ff435516 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -18,7 +18,6 @@ import { compose, withInstanceId } from '@wordpress/compose'; import PostAuthorCheck from './check'; function PostAuthor( { authors, postAuthor, onUpdateAuthor } ) { - const authorsForField = useMemo( () => { return authors.map( ( author ) => { return { @@ -43,7 +42,8 @@ function PostAuthor( { authors, postAuthor, onUpdateAuthor } ) { /** * Handle author selection. * - * @param {Object} selectedItem The selected Author. + * @param {Object} value The selected Author. + * @param {Object} value.selectedItem The selected Author. */ const handleSelect = ( { selectedItem } ) => { if ( ! selectedItem ) { @@ -70,7 +70,7 @@ function PostAuthor( { authors, postAuthor, onUpdateAuthor } ) { fieldValue === postAuthor?.name ) { return select( 'core' ) - .getAuthors() + .getUsers( { who: 'authors' } ) .map( ( author ) => ( { key: author.id, name: author.name, @@ -78,7 +78,7 @@ function PostAuthor( { authors, postAuthor, onUpdateAuthor } ) { } return select( 'core' ) - .getAuthors( { search: fieldValue } ) + .getUsers( { who: 'authors', search: fieldValue } ) .map( ( author ) => ( { key: author.id, name: author.name, @@ -89,8 +89,8 @@ function PostAuthor( { authors, postAuthor, onUpdateAuthor } ) { const isLoading = useSelect( ( select ) => { - return select( 'core/data' ).isResolving( 'core', 'getAuthors', [ - { search: fieldValue }, + return select( 'core/data' ).isResolving( 'core', 'getUsers', [ + { search: fieldValue, who: 'authors' }, ] ); }, [ availableAuthors, fieldValue ] @@ -124,11 +124,11 @@ function PostAuthor( { authors, postAuthor, onUpdateAuthor } ) { export default compose( [ withSelect( ( select ) => { - const { getAuthor, getAuthors } = select( 'core' ); + const { getUser, getUsers } = select( 'core' ); const { getEditedPostAttribute } = select( 'core/editor' ); return { - authors: getAuthors(), - postAuthor: getAuthor( getEditedPostAttribute( 'author' ) ), + authors: getUsers( { who: 'authors' } ), + postAuthor: getUser( getEditedPostAttribute( 'author' ) ), }; } ), withDispatch( ( dispatch ) => ( { From fb528ff6139a3d30930aa812b4d881e90b9f4b67 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 8 Sep 2020 11:42:53 +0100 Subject: [PATCH 60/66] deprecate getAuthors --- .../developers/data/data-core.md | 12 ++++++++++++ packages/core-data/README.md | 12 ++++++++++++ packages/core-data/src/resolvers.js | 11 +++++++++++ packages/core-data/src/selectors.js | 14 ++++++++++++++ 4 files changed, 49 insertions(+) diff --git a/docs/designers-developers/developers/data/data-core.md b/docs/designers-developers/developers/data/data-core.md index b323aeb232079..6484e914f2eef 100644 --- a/docs/designers-developers/developers/data/data-core.md +++ b/docs/designers-developers/developers/data/data-core.md @@ -27,6 +27,18 @@ _Returns_ - `(boolean|undefined)`: Whether or not the user can perform the action, or `undefined` if the OPTIONS request is still being made. +# **getAuthors** + +Returns all available authors. + +_Parameters_ + +- _state_ `Object`: Data state. + +_Returns_ + +- `Array`: Authors list. + # **getAutosave** Returns the autosave for the post and author. diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 4d8e4012ff558..fdb7e87043ac2 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -264,6 +264,18 @@ _Returns_ - `(boolean|undefined)`: Whether or not the user can perform the action, or `undefined` if the OPTIONS request is still being made. +# **getAuthors** + +Returns all available authors. + +_Parameters_ + +- _state_ `Object`: Data state. + +_Returns_ + +- `Array`: Authors list. + # **getAutosave** Returns the autosave for the post and author. diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 056d2a626d551..2f477bcb72182 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -13,6 +13,7 @@ import deprecated from '@wordpress/deprecated'; * Internal dependencies */ import { + receiveUserQuery, receiveCurrentTheme, receiveCurrentUser, receiveEntityRecords, @@ -25,6 +26,16 @@ import { getKindEntities, DEFAULT_ENTITY_KEY } from './entities'; import { apiFetch, select, resolveSelect } from './controls'; import { ifNotResolved, getNormalizedCommaSeparable } from './utils'; +/** + * Requests authors from the REST API. + */ +export function* getAuthors() { + const users = yield apiFetch( { + path: '/wp/v2/users/?who=authors&per_page=-1', + } ); + yield receiveUserQuery( 'authors', users ); +} + /** * Requests the current user from the REST API. */ diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index d16b713ed9780..cd56f12bfc052 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -36,6 +36,20 @@ export const isRequestingEmbedPreview = createRegistrySelector( } ); +/** + * Returns all available authors. + * + * @param {Object} state Data state. + * + * @return {Array} Authors list. + */ +export function getAuthors( state ) { + deprecated( "select( 'core' ).getAuthors()", { + alternative: "select( 'core' ).getUsers({ who: 'authors' })", + } ); + return getUserQueryResults( state, 'authors' ); +} + /** * Returns the current user. * From 41e87ae7584034cdd4dc72317efa5ff1b154d801 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 8 Sep 2020 12:04:57 +0100 Subject: [PATCH 61/66] Small refactoring --- .../src/components/post-author/index.js | 134 +++++++----------- 1 file changed, 55 insertions(+), 79 deletions(-) diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index 2fce5ff435516..e882e7dac70c0 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -6,39 +6,68 @@ import { debounce } from 'lodash'; /** * WordPress dependencies */ -import { useState, useMemo } from '@wordpress/element'; -import { withSelect, withDispatch, useSelect } from '@wordpress/data'; +import { useState, useMemo, useEffect } from '@wordpress/element'; +import { useSelect, useDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { ComboboxControl } from '@wordpress/components'; -import { compose, withInstanceId } from '@wordpress/compose'; /** * Internal dependencies */ import PostAuthorCheck from './check'; -function PostAuthor( { authors, postAuthor, onUpdateAuthor } ) { - const authorsForField = useMemo( () => { - return authors.map( ( author ) => { +function PostAuthor() { + const [ fieldValue, setFieldValue ] = useState(); + + const { isLoading, authors, postAuthor } = useSelect( + ( select ) => { + const { getUser, getUsers, isResolving } = select( 'core' ); + const { getEditedPostAttribute } = select( 'core/editor' ); + const author = getUser( getEditedPostAttribute( 'author' ) ); + const query = + ! fieldValue || '' === fieldValue || fieldValue === author?.name + ? {} + : { search: fieldValue }; + return { + postAuthor: author, + authors: getUsers( { who: 'authors', ...query } ), + isLoading: isResolving( 'core', 'getUsers', [ + { search: fieldValue, who: 'authors' }, + ] ), + }; + }, + [ fieldValue ] + ); + const { editPost } = useDispatch( 'core/editor' ); + + const authorOptions = useMemo( () => { + const fetchedAuthors = ( authors ?? [] ).map( ( author ) => { return { key: author.id, name: author.name, }; } ); - }, [ authors ] ); - // Ensure the current author is included in the initial dropdown list. - let foundAuthor = authorsForField.findIndex( - ( author ) => postAuthor?.id === author.key - ); - // The currently field value. - const [ fieldValue, setFieldValue ] = useState( postAuthor?.name ); + // Ensure the current author is included in the dropdown list. + const foundAuthor = fetchedAuthors.findIndex( + ( { key } ) => postAuthor?.id === key + ); + if ( foundAuthor < 0 && postAuthor ) { + return [ + { key: postAuthor.id, name: postAuthor.name }, + ...fetchedAuthors, + ]; + } + + return fetchedAuthors; + }, [ authors, postAuthor ] ); + + // Initializes the post author properly + // Also ensures external changes are reflected. + useEffect( () => { + setFieldValue( postAuthor.name ); + }, [ postAuthor ] ); - if ( authors?.length > 0 && foundAuthor < 0 && postAuthor ) { - postAuthor.key = authorsForField.length; - authors.unshift( postAuthor ); - foundAuthor = 0; - } /** * Handle author selection. * @@ -50,7 +79,7 @@ function PostAuthor( { authors, postAuthor, onUpdateAuthor } ) { return; } setFieldValue( selectedItem.name ); - onUpdateAuthor( selectedItem.key ); + editPost( { author: selectedItem.key } ); }; /** @@ -62,79 +91,26 @@ function PostAuthor( { authors, postAuthor, onUpdateAuthor } ) { setFieldValue( inputValue ); }; - const availableAuthors = useSelect( - ( select ) => { - if ( - ! fieldValue || - '' === fieldValue || - fieldValue === postAuthor?.name - ) { - return select( 'core' ) - .getUsers( { who: 'authors' } ) - .map( ( author ) => ( { - key: author.id, - name: author.name, - } ) ); - } - - return select( 'core' ) - .getUsers( { who: 'authors', search: fieldValue } ) - .map( ( author ) => ( { - key: author.id, - name: author.name, - } ) ); - }, - [ fieldValue, postAuthor, isLoading ] - ); - - const isLoading = useSelect( - ( select ) => { - return select( 'core/data' ).isResolving( 'core', 'getUsers', [ - { search: fieldValue, who: 'authors' }, - ] ); - }, - [ availableAuthors, fieldValue ] - ); - if ( ! postAuthor ) { return null; } - const selectId = 'post-author-selector'; - - const postAuthorEntry = { - key: postAuthor.id, - name: postAuthor.name, - }; - return ( - ); } -export default compose( [ - withSelect( ( select ) => { - const { getUser, getUsers } = select( 'core' ); - const { getEditedPostAttribute } = select( 'core/editor' ); - return { - authors: getUsers( { who: 'authors' } ), - postAuthor: getUser( getEditedPostAttribute( 'author' ) ), - }; - } ), - withDispatch( ( dispatch ) => ( { - onUpdateAuthor( author ) { - dispatch( 'core/editor' ).editPost( { author } ); - }, - } ) ), - withInstanceId, -] )( PostAuthor ); +export default PostAuthor; From 2383f1cf583b7c8028fea7891681d0e1f6b239ef Mon Sep 17 00:00:00 2001 From: jasmussen Date: Wed, 9 Sep 2020 11:45:18 +0200 Subject: [PATCH 62/66] Polish. --- .../components/src/combobox-control/index.js | 15 ++++-- .../src/combobox-control/style.scss | 54 +++++++++---------- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js index 122e2cff4504e..c279785a9cdf8 100644 --- a/packages/components/src/combobox-control/index.js +++ b/packages/components/src/combobox-control/index.js @@ -5,10 +5,15 @@ import { useCombobox } from 'downshift'; import classnames from 'classnames'; import { isEqual } from 'lodash'; +/** + * WordPress dependencies + */ +import { check, chevronDown } from '@wordpress/icons'; + /** * Internal dependencies */ -import { Button, Dashicon, Spinner } from '../'; +import { Button, Icon, Spinner } from '../'; const itemToString = ( item ) => item && item.name; export default function ComboboxControl( { @@ -90,9 +95,9 @@ export default function ComboboxControl( { className: 'components-combobox-control__button-button', } ) } > -
@@ -116,9 +121,9 @@ export default function ComboboxControl( { } ) } > { isEqual( item, selectedItem ) && ( - ) } { item.name } diff --git a/packages/components/src/combobox-control/style.scss b/packages/components/src/combobox-control/style.scss index 636da65e38dc4..a109efd8d7092 100644 --- a/packages/components/src/combobox-control/style.scss +++ b/packages/components/src/combobox-control/style.scss @@ -1,48 +1,46 @@ .components-combobox-control { - color: $dark-gray-500; position: relative; + margin-bottom: $grid-unit-15; } .components-combobox-control__label { display: block; - margin-bottom: 5px; + margin-bottom: $grid-unit-05; } .components-combobox-control__button { - border: 1px solid $dark-gray-200; - border-radius: 4px; - color: $dark-gray-500; display: inline-block; - min-height: 30px; - min-width: 130px; + min-height: $button-size-small; + min-width: 140px; position: relative; text-align: left; - &:focus { - border-color: var(--wp-admin-theme-color); - } - - &-input { - border: none; - height: calc(100% - 2px); - left: 1px; - padding: 0 4px; + .components-combobox-control__button-input { + height: 100%; + width: 100%; + left: 0; + top: 0; position: absolute; - top: 1px; - width: calc(100% - 2px); - } + margin: 0; - &-button:hover { - box-shadow: none !important; + @include input-control; } - &-icon { + .components-combobox-control__button-icon { height: 100%; - padding: 0 4px; + padding: 0; position: absolute; right: 0; top: 0; } + + .components-combobox-control__button-button { + height: $button-size-small + $border-width + $border-width; + + &:focus:not(:disabled) { + box-shadow: none; + } + } } .components-combobox-control__menu { @@ -53,6 +51,8 @@ z-index: z-index(".components-popover"); &:not(:empty) { + margin: $grid-unit-15 0 0 0; + border-radius: $radius-block-ui; border: $border-width solid $gray-900; } } @@ -61,14 +61,14 @@ align-items: center; display: flex; list-style-type: none; - padding: 10px 5px 10px 25px; + padding: $grid-unit-10 $grid-unit-15 $grid-unit-10 ($button-size-small + $grid-unit-15); &.is-highlighted { background: $gray-200; } - &-icon { - margin-left: -20px; - margin-right: 0; + .components-combobox-control__item-icon { + margin-left: -$button-size-small - $grid-unit-05; + margin-right: $grid-unit-05; } } From 9428906e7776446483d8e229887d904d921ee930 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 9 Sep 2020 22:42:55 -0600 Subject: [PATCH 63/66] Onle set field value once postAuthor is available. --- packages/editor/src/components/post-author/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index e882e7dac70c0..d46f6e900f357 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -65,7 +65,9 @@ function PostAuthor() { // Initializes the post author properly // Also ensures external changes are reflected. useEffect( () => { - setFieldValue( postAuthor.name ); + if ( postAuthor ) { + setFieldValue( postAuthor.name ); + } }, [ postAuthor ] ); /** From 3c47fa850c0ef6c6473c564a1b841d26dc9dc0ac Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 9 Sep 2020 22:42:55 -0600 Subject: [PATCH 64/66] Only set field value once postAuthor is available. --- packages/editor/src/components/post-author/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index e882e7dac70c0..d46f6e900f357 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -65,7 +65,9 @@ function PostAuthor() { // Initializes the post author properly // Also ensures external changes are reflected. useEffect( () => { - setFieldValue( postAuthor.name ); + if ( postAuthor ) { + setFieldValue( postAuthor.name ); + } }, [ postAuthor ] ); /** From d61111c1b6feb6cd7e9d83971db57a1aab745e7d Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Mon, 14 Sep 2020 09:55:18 +0100 Subject: [PATCH 65/66] Remove useless test --- .../src/components/post-author/test/index.js | 64 ------------------- 1 file changed, 64 deletions(-) delete mode 100644 packages/editor/src/components/post-author/test/index.js diff --git a/packages/editor/src/components/post-author/test/index.js b/packages/editor/src/components/post-author/test/index.js deleted file mode 100644 index 368be4fda7d26..0000000000000 --- a/packages/editor/src/components/post-author/test/index.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * External dependencies - */ -import { shallow } from 'enzyme'; - -/** - * Internal dependencies - */ -import { PostAuthor } from '../'; - -describe( 'PostAuthor', () => { - const authors = [ - { - id: 1, - name: 'admin', - capabilities: { - level_1: true, - }, - }, - { - id: 2, - name: 'subscriber', - capabilities: { - level_0: true, - }, - }, - { - id: 3, - name: 'andrew', - capabilities: { - level_1: true, - }, - }, - ]; - - const user = { - data: { - capabilities: { - publish_posts: true, - }, - }, - }; - - describe( '#render()', () => { - it( 'should update author', () => { - const onUpdateAuthor = jest.fn(); - const wrapper = shallow( - - ); - - wrapper.find( 'select' ).simulate( 'change', { - target: { - value: '3', - }, - } ); - - expect( onUpdateAuthor ).toHaveBeenCalledWith( 3 ); - } ); - } ); -} ); From 0fa42d566399e474aa27cf0658a732e573604777 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Mon, 28 Sep 2020 11:09:27 +0100 Subject: [PATCH 66/66] Use the new combobox control --- .../components/src/combobox-control/index.js | 28 ++++----------- .../src/combobox-control/stories/index.js | 2 +- .../src/combobox-control/style.scss | 6 +++- .../src/components/post-author/index.js | 36 ++++++++----------- 4 files changed, 28 insertions(+), 44 deletions(-) diff --git a/packages/components/src/combobox-control/index.js b/packages/components/src/combobox-control/index.js index e3ee035f86fdf..fcc8d332e41bd 100644 --- a/packages/components/src/combobox-control/index.js +++ b/packages/components/src/combobox-control/index.js @@ -19,7 +19,7 @@ function ComboboxControl( { label, options, onChange, - onInputChange: onInputChangeProp = () => {}, + onFilterValueChange, hideLabelFromVision, help, messages = { @@ -31,11 +31,10 @@ function ComboboxControl( { const [ isExpanded, setIsExpanded ] = useState( false ); const [ inputValue, setInputValue ] = useState( '' ); const inputContainer = useRef(); + const currentOption = options.find( ( option ) => option.value === value ); + const currentLabel = currentOption?.label ?? ''; const matchingSuggestions = useMemo( () => { - if ( ! inputValue || inputValue.length === 0 ) { - return options.filter( ( option ) => option.value !== value ); - } const startsWithMatch = []; const containsMatch = []; const match = inputValue.toLocaleLowerCase(); @@ -55,7 +54,7 @@ function ComboboxControl( { onChange( newSelectedSuggestion.value ); speak( messages.selected, 'assertive' ); setSelectedSuggestion( newSelectedSuggestion ); - setInputValue( selectedSuggestion.label ); + setInputValue( '' ); setIsExpanded( false ); }; @@ -109,33 +108,20 @@ function ComboboxControl( { // TODO: TokenInput should preferably forward ref inputContainer.current.input.focus(); setIsExpanded( true ); + onFilterValueChange( '' ); }; const onBlur = () => { - const currentOption = options.find( - ( option ) => option.value === value - ); - setInputValue( currentOption?.label ?? '' ); setIsExpanded( false ); }; const onInputChange = ( event ) => { const text = event.value; setInputValue( text ); - onInputChangeProp( text ); + onFilterValueChange( text ); setIsExpanded( true ); }; - // Reset the value on change - useEffect( () => { - if ( matchingSuggestions.indexOf( selectedSuggestion ) === -1 ) { - setSelectedSuggestion( null ); - } - if ( ! inputValue || matchingSuggestions.length === 0 ) { - onChange( null ); - } - }, [ matchingSuggestions, inputValue, value ] ); - // Announcements useEffect( () => { const hasMatchingSuggestions = matchingSuggestions.length > 0; @@ -179,7 +165,7 @@ function ComboboxControl( { className="components-combobox-control__input" instanceId={ instanceId } ref={ inputContainer } - value={ inputValue } + value={ isExpanded ? inputValue : currentLabel } onBlur={ onBlur } isExpanded={ isExpanded } selectedSuggestionIndex={ matchingSuggestions.indexOf( diff --git a/packages/components/src/combobox-control/stories/index.js b/packages/components/src/combobox-control/stories/index.js index dbe474fb2b6d0..a7f250e38573e 100644 --- a/packages/components/src/combobox-control/stories/index.js +++ b/packages/components/src/combobox-control/stories/index.js @@ -276,7 +276,7 @@ function ComboboxControlWithState() { onChange={ setValue } label="Select a country" options={ filteredOptions } - onInputChange={ ( filter ) => + onFilterValueChange={ ( filter ) => setFilteredOptions( countries .filter( ( country ) => diff --git a/packages/components/src/combobox-control/style.scss b/packages/components/src/combobox-control/style.scss index 7015bca4e3a09..2dbfcb3b70c35 100644 --- a/packages/components/src/combobox-control/style.scss +++ b/packages/components/src/combobox-control/style.scss @@ -2,10 +2,14 @@ width: 100%; } -.components-combobox-control__input { +input.components-combobox-control__input[type="text"] { width: 100%; border: none; box-shadow: none; + padding: 2px; + margin: 0; + line-height: inherit; + min-height: auto; &:focus { outline: none; diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index d46f6e900f357..d97a6223fd232 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -19,16 +19,15 @@ import PostAuthorCheck from './check'; function PostAuthor() { const [ fieldValue, setFieldValue ] = useState(); - const { isLoading, authors, postAuthor } = useSelect( + const { authorId, isLoading, authors, postAuthor } = useSelect( ( select ) => { const { getUser, getUsers, isResolving } = select( 'core' ); const { getEditedPostAttribute } = select( 'core/editor' ); const author = getUser( getEditedPostAttribute( 'author' ) ); const query = - ! fieldValue || '' === fieldValue || fieldValue === author?.name - ? {} - : { search: fieldValue }; + ! fieldValue || '' === fieldValue ? {} : { search: fieldValue }; return { + authorId: getEditedPostAttribute( 'author' ), postAuthor: author, authors: getUsers( { who: 'authors', ...query } ), isLoading: isResolving( 'core', 'getUsers', [ @@ -43,18 +42,19 @@ function PostAuthor() { const authorOptions = useMemo( () => { const fetchedAuthors = ( authors ?? [] ).map( ( author ) => { return { - key: author.id, - name: author.name, + value: author.id, + label: author.name, }; } ); // Ensure the current author is included in the dropdown list. const foundAuthor = fetchedAuthors.findIndex( - ( { key } ) => postAuthor?.id === key + ( { value } ) => postAuthor?.id === value ); + if ( foundAuthor < 0 && postAuthor ) { return [ - { key: postAuthor.id, name: postAuthor.name }, + { value: postAuthor.id, label: postAuthor.name }, ...fetchedAuthors, ]; } @@ -73,15 +73,13 @@ function PostAuthor() { /** * Handle author selection. * - * @param {Object} value The selected Author. - * @param {Object} value.selectedItem The selected Author. + * @param {number} postAuthorId The selected Author. */ - const handleSelect = ( { selectedItem } ) => { - if ( ! selectedItem ) { + const handleSelect = ( postAuthorId ) => { + if ( ! postAuthorId ) { return; } - setFieldValue( selectedItem.name ); - editPost( { author: selectedItem.key } ); + editPost( { author: postAuthorId } ); }; /** @@ -89,7 +87,7 @@ function PostAuthor() { * * @param {string} inputValue The current value of the input field. */ - const handleKeydown = ( { inputValue } ) => { + const handleKeydown = ( inputValue ) => { setFieldValue( inputValue ); }; @@ -102,13 +100,9 @@ function PostAuthor() {