From 54ee86217509d2b6439f7d1d36090d8f6232187e Mon Sep 17 00:00:00 2001 From: Mehmood Ahmad <31419912+mehmoodak@users.noreply.github.com> Date: Fri, 17 Jan 2025 02:22:13 +0500 Subject: [PATCH] Reader: Add utils for user profile (#98346) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Lookup user id if username is in route * 💫 UPDATE: reader author avatar links to use user profiles if flag is enabled * 🔨 REFACTOR: migrate PostTrackback to functional component with TS support * Revert "Lookup user id if username is in route" This reverts commit ac9f207ce385fd74b8551a051fe523fd12979f28. * ➕ ADDS: getUserProfileUrl util function * ➕ ADDS: isUserProfileEnabled util function * ➕ ADDS: getUserProfileBasePath util function --------- Co-authored-by: DustyReagan --- client/blocks/comments/post-comment.jsx | 8 ++++-- client/blocks/comments/post-trackback.tsx | 9 ++++--- client/blocks/reader-author-link/index.tsx | 9 ++++--- client/blocks/reader-avatar/index.tsx | 8 +++--- client/reader/index.js | 12 ++++++--- .../components/user-profile-header/index.tsx | 11 ++++---- client/reader/user-stream/controller.tsx | 5 ++-- client/reader/user-stream/index.tsx | 7 ++--- .../reader/user-stream/user-profile.utils.ts | 26 +++++++++++++++++++ 9 files changed, 70 insertions(+), 25 deletions(-) create mode 100644 client/reader/user-stream/user-profile.utils.ts diff --git a/client/blocks/comments/post-comment.jsx b/client/blocks/comments/post-comment.jsx index d291605708f1b..008596919800a 100644 --- a/client/blocks/comments/post-comment.jsx +++ b/client/blocks/comments/post-comment.jsx @@ -17,6 +17,10 @@ import isReaderTagEmbedPage from 'calypso/lib/reader/is-reader-tag-embed-page'; import withDimensions from 'calypso/lib/with-dimensions'; import { getStreamUrl } from 'calypso/reader/route'; import { recordAction, recordGaEvent, recordPermalinkClick } from 'calypso/reader/stats'; +import { + getUserProfileUrl, + isUserProfileEnabled, +} from 'calypso/reader/user-stream/user-profile.utils'; import { expandComments } from 'calypso/state/comments/actions'; import { PLACEHOLDER_STATE, POST_COMMENT_DISPLAY_TYPES } from 'calypso/state/comments/constants'; import { getCurrentUser, isUserLoggedIn } from 'calypso/state/current-user/selectors'; @@ -313,8 +317,8 @@ class PostComment extends PureComponent { const commentAuthorName = decodeEntities( commentAuthor.name ); let commentAuthorUrl; - if ( config.isEnabled( 'reader/user-profile' ) && commentAuthor.ID ) { - commentAuthorUrl = `/read/users/${ commentAuthor.ID }`; + if ( isUserProfileEnabled() && commentAuthor.ID ) { + commentAuthorUrl = getUserProfileUrl( commentAuthor.ID ); } else if ( commentAuthor.site_ID ) { commentAuthorUrl = getStreamUrl( null, commentAuthor.site_ID ); } else { diff --git a/client/blocks/comments/post-trackback.tsx b/client/blocks/comments/post-trackback.tsx index adabead92f046..8656eaa3d8316 100644 --- a/client/blocks/comments/post-trackback.tsx +++ b/client/blocks/comments/post-trackback.tsx @@ -1,7 +1,10 @@ -import config from '@automattic/calypso-config'; import { Gridicon } from '@automattic/components'; import { get } from 'lodash'; import TimeSince from 'calypso/components/time-since'; +import { + getUserProfileUrl, + isUserProfileEnabled, +} from 'calypso/reader/user-stream/user-profile.utils'; import './post-comment.scss'; // yes, this is intentional. they share styles. @@ -35,8 +38,8 @@ export default function PostTrackback( props: PostTrackbackProps ): JSX.Element const unescapedAuthorName = unescape( get( comment, 'author.name', '' ) ); const authorUrlLink = - config.isEnabled( 'reader/user-profile' ) && comment.author?.ID - ? `/read/users/${ comment.author.ID }` + isUserProfileEnabled() && comment.author?.ID + ? getUserProfileUrl( comment.author.ID ) : comment.author?.URL; return ( diff --git a/client/blocks/reader-author-link/index.tsx b/client/blocks/reader-author-link/index.tsx index 40114bcb52650..563c0e740da73 100644 --- a/client/blocks/reader-author-link/index.tsx +++ b/client/blocks/reader-author-link/index.tsx @@ -1,8 +1,11 @@ -import config from '@automattic/calypso-config'; import clsx from 'clsx'; import React from 'react'; import { isAuthorNameBlocked } from 'calypso/reader/lib/author-name-blocklist'; import * as stats from 'calypso/reader/stats'; +import { + getUserProfileUrl, + isUserProfileEnabled, +} from 'calypso/reader/user-stream/user-profile.utils'; import './style.scss'; @@ -38,8 +41,8 @@ export default function ReaderAuthorLink( props: ReaderAuthorLinkProps ) { }; const authorLinkUrl = - config.isEnabled( 'reader/user-profile' ) && author.ID - ? `/read/users/${ author.ID }` + isUserProfileEnabled() && author.ID + ? getUserProfileUrl( author.ID ) : props.siteUrl ?? author.URL; const authorName = author.name; diff --git a/client/blocks/reader-avatar/index.tsx b/client/blocks/reader-avatar/index.tsx index d10a309b32342..6a20d7a02aa66 100644 --- a/client/blocks/reader-avatar/index.tsx +++ b/client/blocks/reader-avatar/index.tsx @@ -1,9 +1,12 @@ -import config from '@automattic/calypso-config'; import { safeImageUrl } from '@automattic/calypso-url'; import { Gridicon } from '@automattic/components'; import clsx from 'clsx'; import SiteIcon from 'calypso/blocks/site-icon'; import Gravatar from 'calypso/components/gravatar'; +import { + getUserProfileUrl, + isUserProfileEnabled, +} from 'calypso/reader/user-stream/user-profile.utils'; import './style.scss'; @@ -117,8 +120,7 @@ export default function ReaderAvatar( { const siteIconElement = hasSiteIcon && ( ); - const avatarUrl = - config.isEnabled( 'reader/user-profile' ) && author?.ID ? `/read/users/${ author.ID }` : null; + const avatarUrl = isUserProfileEnabled() && author?.ID ? getUserProfileUrl( author.ID ) : null; const authorAvatar = ( hasAvatar || showPlaceholder ) && ( ); diff --git a/client/reader/index.js b/client/reader/index.js index 06f197ebcbf8b..69ac43b7ab641 100644 --- a/client/reader/index.js +++ b/client/reader/index.js @@ -8,6 +8,10 @@ import { render as clientRender, setSelectedSiteIdByOrigin, } from 'calypso/controller'; +import { + getUserProfileBasePath, + isUserProfileEnabled, +} from 'calypso/reader/user-stream/user-profile.utils'; import { blogListing, feedDiscovery, @@ -96,10 +100,10 @@ export default async function () { clientRender ); - // User stream - if ( config.isEnabled( 'reader/user-profile' ) ) { + // User profile + if ( isUserProfileEnabled() ) { page( - '/read/users/:user_id', + getUserProfileBasePath(), blogDiscoveryByFeedId, redirectLoggedOutToSignup, updateLastRoute, @@ -109,7 +113,7 @@ export default async function () { clientRender ); page( - '/read/users/:user_id/lists', + getUserProfileBasePath( 'lists' ), blogDiscoveryByFeedId, redirectLoggedOutToSignup, updateLastRoute, diff --git a/client/reader/user-stream/components/user-profile-header/index.tsx b/client/reader/user-stream/components/user-profile-header/index.tsx index 1e604ef15e133..3d7f52a731376 100644 --- a/client/reader/user-stream/components/user-profile-header/index.tsx +++ b/client/reader/user-stream/components/user-profile-header/index.tsx @@ -5,6 +5,7 @@ import SectionNav from 'calypso/components/section-nav'; import NavItem from 'calypso/components/section-nav/item'; import NavTabs from 'calypso/components/section-nav/tabs'; import { UserData } from 'calypso/lib/user/user'; +import { getUserProfileUrl } from 'calypso/reader/user-stream/user-profile.utils'; import './style.scss'; @@ -16,17 +17,17 @@ const UserProfileHeader = ( { user }: UserProfileHeaderProps ): JSX.Element => { const translate = useTranslate(); const currentPath = page.current; const userId = user.ID; - + const userProfileUrl = getUserProfileUrl( Number( userId ) ); const navigationItems = [ { label: translate( 'Posts' ), - path: `/read/users/${ userId }`, - selected: currentPath === `/read/users/${ userId }`, + path: userProfileUrl, + selected: currentPath === userProfileUrl, }, { label: translate( 'Lists' ), - path: `/read/users/${ userId }/lists`, - selected: currentPath === `/read/users/${ userId }/lists`, + path: `${ userProfileUrl }/lists`, + selected: currentPath === `${ userProfileUrl }/lists`, }, ]; diff --git a/client/reader/user-stream/controller.tsx b/client/reader/user-stream/controller.tsx index cf05b2959eac8..dbffef0e328b4 100644 --- a/client/reader/user-stream/controller.tsx +++ b/client/reader/user-stream/controller.tsx @@ -1,6 +1,7 @@ import { ReactElement } from 'react'; import AsyncLoad from 'calypso/components/async-load'; import { trackPageLoad, trackScrollPage } from 'calypso/reader/controller-helper'; +import { getUserProfileBasePath } from 'calypso/reader/user-stream/user-profile.utils'; import type { AppState } from 'calypso/types'; interface Context { @@ -17,7 +18,7 @@ const analyticsPageTitle = 'Reader'; export function userPosts( context: Context, next: () => void ): void { const userId = context.params.user_id; - const basePath = '/read/users/:user_id'; + const basePath = getUserProfileBasePath(); const fullAnalyticsPageTitle = analyticsPageTitle + ' > User > ' + userId + ' > Posts'; const mcKey = 'user_posts'; const streamKey = 'user:' + userId; @@ -45,7 +46,7 @@ export function userPosts( context: Context, next: () => void ): void { export function userLists( context: Context, next: () => void ): void { const userId = context.params.user_id; - const basePath = '/read/users/:user_id/lists'; + const basePath = getUserProfileBasePath( 'lists' ); const fullAnalyticsPageTitle = analyticsPageTitle + ' > User > ' + userId + ' > Lists'; const mcKey = 'user_lists'; diff --git a/client/reader/user-stream/index.tsx b/client/reader/user-stream/index.tsx index b9cbaaa8848c6..dcb0eb285f03f 100644 --- a/client/reader/user-stream/index.tsx +++ b/client/reader/user-stream/index.tsx @@ -4,11 +4,11 @@ import { useEffect } from 'react'; import { connect } from 'react-redux'; import EmptyContent from 'calypso/components/empty-content'; import { UserData } from 'calypso/lib/user/user'; +import { getUserProfileUrl } from 'calypso/reader/user-stream/user-profile.utils'; import UserLists from 'calypso/reader/user-stream/views/lists'; import UserPosts from 'calypso/reader/user-stream/views/posts'; import { requestUser } from 'calypso/state/reader/users/actions'; import './style.scss'; - interface UserStreamProps { streamKey?: string; userId: string; @@ -51,13 +51,14 @@ export function UserStream( { userId, requestUser, user, streamKey, isLoading }: } const currentPath = page.current; + const userProfileUrl = getUserProfileUrl( Number( userId ) ); const renderContent = (): React.ReactNode => { const basePath = currentPath.split( '?' )[ 0 ]; switch ( basePath ) { - case `/read/users/${ userId }`: + case userProfileUrl: return ; - case `/read/users/${ userId }/lists`: + case `${ userProfileUrl }/lists`: return ; default: return null; diff --git a/client/reader/user-stream/user-profile.utils.ts b/client/reader/user-stream/user-profile.utils.ts new file mode 100644 index 0000000000000..0b3431654a3db --- /dev/null +++ b/client/reader/user-stream/user-profile.utils.ts @@ -0,0 +1,26 @@ +import config from '@automattic/calypso-config'; + +/** + * Return `true` if the user profile feature is enabled. + */ +export function isUserProfileEnabled(): boolean { + return config.isEnabled( 'reader/user-profile' ); +} + +/** + * Return the URL of the user profile page for a given user ID. + * + * Example: `/read/users/123` + */ +export function getUserProfileUrl( userId: number ): string { + return `/read/users/${ userId }`; +} + +type UserProfileSubPage = '' | 'lists'; + +/** + * Return the base path of the user profile page. + */ +export function getUserProfileBasePath( subPage: UserProfileSubPage = '' ): string { + return subPage ? `/read/users/:user_id/${ subPage }` : `/read/users/:user_id`; +}