-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Homepage: Create RecentProjects component, refactor data fetching in …
…RecentSubjects (#6125) * fetch and display project cards for 'project_contributions' on hompage * add count badge * refactor RecentSubjects to fetch data like RecentProjects * create grid layout in UserHome * remove edits to Dashboard * use project_preferences for most recently classified projects * minor fix for new users with no projectPreferences * Refactor RecentProjects and RecentSubject containers to throw fetch error * Refactor Recent projects and subjects components ul and li's * Refactor Recent projects and subjects stories * Refactor project and subject cards for improved focus styling * Refactor recents in RecentSubjectsContainer * Add await for checkCurrent user --------- Co-authored-by: Mark Bouslog <[email protected]>
- Loading branch information
1 parent
1a9e6c2
commit 37bef25
Showing
12 changed files
with
362 additions
and
175 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
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
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
77 changes: 77 additions & 0 deletions
77
packages/lib-user/src/components/UserHome/components/RecentProjects/RecentProjects.js
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,77 @@ | ||
import { Anchor, Box, ResponsiveContext, Text } from 'grommet' | ||
import { arrayOf, bool, shape, string } from 'prop-types' | ||
import { useContext } from 'react' | ||
import { Loader, ProjectCard, SpacedText } from '@zooniverse/react-components' | ||
|
||
import { ContentBox } from '@components/shared' | ||
|
||
export default function RecentProjects({ | ||
isLoading = false, | ||
projectPreferences = [], | ||
error = undefined | ||
}) { | ||
const size = useContext(ResponsiveContext) | ||
|
||
return ( | ||
<ContentBox title='Continue Classifying' screenSize={size}> | ||
{isLoading && ( | ||
<Box fill justify='center' align='center'> | ||
<Loader /> | ||
</Box> | ||
)} | ||
{!isLoading && error && ( | ||
<Box fill justify='center' align='center' pad='medium'> | ||
<SpacedText> | ||
There was an error fetching your recent projects | ||
</SpacedText> | ||
</Box> | ||
)} | ||
{!isLoading && !projectPreferences.length && !error && ( | ||
<Box fill justify='center' align='center' pad='medium'> | ||
<SpacedText>No Recent Projects found</SpacedText> | ||
<Text> | ||
Start by{' '} | ||
<Anchor href='https://www.zooniverse.org/projects'> | ||
classifying any project | ||
</Anchor> | ||
. | ||
</Text> | ||
</Box> | ||
)} | ||
{!isLoading && | ||
projectPreferences?.length ? ( | ||
<Box | ||
as='ul' | ||
direction='row' | ||
gap='small' | ||
pad={{ horizontal: 'xxsmall', bottom: 'xsmall', top: 'xxsmall' }} | ||
overflow={{ horizontal: 'auto' }} | ||
style={{ listStyle: 'none' }} | ||
margin='0' | ||
> | ||
{projectPreferences.map(preference => ( | ||
<li key={preference?.project?.id}> | ||
<ProjectCard | ||
badge={preference?.activity_count} | ||
description={preference?.project?.description} | ||
displayName={preference?.project?.display_name} | ||
href={`https://www.zooniverse.org/projects/${preference?.project?.slug}`} | ||
imageSrc={preference?.project?.avatar_src} | ||
size={size} | ||
/> | ||
</li> | ||
))} | ||
</Box> | ||
) : null} | ||
</ContentBox> | ||
) | ||
} | ||
|
||
RecentProjects.propTypes = { | ||
isLoading: bool, | ||
projectPreferences: arrayOf( | ||
shape({ | ||
id: string | ||
}) | ||
) | ||
} |
31 changes: 31 additions & 0 deletions
31
...ages/lib-user/src/components/UserHome/components/RecentProjects/RecentProjects.stories.js
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,31 @@ | ||
import RecentProjects from './RecentProjects.js' | ||
import { PROJECTS } from '../../../../../test/mocks/panoptes/projects.js' | ||
|
||
const mockProjectPreferencesWithProjectObj = PROJECTS.map(project => ({ | ||
activity_count: Math.floor(Math.random() * 100), | ||
project | ||
})) | ||
|
||
export default { | ||
title: 'Components / UserHome / RecentProjects', | ||
component: RecentProjects | ||
} | ||
|
||
export const Default = { | ||
args: { | ||
projectPreferences: mockProjectPreferencesWithProjectObj | ||
} | ||
} | ||
|
||
export const NoProjects = { | ||
args: { | ||
projectPreferences: [] | ||
} | ||
} | ||
|
||
export const Error = { | ||
args: { | ||
projectPreferences: [], | ||
error: { message: `Couldn't fetch recent projects` } | ||
} | ||
} |
92 changes: 92 additions & 0 deletions
92
...ges/lib-user/src/components/UserHome/components/RecentProjects/RecentProjectsContainer.js
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,92 @@ | ||
import { shape, string } from 'prop-types' | ||
import { panoptes } from '@zooniverse/panoptes-js' | ||
import useSWR from 'swr' | ||
import auth from 'panoptes-client/lib/auth' | ||
|
||
import { usePanoptesProjects } from '@hooks' | ||
import RecentProjects from './RecentProjects.js' | ||
|
||
const SWROptions = { | ||
revalidateIfStale: true, | ||
revalidateOnMount: true, | ||
revalidateOnFocus: true, | ||
revalidateOnReconnect: true, | ||
refreshInterval: 0 | ||
} | ||
|
||
async function fetchUserProjectPreferences() { | ||
const user = await auth.checkCurrent() | ||
const token = await auth.checkBearerToken() | ||
const authorization = `Bearer ${token}` | ||
try { | ||
const query = { | ||
page: 1, // returns 20 items | ||
sort: '-updated_at', | ||
user_id: user.id | ||
} | ||
const response = await panoptes.get('/project_preferences', query, { authorization }) | ||
if (response.ok) { | ||
const projectPreferencesUserHasClassified = | ||
response.body.project_preferences | ||
.filter(preference => preference.activity_count > 0) | ||
.slice(0, 10) | ||
return projectPreferencesUserHasClassified | ||
} | ||
return [] | ||
} catch (error) { | ||
console.error(error) | ||
throw error | ||
} | ||
} | ||
|
||
export default function RecentProjectsContainer({ authUser }) { | ||
// Get user's project preference.activity_count for 10 most recently classified projects | ||
const cacheKey = { | ||
name: 'user-project-preferences', | ||
userId: authUser.id | ||
} | ||
const { | ||
data: projectPreferences, | ||
isLoading: preferencesLoading, | ||
error: preferencesError | ||
} = useSWR(cacheKey, fetchUserProjectPreferences, SWROptions) | ||
|
||
// Get more info about each project and attach it to correct projectPreference object | ||
const recentProjectIds = projectPreferences?.map( | ||
preference => preference.links.project | ||
) | ||
const { | ||
data: projects, | ||
isLoading: projectsLoading, | ||
error: projectsError | ||
} = usePanoptesProjects(recentProjectIds) | ||
|
||
let projectPreferencesWithProjectObj | ||
|
||
if (projects?.length) { | ||
projectPreferencesWithProjectObj = projectPreferences?.map(preference => { | ||
const matchedProjectObj = projects.find( | ||
project => project.id === preference.links.project | ||
) | ||
|
||
if (matchedProjectObj) { | ||
preference.project = matchedProjectObj | ||
} | ||
return preference | ||
}) | ||
} | ||
|
||
return ( | ||
<RecentProjects | ||
isLoading={preferencesLoading || projectsLoading} | ||
projectPreferences={projectPreferencesWithProjectObj} | ||
error={preferencesError || projectsError} | ||
/> | ||
) | ||
} | ||
|
||
RecentProjectsContainer.propTypes = { | ||
authUser: shape({ | ||
id: string | ||
}) | ||
} |
Oops, something went wrong.