From ec9bb047507d75055301b40b0c101f780dbac288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Tue, 12 Nov 2024 17:17:58 +0100 Subject: [PATCH] Extract author to fields package --- package-lock.json | 2 + .../src/components/post-fields/index.js | 64 ++----------------- packages/fields/README.md | 4 ++ packages/fields/package.json | 1 + .../fields/src/fields/author/author-view.tsx | 63 ++++++++++++++++++ packages/fields/src/fields/author/index.tsx | 32 ++++++++++ packages/fields/src/fields/index.ts | 1 + packages/fields/src/types.ts | 10 +++ 8 files changed, 117 insertions(+), 60 deletions(-) create mode 100644 packages/fields/src/fields/author/author-view.tsx create mode 100644 packages/fields/src/fields/author/index.tsx diff --git a/package-lock.json b/package-lock.json index 27f01fd681824..a4c740c9c1c99 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21155,6 +21155,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -54701,6 +54702,7 @@ "@wordpress/warning": "*", "change-case": "4.1.2", "client-zip": "^2.4.5", + "clsx": "2.1.1", "remove-accents": "^0.5.0" }, "engines": { diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index e151c5a048c01..2fa95f8cf2db8 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -1,8 +1,3 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - /** * WordPress dependencies */ @@ -16,50 +11,10 @@ import { commentStatusField, titleField, dateField, + authorField, } from '@wordpress/fields'; -import { useMemo, useState } from '@wordpress/element'; -import { commentAuthorAvatar as authorIcon } from '@wordpress/icons'; -import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; -import { useSelect } from '@wordpress/data'; -import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; - -function PostAuthorField( { item } ) { - const { text, imageUrl } = useSelect( - ( select ) => { - const { getUser } = select( coreStore ); - const user = getUser( item.author ); - return { - imageUrl: user?.avatar_urls?.[ 48 ], - text: user?.name, - }; - }, - [ item ] - ); - const [ isImageLoaded, setIsImageLoaded ] = useState( false ); - return ( - - { !! imageUrl && ( -
- setIsImageLoaded( true ) } - alt={ __( 'Author avatar' ) } - src={ imageUrl } - /> -
- ) } - { ! imageUrl && ( -
- -
- ) } - { text } -
- ); -} +import { useMemo } from '@wordpress/element'; +import { useEntityRecords } from '@wordpress/core-data'; function usePostFields() { const { records: authors, isResolving: isLoadingAuthors } = @@ -70,23 +25,12 @@ function usePostFields() { featuredImageField, titleField, { - label: __( 'Author' ), - id: 'author', - type: 'integer', + ...authorField, elements: authors?.map( ( { id, name } ) => ( { value: id, label: name, } ) ) || [], - render: PostAuthorField, - sort: ( a, b, direction ) => { - const nameA = a._embedded?.author?.[ 0 ]?.name || ''; - const nameB = b._embedded?.author?.[ 0 ]?.name || ''; - - return direction === 'asc' - ? nameA.localeCompare( nameB ) - : nameB.localeCompare( nameA ); - }, }, statusField, dateField, diff --git a/packages/fields/README.md b/packages/fields/README.md index bfcc63be4da47..e6cf6d3007ed9 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -14,6 +14,10 @@ npm install @wordpress/fields --save +### authorField + +Author field for BasePost. + ### commentStatusField Comment status field for BasePost. diff --git a/packages/fields/package.json b/packages/fields/package.json index f32c779c2e989..cee1060223767 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -57,6 +57,7 @@ "@wordpress/warning": "*", "change-case": "4.1.2", "client-zip": "^2.4.5", + "clsx": "2.1.1", "remove-accents": "^0.5.0" }, "peerDependencies": { diff --git a/packages/fields/src/fields/author/author-view.tsx b/packages/fields/src/fields/author/author-view.tsx new file mode 100644 index 0000000000000..51e0a1ca59b75 --- /dev/null +++ b/packages/fields/src/fields/author/author-view.tsx @@ -0,0 +1,63 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { useState } from '@wordpress/element'; +import { commentAuthorAvatar as authorIcon } from '@wordpress/icons'; +import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import type { User } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; + +function AuthorView( { item }: { item: BasePost } ) { + const { text, imageUrl } = useSelect( + ( select ) => { + const { getEntityRecord } = select( coreStore ); + let user: User | undefined; + if ( !! item.author ) { + user = getEntityRecord( 'root', 'user', item.author ); + } + return { + imageUrl: user?.avatar_urls?.[ 48 ], + text: user?.name, + }; + }, + [ item ] + ); + const [ isImageLoaded, setIsImageLoaded ] = useState( false ); + return ( + + { !! imageUrl && ( +
+ setIsImageLoaded( true ) } + alt={ __( 'Author avatar' ) } + src={ imageUrl } + /> +
+ ) } + { ! imageUrl && ( +
+ +
+ ) } + { text } +
+ ); +} + +export default AuthorView; diff --git a/packages/fields/src/fields/author/index.tsx b/packages/fields/src/fields/author/index.tsx new file mode 100644 index 0000000000000..6e5a43d44426d --- /dev/null +++ b/packages/fields/src/fields/author/index.tsx @@ -0,0 +1,32 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import AuthorView from './author-view'; + +const authorField: Field< BasePost > = { + label: __( 'Author' ), + id: 'author', + type: 'integer', + elements: [], + render: AuthorView, + sort: ( a, b, direction ) => { + const nameA = a._embedded?.author?.[ 0 ]?.name || ''; + const nameB = b._embedded?.author?.[ 0 ]?.name || ''; + + return direction === 'asc' + ? nameA.localeCompare( nameB ) + : nameB.localeCompare( nameA ); + }, +}; + +/** + * Author field for BasePost. + */ +export default authorField; diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts index 36e064006232b..5ea4235af1d96 100644 --- a/packages/fields/src/fields/index.ts +++ b/packages/fields/src/fields/index.ts @@ -7,3 +7,4 @@ export { default as passwordField } from './password'; export { default as statusField } from './status'; export { default as commentStatusField } from './comment-status'; export { default as dateField } from './date'; +export { default as authorField } from './author'; diff --git a/packages/fields/src/types.ts b/packages/fields/src/types.ts index 71831b6aab180..be0391c7c865b 100644 --- a/packages/fields/src/types.ts +++ b/packages/fields/src/types.ts @@ -23,6 +23,14 @@ interface Links { [ key: string ]: { href: string }[] | undefined; } +interface Author { + name: string; +} + +interface Embedded { + author?: Author[]; +} + export interface BasePost extends CommonPost { comment_status?: 'open' | 'closed'; excerpt?: string | { raw: string; rendered: string }; @@ -39,6 +47,8 @@ export interface BasePost extends CommonPost { permalink_template?: string; date?: string; modified?: string; + author?: number; + _embedded?: Embedded; } export interface Template extends CommonPost {