-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use standard select element for small number of authors. (#26426)
* Use standard select element for small number of authors. * Restore changed file. * restore changed file * Rename post-author to post-author-combobox. * Reintroduce HTML select based post author selector. * Introduce top level PostAuthor displays PostAuthorSelect or PostAuthorCombobox. * Reduce post author check query size. * Restore file from master. * Refactor PostAuthorSelect as functional component. * Restore packages/editor/src/components/post-author/check.js from master. * Small tweaks Co-authored-by: Riad Benguella <[email protected]>
- Loading branch information
1 parent
5f61405
commit 8be8de1
Showing
3 changed files
with
162 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { debounce } from 'lodash'; | ||
|
||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useState, useMemo, useEffect } from '@wordpress/element'; | ||
import { useSelect, useDispatch } from '@wordpress/data'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { ComboboxControl } from '@wordpress/components'; | ||
|
||
function PostAuthorCombobox() { | ||
const [ fieldValue, setFieldValue ] = useState(); | ||
|
||
const { authorId, isLoading, authors, postAuthor } = useSelect( | ||
( select ) => { | ||
const { __unstableGetAuthor, getAuthors, isResolving } = select( | ||
'core' | ||
); | ||
const { getEditedPostAttribute } = select( 'core/editor' ); | ||
const author = __unstableGetAuthor( | ||
getEditedPostAttribute( 'author' ) | ||
); | ||
const query = | ||
! fieldValue || '' === fieldValue ? {} : { search: fieldValue }; | ||
return { | ||
authorId: getEditedPostAttribute( 'author' ), | ||
postAuthor: author, | ||
authors: getAuthors( query ), | ||
isLoading: isResolving( 'core', 'getAuthors', [ query ] ), | ||
}; | ||
}, | ||
[ fieldValue ] | ||
); | ||
const { editPost } = useDispatch( 'core/editor' ); | ||
|
||
const authorOptions = useMemo( () => { | ||
const fetchedAuthors = ( authors ?? [] ).map( ( author ) => { | ||
return { | ||
value: author.id, | ||
label: author.name, | ||
}; | ||
} ); | ||
|
||
// Ensure the current author is included in the dropdown list. | ||
const foundAuthor = fetchedAuthors.findIndex( | ||
( { value } ) => postAuthor?.id === value | ||
); | ||
|
||
if ( foundAuthor < 0 && postAuthor ) { | ||
return [ | ||
{ value: postAuthor.id, label: postAuthor.name }, | ||
...fetchedAuthors, | ||
]; | ||
} | ||
|
||
return fetchedAuthors; | ||
}, [ authors, postAuthor ] ); | ||
|
||
// Initializes the post author properly | ||
// Also ensures external changes are reflected. | ||
useEffect( () => { | ||
if ( postAuthor ) { | ||
setFieldValue( postAuthor.name ); | ||
} | ||
}, [ postAuthor ] ); | ||
|
||
/** | ||
* Handle author selection. | ||
* | ||
* @param {number} postAuthorId The selected Author. | ||
*/ | ||
const handleSelect = ( postAuthorId ) => { | ||
if ( ! postAuthorId ) { | ||
return; | ||
} | ||
editPost( { author: postAuthorId } ); | ||
}; | ||
|
||
/** | ||
* Handle user input. | ||
* | ||
* @param {string} inputValue The current value of the input field. | ||
*/ | ||
const handleKeydown = ( inputValue ) => { | ||
setFieldValue( inputValue ); | ||
}; | ||
|
||
if ( ! postAuthor ) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<ComboboxControl | ||
label={ __( 'Author' ) } | ||
options={ authorOptions } | ||
value={ authorId } | ||
onFilterValueChange={ debounce( handleKeydown, 300 ) } | ||
onChange={ handleSelect } | ||
isLoading={ isLoading } | ||
allowReset={ false } | ||
/> | ||
); | ||
} | ||
|
||
export default PostAuthorCombobox; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,115 +1,29 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { debounce } from 'lodash'; | ||
|
||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useState, useMemo, useEffect } from '@wordpress/element'; | ||
import { useSelect, useDispatch } from '@wordpress/data'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { ComboboxControl } from '@wordpress/components'; | ||
import { useSelect } from '@wordpress/data'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import PostAuthorCheck from './check'; | ||
import PostAuthorCombobox from './combobox'; | ||
import PostAuthorSelect from './select'; | ||
|
||
function PostAuthor() { | ||
const [ fieldValue, setFieldValue ] = useState(); | ||
const minimumUsersForCombobox = 25; | ||
|
||
const { authorId, isLoading, authors, postAuthor } = useSelect( | ||
( select ) => { | ||
const { __unstableGetAuthor, getAuthors, isResolving } = select( | ||
'core' | ||
); | ||
const { getEditedPostAttribute } = select( 'core/editor' ); | ||
const author = __unstableGetAuthor( | ||
getEditedPostAttribute( 'author' ) | ||
); | ||
const query = | ||
! fieldValue || '' === fieldValue ? {} : { search: fieldValue }; | ||
return { | ||
authorId: getEditedPostAttribute( 'author' ), | ||
postAuthor: author, | ||
authors: getAuthors( query ), | ||
isLoading: isResolving( 'core', 'getAuthors', [ query ] ), | ||
}; | ||
}, | ||
[ fieldValue ] | ||
); | ||
const { editPost } = useDispatch( 'core/editor' ); | ||
|
||
const authorOptions = useMemo( () => { | ||
const fetchedAuthors = ( authors ?? [] ).map( ( author ) => { | ||
return { | ||
value: author.id, | ||
label: author.name, | ||
}; | ||
function PostAuthor() { | ||
const showCombobox = useSelect( ( select ) => { | ||
const authors = select( 'core' ).getUsers( { | ||
who: 'authors', | ||
per_page: minimumUsersForCombobox + 1, | ||
} ); | ||
return authors?.length >= minimumUsersForCombobox; | ||
}, [] ); | ||
|
||
// Ensure the current author is included in the dropdown list. | ||
const foundAuthor = fetchedAuthors.findIndex( | ||
( { value } ) => postAuthor?.id === value | ||
); | ||
|
||
if ( foundAuthor < 0 && postAuthor ) { | ||
return [ | ||
{ value: postAuthor.id, label: postAuthor.name }, | ||
...fetchedAuthors, | ||
]; | ||
} | ||
|
||
return fetchedAuthors; | ||
}, [ authors, postAuthor ] ); | ||
|
||
// Initializes the post author properly | ||
// Also ensures external changes are reflected. | ||
useEffect( () => { | ||
if ( postAuthor ) { | ||
setFieldValue( postAuthor.name ); | ||
} | ||
}, [ postAuthor ] ); | ||
|
||
/** | ||
* Handle author selection. | ||
* | ||
* @param {number} postAuthorId The selected Author. | ||
*/ | ||
const handleSelect = ( postAuthorId ) => { | ||
if ( ! postAuthorId ) { | ||
return; | ||
} | ||
editPost( { author: postAuthorId } ); | ||
}; | ||
|
||
/** | ||
* Handle user input. | ||
* | ||
* @param {string} inputValue The current value of the input field. | ||
*/ | ||
const handleKeydown = ( inputValue ) => { | ||
setFieldValue( inputValue ); | ||
}; | ||
|
||
if ( ! postAuthor ) { | ||
return null; | ||
if ( showCombobox ) { | ||
return <PostAuthorCombobox />; | ||
} | ||
|
||
return ( | ||
<PostAuthorCheck> | ||
<ComboboxControl | ||
label={ __( 'Author' ) } | ||
options={ authorOptions } | ||
value={ authorId } | ||
onFilterValueChange={ debounce( handleKeydown, 300 ) } | ||
onChange={ handleSelect } | ||
isLoading={ isLoading } | ||
allowReset={ false } | ||
/> | ||
</PostAuthorCheck> | ||
); | ||
return <PostAuthorSelect />; | ||
} | ||
|
||
export default PostAuthor; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { __ } from '@wordpress/i18n'; | ||
import { useSelect, useDispatch } from '@wordpress/data'; | ||
import { decodeEntities } from '@wordpress/html-entities'; | ||
import { SelectControl } from '@wordpress/components'; | ||
|
||
function PostAuthorSelect() { | ||
const { editPost } = useDispatch( 'core/editor' ); | ||
const { postAuthor, authors } = useSelect( ( select ) => { | ||
const authorsFromAPI = select( 'core' ).getAuthors(); | ||
return { | ||
postAuthor: select( 'core/editor' ).getEditedPostAttribute( | ||
'author' | ||
), | ||
authors: authorsFromAPI.map( ( author ) => ( { | ||
label: decodeEntities( author.name ), | ||
value: author.id, | ||
} ) ), | ||
}; | ||
}, [] ); | ||
|
||
const setAuthorId = ( value ) => { | ||
const author = Number( value ); | ||
editPost( { author } ); | ||
}; | ||
|
||
return ( | ||
<SelectControl | ||
className="post-author-selector" | ||
label={ __( 'Author' ) } | ||
options={ authors } | ||
onChange={ setAuthorId } | ||
value={ postAuthor } | ||
/> | ||
); | ||
} | ||
|
||
export default PostAuthorSelect; |