Instantly share code, notes, and snippets.
Last active
February 13, 2023 14:03
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save landbryo/01a9eaea330e030d5904553b15ac0263 to your computer and use it in GitHub Desktop.
Add additional authors UI.
This file contains hidden or 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
/** | |
* WordPress dependencies | |
*/ | |
import { PluginPostStatusInfo } from '@wordpress/edit-post'; | |
import { useEffect, useMemo, useState } from '@wordpress/element'; | |
import { useDispatch, useSelect } from '@wordpress/data'; | |
import { __ } from '@wordpress/i18n'; | |
import { SelectControl } from '@wordpress/components'; | |
import { decodeEntities } from '@wordpress/html-entities'; | |
import { store as coreStore } from '@wordpress/core-data'; | |
const PostAddAuthor = () => { | |
const [ inputList, setInputList ] = useState( [] ); | |
const { editPost } = useDispatch( 'core/editor' ); | |
// Get author ids from meta. | |
let authorIds = useSelect( ( select ) => { | |
const { getEditedPostAttribute } = select( 'core/editor' ); | |
return getEditedPostAttribute( 'meta' ).forage_authors || []; | |
}, [] ); | |
// Get array of user objects. | |
const authors = useSelect( ( select ) => { | |
const AUTHORS_QUERY = { | |
who: 'authors', | |
per_page: 100, | |
_fields: 'id,name', | |
context: 'view', | |
}; | |
const { getUsers } = select( coreStore ); | |
const query = { ...AUTHORS_QUERY }; | |
return getUsers( query ); | |
}, [] ); | |
/** | |
* Handle author selection. | |
* | |
* @param {number} authorId The selected Author. | |
* @param {number} index The author ID index for the previous value. | |
*/ | |
const onChangeAuthor = ( authorId, index ) => { | |
if ( ! authorId ) { | |
return; | |
} | |
const ids = authorIds; | |
// Make sure the authorId is a number. | |
authorId = Number( authorId ); | |
// Don't add duplicate authors. | |
if ( ids.includes( authorId ) ) { | |
onAddAuthor(); | |
return; | |
} | |
ids[ Number( index ) ] = authorId; | |
editPost( { | |
meta: { | |
forage_authors: ids, | |
forage_authors_updated: Math.floor( Date.now() / 1000 ), | |
}, | |
} ); | |
authorIds = ids; | |
}; | |
/** | |
* Handle removing the additionally added author. | |
* | |
* @param {number} authorId The selected Author. | |
* @param {number} index The author ID index for the previous value. | |
*/ | |
const removeAuthor = ( authorId, index ) => { | |
const ids = authorIds.filter( | |
( item, itemIndex ) => item !== authorId && index !== itemIndex | |
); | |
editPost( { | |
meta: { | |
forage_authors: ids, | |
forage_authors_updated: Math.floor( Date.now() / 1000 ), | |
}, | |
} ); | |
authorIds = ids; | |
}; | |
/** | |
* Handle adding another author selector. | |
*/ | |
const onAddAuthor = () => { | |
setInputList( | |
inputList.concat( | |
<AddAuthor | |
key={ inputList.length } | |
index={ inputList.length } | |
options={ authorOptions } | |
onChangeAuthor={ onChangeAuthor } | |
removeAuthor={ removeAuthor } | |
/> | |
) | |
); | |
}; | |
/** | |
* Populate author options from fetched authors. | |
* | |
* @type {*[]} | |
*/ | |
const authorOptions = useMemo( () => { | |
const fetchedAuthors = [ | |
{ | |
value: 0, | |
label: __( 'Select', 'forage-core' ), | |
}, | |
]; | |
( authors ?? [] ).forEach( ( author ) => { | |
if ( author ) { | |
fetchedAuthors.push( { | |
value: author.id, | |
label: decodeEntities( author.name ), | |
} ); | |
} | |
} ); | |
return fetchedAuthors; | |
}, [ authors ] ); | |
/** | |
* Add existing authors to input list. | |
*/ | |
useEffect( () => { | |
const inputs = []; | |
authorIds.forEach( ( authorId, index ) => { | |
inputs.push( | |
<AddAuthor | |
key={ index } | |
index={ index } | |
authorId={ authorId } | |
options={ authorOptions } | |
onChangeAuthor={ onChangeAuthor } | |
removeAuthor={ removeAuthor } | |
/> | |
); | |
} ); | |
setInputList( inputs ); | |
}, [ authors, authorIds ] ); | |
return ( | |
<PluginPostStatusInfo className="forage-additional"> | |
<button className="forage-additional__add" onClick={ onAddAuthor }> | |
{ __( 'Add Author', 'forage-core' ) } + | |
</button> | |
{ inputList } | |
</PluginPostStatusInfo> | |
); | |
}; | |
const AddAuthor = ( { | |
index, | |
authorId, | |
options, | |
onChangeAuthor, | |
removeAuthor, | |
} ) => { | |
return ( | |
<div className="forage-additional__author"> | |
<SelectControl | |
label={ __( 'Additional Author', 'forage-core' ) } | |
options={ options } | |
value={ authorId } | |
onChange={ ( newId ) => { | |
onChangeAuthor( newId, index ); | |
} } | |
/> | |
<button | |
className="clear-button" | |
onClick={ () => { | |
removeAuthor( authorId, index ); | |
} } | |
> | |
× | |
</button> | |
</div> | |
); | |
}; | |
export default PostAddAuthor; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment