diff --git a/packages/lib-user/src/components/UserHome/components/RecentProjects/RecentProjects.js b/packages/lib-user/src/components/UserHome/components/RecentProjects/RecentProjects.js index 107da9beb7..04d860ace3 100644 --- a/packages/lib-user/src/components/UserHome/components/RecentProjects/RecentProjects.js +++ b/packages/lib-user/src/components/UserHome/components/RecentProjects/RecentProjects.js @@ -1,5 +1,5 @@ import { Anchor, Box, ResponsiveContext, Text } from 'grommet' -import { arrayOf, bool, shape, string } from 'prop-types' +import { arrayOf, bool, number, shape, string } from 'prop-types' import { useContext } from 'react' import { Loader, ProjectCard, SpacedText } from '@zooniverse/react-components' @@ -7,26 +7,24 @@ import { ContentBox } from '@components/shared' export default function RecentProjects({ isLoading = false, - projectPreferences = [], + recentProjects = [], error = undefined }) { const size = useContext(ResponsiveContext) return ( - {isLoading && ( + {isLoading ? ( - )} - {!isLoading && error && ( + ) : error ? ( There was an error fetching your recent projects - )} - {!isLoading && !projectPreferences.length && !error && ( + ) : !recentProjects.length ? ( No Recent Projects found @@ -37,41 +35,44 @@ export default function RecentProjects({ . + ) : ( + + {recentProjects.map(project => ( +
  • + +
  • + ))} +
    )} - {!isLoading && - projectPreferences?.length ? ( - - {projectPreferences.map(preference => ( -
  • - -
  • - ))} -
    - ) : null}
    ) } RecentProjects.propTypes = { isLoading: bool, - projectPreferences: arrayOf( + recentProjects: arrayOf( shape({ - id: string + avatar_src: string, + count: number, + description: string, + display_name: string, + id: string, + slug: string }) ) } diff --git a/packages/lib-user/src/components/UserHome/components/RecentProjects/RecentProjectsContainer.js b/packages/lib-user/src/components/UserHome/components/RecentProjects/RecentProjectsContainer.js index d085aa9f4a..a19b75656a 100644 --- a/packages/lib-user/src/components/UserHome/components/RecentProjects/RecentProjectsContainer.js +++ b/packages/lib-user/src/components/UserHome/components/RecentProjects/RecentProjectsContainer.js @@ -1,90 +1,56 @@ 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 { usePanoptesProjects, useStats } 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 = { - 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) - return projectPreferencesUserHasClassified - } - return [] - } catch (error) { - console.error(error) - throw error - } -} - 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 recentProjectsQuery = { + project_contributions: true, + order_project_contributions_by: 'recents', + period: 'day' } + const { - data: projectPreferences, - isLoading: preferencesLoading, - error: preferencesError - } = useSWR(cacheKey, fetchUserProjectPreferences, SWROptions) + data: stats, + isLoading: statsLoading, + error: statsError + } = useStats({ sourceId: authUser?.id, query: recentProjectsQuery }) - // Get more info about each project and attach it to correct projectPreference object - const recentProjectIds = projectPreferences?.map( - preference => preference.links.project - ) + // limit to 20 projects fetched from panoptes + const contributions = stats?.project_contributions.slice(0, 20) + const projectIds = contributions?.map(project => project.project_id) + + // Get more info about each project const { data: projects, isLoading: projectsLoading, error: projectsError } = usePanoptesProjects({ cards: true, - id: recentProjectIds?.join(',') + id: projectIds?.join(',') }) - - // Attach project object to each project preference - let projectPreferencesWithProjectObj - if (projects?.length) { - projectPreferencesWithProjectObj = projectPreferences - .map(preference => { - const matchedProjectObj = projects.find( - project => project.id === preference.links?.project - ) - if (matchedProjectObj) { - preference.project = matchedProjectObj + // Attach project info to each contribution stat (see similar behavior in TopProjects) + let recentProjects = [] + + if (projects?.length && contributions?.length) { + recentProjects = contributions + .map(projectContribution => { + const projectData = projects?.find( + project => project.id === projectContribution.project_id.toString() + ) + return { + count: projectContribution.count, + ...projectData } - return preference }) - .filter(preference => preference?.project?.slug) - .slice(0, 10) + .filter(project => project?.id) // exclude private or deleted projects } return ( ) } diff --git a/packages/lib-user/src/components/shared/ContentBox/components/ContentLink.js b/packages/lib-user/src/components/shared/ContentBox/components/ContentLink.js index f162e4d3ee..a9a117f9d3 100644 --- a/packages/lib-user/src/components/shared/ContentBox/components/ContentLink.js +++ b/packages/lib-user/src/components/shared/ContentBox/components/ContentLink.js @@ -1,10 +1,10 @@ import { SpacedText } from '@zooniverse/react-components' import { Anchor } from 'grommet' -import { shape, string } from 'prop-types' +import { object, oneOfType, shape, string } from 'prop-types' import styled from 'styled-components' const StyledAnchor = styled(Anchor)` - font-family: 'Karla', Arial, sans-serif; + font-family: 'Karla', Arial, sans-serif; font-size: 1rem; line-height: normal; background: none; @@ -45,7 +45,7 @@ function ContentLink({ ContentLink.propTypes = { link: shape({ - as: string, + as: oneOfType([object, string]), href: string, text: string })