From 8204ca8bef804f6d40ea2dee79543ee5459f6beb Mon Sep 17 00:00:00 2001 From: Delilah <23665803+goplayoutside3@users.noreply.github.com> Date: Tue, 4 Jun 2024 21:12:55 -0500 Subject: [PATCH 1/7] build avatar and profile banner into Dashboard --- .../src/components/HomePageContainer.js | 3 +- .../src/components/UserHome/UserHome.js | 20 +++++++++ .../components/Dashboard/Dashboard.js | 44 +++++++++++++++++++ .../components/Dashboard/Dashboard.stories.js | 21 +++++++++ .../Dashboard/DashboardContainer.js | 35 +++++++++++++++ .../lib-user/src/components/UserHome/index.js | 1 + packages/lib-user/src/index.js | 1 + 7 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 packages/lib-user/src/components/UserHome/UserHome.js create mode 100644 packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js create mode 100644 packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.stories.js create mode 100644 packages/lib-user/src/components/UserHome/components/Dashboard/DashboardContainer.js create mode 100644 packages/lib-user/src/components/UserHome/index.js diff --git a/packages/app-root/src/components/HomePageContainer.js b/packages/app-root/src/components/HomePageContainer.js index 5a79fc719c..eacb99cf2b 100644 --- a/packages/app-root/src/components/HomePageContainer.js +++ b/packages/app-root/src/components/HomePageContainer.js @@ -5,6 +5,7 @@ import { Box } from 'grommet' import { PanoptesAuthContext } from '../contexts' import { CommunityContainer, DefaultHome } from '@zooniverse/content' import { Loader } from '@zooniverse/react-components' +import { UserHome } from '@zooniverse/user' export default function HomePageContainer({ dailyZooPosts = [], @@ -20,7 +21,7 @@ export default function HomePageContainer({ ) : ( - {user?.login ?

Signed-in

: } + {user?.login ? : }
)} + + + ) +} + +export default UserHome + +UserHome.propTypes = { + authUser: shape({ + id: string + }) +} diff --git a/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js b/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js new file mode 100644 index 0000000000..a3b363f5a8 --- /dev/null +++ b/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js @@ -0,0 +1,44 @@ +import { Box, Image } from 'grommet' +import styled from 'styled-components' +import { shape, string } from 'prop-types' + +const Relative = styled(Box)` + position: relative; +` + +const StyledAvatar = styled(Image)` + width: 128px; + height: 128px; + object-fit: cover; + border-radius: 50%; + border: solid white 5px; + position: absolute; + top: 206px; +` + +export default function Dashboard({ authUser, profileBannerSrc = '' }) { + return ( + + + + ) +} + +Dashboard.propTypes = { + authUser: shape({ + id: string + }), + profileBannerSrc: string +} diff --git a/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.stories.js b/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.stories.js new file mode 100644 index 0000000000..5088c1acc0 --- /dev/null +++ b/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.stories.js @@ -0,0 +1,21 @@ +import { GROUP_ADMIN_USER, USER } from '../../../../../test/mocks/panoptes/users.js' +import Dashboard from './Dashboard.js' + +export default { + title: 'Components / UserHome / Dashboard', + component: Dashboard +} + +export const Default = { + args: { + authUser: USER, + profileBannerSrc: 'https://panoptes-uploads.zooniverse.org/user_profile_header/9da9fd16-46c1-4d84-a272-83ac19fb32c3.jpeg' + } +} + +export const NoAvatarOrBanner = { + args: { + authUser: GROUP_ADMIN_USER, + profileBannerSrc: '' + } +} diff --git a/packages/lib-user/src/components/UserHome/components/Dashboard/DashboardContainer.js b/packages/lib-user/src/components/UserHome/components/Dashboard/DashboardContainer.js new file mode 100644 index 0000000000..617506a822 --- /dev/null +++ b/packages/lib-user/src/components/UserHome/components/Dashboard/DashboardContainer.js @@ -0,0 +1,35 @@ +import { panoptes } from '@zooniverse/panoptes-js' +import auth from 'panoptes-client/lib/auth' +import useSWR from 'swr' + +import Dashboard from './Dashboard' + +const fetchProfileBanner = async ({ authUser }) => { + const token = await auth.checkBearerToken() + const authorization = `Bearer ${token}` + const query = { include: 'profile_header', user_id: authUser.id } + + try { + const { body } = await panoptes.get('/users', query, { authorization }) + const profileBannerSrc = body.linked.profile_headers[0].src + return profileBannerSrc + } catch (error) { + console.error(error) + return null + } +} + +const SWROptions = { + revalidateIfStale: true, + revalidateOnMount: true, + revalidateOnFocus: true, + revalidateOnReconnect: true, + refreshInterval: 0 +} + +export default function DashboardContainer({ authUser }) { + const key = { authUser } + const { data: profileBannerSrc } = useSWR(key, fetchProfileBanner, SWROptions) + + return +} diff --git a/packages/lib-user/src/components/UserHome/index.js b/packages/lib-user/src/components/UserHome/index.js new file mode 100644 index 0000000000..03fdd51fa5 --- /dev/null +++ b/packages/lib-user/src/components/UserHome/index.js @@ -0,0 +1 @@ +export { default } from './UserHome.js' diff --git a/packages/lib-user/src/index.js b/packages/lib-user/src/index.js index f66e4601da..64c7ffb24f 100644 --- a/packages/lib-user/src/index.js +++ b/packages/lib-user/src/index.js @@ -2,6 +2,7 @@ export { default as UserStats } from './components/UserStats' export { default as MyGroups } from './components/MyGroups' export { default as GroupStats } from './components/GroupStats' +export { default as UserHome } from './components/UserHome' // components/shared export { default as Avatar } from './components/shared/Avatar' From 0065641cb113a72dc5aed15de9a0847f41a67161 Mon Sep 17 00:00:00 2001 From: Delilah <23665803+goplayoutside3@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:12:42 -0500 Subject: [PATCH 2/7] fix UserHome import --- packages/app-root/src/components/HomePageContainer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/app-root/src/components/HomePageContainer.js b/packages/app-root/src/components/HomePageContainer.js index b008c3f422..8725a3bf2a 100644 --- a/packages/app-root/src/components/HomePageContainer.js +++ b/packages/app-root/src/components/HomePageContainer.js @@ -6,7 +6,6 @@ import { PanoptesAuthContext } from '../contexts' import { CommunityContainer, DefaultHome } from '@zooniverse/content' import { UserHome } from '@zooniverse/user' import { Loader } from '@zooniverse/react-components' -import { UserHome } from '@zooniverse/user' export default function HomePageContainer({ dailyZooPosts = [], From 7b355e89c7b379f567a9e1976a55e71d5bde4347 Mon Sep 17 00:00:00 2001 From: Delilah <23665803+goplayoutside3@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:22:55 -0500 Subject: [PATCH 3/7] add round to top of Dashboard --- .../src/components/UserHome/components/Dashboard/Dashboard.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js b/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js index a3b363f5a8..f7cd046b26 100644 --- a/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js +++ b/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js @@ -23,6 +23,7 @@ export default function Dashboard({ authUser, profileBannerSrc = '' }) { align='center' height={{ min: '270px', max: '270px' }} background={{ image: `url(${profileBannerSrc})`, color: 'neutral-1' }} + round={{ size: '16px', corner: 'top' }} > Date: Thu, 6 Jun 2024 15:30:15 -0500 Subject: [PATCH 4/7] add responsive styling to avatar --- .../components/Dashboard/Dashboard.js | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js b/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js index f7cd046b26..d08e8c6b5d 100644 --- a/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js +++ b/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js @@ -1,6 +1,7 @@ -import { Box, Image } from 'grommet' +import { Box, Image, ResponsiveContext } from 'grommet' import styled from 'styled-components' import { shape, string } from 'prop-types' +import { useContext } from 'react' const Relative = styled(Box)` position: relative; @@ -11,19 +12,32 @@ const StyledAvatar = styled(Image)` height: 128px; object-fit: cover; border-radius: 50%; - border: solid white 5px; + border: solid white 6px; position: absolute; - top: 206px; + top: 203px; + + // For Grommet breakpoint small + @media (width < 769px) { + width: 80px; + height: 80px; + top: 137px; + } ` export default function Dashboard({ authUser, profileBannerSrc = '' }) { + const size = useContext(ResponsiveContext) + return ( Date: Thu, 6 Jun 2024 20:58:30 -0500 Subject: [PATCH 5/7] fetch user resource via panoptes in DashboardContainer --- .../components/Dashboard/Dashboard.js | 26 ++++++++++------- .../components/Dashboard/Dashboard.stories.js | 25 ++++++++++++---- .../Dashboard/DashboardContainer.js | 29 +++++++++++-------- 3 files changed, 53 insertions(+), 27 deletions(-) diff --git a/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js b/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js index d08e8c6b5d..df1c3316a9 100644 --- a/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js +++ b/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.js @@ -1,6 +1,6 @@ import { Box, Image, ResponsiveContext } from 'grommet' import styled from 'styled-components' -import { shape, string } from 'prop-types' +import { bool, shape, string } from 'prop-types' import { useContext } from 'react' const Relative = styled(Box)` @@ -24,7 +24,7 @@ const StyledAvatar = styled(Image)` } ` -export default function Dashboard({ authUser, profileBannerSrc = '' }) { +export default function Dashboard({ isLoading = false, user }) { const size = useContext(ResponsiveContext) return ( @@ -36,15 +36,19 @@ export default function Dashboard({ authUser, profileBannerSrc = '' }) { ? { min: '270px', max: '270px' } : { min: '180px', max: '180px' } } - background={{ image: `url(${profileBannerSrc})`, color: 'neutral-1' }} + background={ + isLoading || !user?.profile_header + ? 'brand' + : { image: `url(${user.profile_header})` } + } round={size !== 'small' ? { size: '16px', corner: 'top' } : false} > @@ -52,8 +56,10 @@ export default function Dashboard({ authUser, profileBannerSrc = '' }) { } Dashboard.propTypes = { - authUser: shape({ - id: string - }), - profileBannerSrc: string + isLoading: bool, + user: shape({ + avatar_src: string, + id: string.isRequired, + profile_header: string + }) } diff --git a/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.stories.js b/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.stories.js index 5088c1acc0..0ec141f612 100644 --- a/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.stories.js +++ b/packages/lib-user/src/components/UserHome/components/Dashboard/Dashboard.stories.js @@ -1,4 +1,3 @@ -import { GROUP_ADMIN_USER, USER } from '../../../../../test/mocks/panoptes/users.js' import Dashboard from './Dashboard.js' export default { @@ -6,16 +5,32 @@ export default { component: Dashboard } +const USER = { + admin: false, + avatar_src: 'https://panoptes-uploads-staging.zooniverse.org/user_avatar/e638f5a3-7ffb-4d23-bb08-f296377a2e74.jpeg', + display_name: 'Test User 1', + id: '12345', + login: 'TestUser', + profile_header: 'https://panoptes-uploads.zooniverse.org/user_profile_header/9da9fd16-46c1-4d84-a272-83ac19fb32c3.jpeg' +} + +const USER_NO_IMAGES = { + admin: false, + avatar_src: '', + display_name: 'Zootester 123', + id: '847637', + login: 'zootester123', + profile_header: '' +} + export const Default = { args: { - authUser: USER, - profileBannerSrc: 'https://panoptes-uploads.zooniverse.org/user_profile_header/9da9fd16-46c1-4d84-a272-83ac19fb32c3.jpeg' + user: USER } } export const NoAvatarOrBanner = { args: { - authUser: GROUP_ADMIN_USER, - profileBannerSrc: '' + user: USER_NO_IMAGES } } diff --git a/packages/lib-user/src/components/UserHome/components/Dashboard/DashboardContainer.js b/packages/lib-user/src/components/UserHome/components/Dashboard/DashboardContainer.js index 617506a822..4ca53b6746 100644 --- a/packages/lib-user/src/components/UserHome/components/Dashboard/DashboardContainer.js +++ b/packages/lib-user/src/components/UserHome/components/Dashboard/DashboardContainer.js @@ -4,6 +4,15 @@ import useSWR from 'swr' import Dashboard from './Dashboard' +const SWROptions = { + revalidateIfStale: true, + revalidateOnMount: true, + revalidateOnFocus: true, + revalidateOnReconnect: true, + refreshInterval: 0 +} + +/* This is a similar pattern to usePanoptesUser hook, but includes the profile_header */ const fetchProfileBanner = async ({ authUser }) => { const token = await auth.checkBearerToken() const authorization = `Bearer ${token}` @@ -11,25 +20,21 @@ const fetchProfileBanner = async ({ authUser }) => { try { const { body } = await panoptes.get('/users', query, { authorization }) - const profileBannerSrc = body.linked.profile_headers[0].src - return profileBannerSrc + const user = body.users?.[0] + + if (body.linked?.profile_headers?.length) { + user.profile_header = body.linked.profile_headers[0].src + } + return user } catch (error) { console.error(error) return null } } -const SWROptions = { - revalidateIfStale: true, - revalidateOnMount: true, - revalidateOnFocus: true, - revalidateOnReconnect: true, - refreshInterval: 0 -} - export default function DashboardContainer({ authUser }) { const key = { authUser } - const { data: profileBannerSrc } = useSWR(key, fetchProfileBanner, SWROptions) + const { data: user, isLoading } = useSWR(key, fetchProfileBanner, SWROptions) - return + return } From 0685e44ab10c85a54463bdbe5f3a0a75412d7fe1 Mon Sep 17 00:00:00 2001 From: Delilah <23665803+goplayoutside3@users.noreply.github.com> Date: Thu, 6 Jun 2024 21:07:33 -0500 Subject: [PATCH 6/7] import UserHome into lib-user dev App --- packages/lib-user/dev/components/App/App.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/lib-user/dev/components/App/App.js b/packages/lib-user/dev/components/App/App.js index e6be895c39..374a164169 100644 --- a/packages/lib-user/dev/components/App/App.js +++ b/packages/lib-user/dev/components/App/App.js @@ -9,6 +9,7 @@ import { Contributors, GroupStats, MyGroups, + UserHome, UserStats } from '@components' @@ -31,7 +32,7 @@ function App({ useEffect(() => { async function checkUserSession() { setLoading(true) - + try { const user = await auth.checkCurrent() setUser(user) @@ -41,7 +42,7 @@ function App({ setLoading(false) } } - + auth.listen('change', checkUserSession) return function () { @@ -93,13 +94,14 @@ function App({ + {user?.id ? : null} ) if (groups) { const subpaths = groups.split('/') const groupId = subpaths[0] || '' - + if (subpaths[0] === '[user_group_id]') { content =

In the url query param ?groups=, please replace [user_group_id] with a user group id.

} else if (subpaths[1] === 'contributors') { @@ -185,7 +187,7 @@ function App({ /> - {loading ? + {loading ?

Loading...

: (
{content} From 6359f59b739f0494530a8297f060338ca1c25b98 Mon Sep 17 00:00:00 2001 From: Delilah <23665803+goplayoutside3@users.noreply.github.com> Date: Fri, 7 Jun 2024 17:26:54 -0500 Subject: [PATCH 7/7] add endpoint to DashboardContainer key and no need for authorization --- .../components/Dashboard/DashboardContainer.js | 11 +++-------- .../UserHome/components/SubjectCard/SubjectCard.js | 4 ++-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/packages/lib-user/src/components/UserHome/components/Dashboard/DashboardContainer.js b/packages/lib-user/src/components/UserHome/components/Dashboard/DashboardContainer.js index 4ca53b6746..31ab8f324d 100644 --- a/packages/lib-user/src/components/UserHome/components/Dashboard/DashboardContainer.js +++ b/packages/lib-user/src/components/UserHome/components/Dashboard/DashboardContainer.js @@ -1,5 +1,4 @@ import { panoptes } from '@zooniverse/panoptes-js' -import auth from 'panoptes-client/lib/auth' import useSWR from 'swr' import Dashboard from './Dashboard' @@ -13,13 +12,9 @@ const SWROptions = { } /* This is a similar pattern to usePanoptesUser hook, but includes the profile_header */ -const fetchProfileBanner = async ({ authUser }) => { - const token = await auth.checkBearerToken() - const authorization = `Bearer ${token}` - const query = { include: 'profile_header', user_id: authUser.id } - +const fetchProfileBanner = async ({ authUser}) => { try { - const { body } = await panoptes.get('/users', query, { authorization }) + const { body } = await panoptes.get(`/users/${authUser.id}/?include=profile_header`) const user = body.users?.[0] if (body.linked?.profile_headers?.length) { @@ -33,7 +28,7 @@ const fetchProfileBanner = async ({ authUser }) => { } export default function DashboardContainer({ authUser }) { - const key = { authUser } + const key = { endpoint: '/users/[id]', authUser } const { data: user, isLoading } = useSWR(key, fetchProfileBanner, SWROptions) return diff --git a/packages/lib-user/src/components/UserHome/components/SubjectCard/SubjectCard.js b/packages/lib-user/src/components/UserHome/components/SubjectCard/SubjectCard.js index 2c131ad333..4fbac524a5 100644 --- a/packages/lib-user/src/components/UserHome/components/SubjectCard/SubjectCard.js +++ b/packages/lib-user/src/components/UserHome/components/SubjectCard/SubjectCard.js @@ -12,7 +12,7 @@ import styled from 'styled-components' import { Anchor, Box } from 'grommet' import { Media, SpacedText } from '@zooniverse/react-components' -import { number, string } from 'prop-types' +import { string } from 'prop-types' const StyledAnchor = styled(Anchor)` text-decoration: none; @@ -99,5 +99,5 @@ SubjectCard.propTypes = { size: string, projectSlug: string, mediaSrc: string, - subjectID: number.isRequired + subjectID: string.isRequired }