Skip to content

Commit

Permalink
Move API calls on community page to client side (#995)
Browse files Browse the repository at this point in the history
* Move API calls on community page to client side

* Replace API functions with hooks

* Update src/components/Community/Learn/index.js

Co-Authored-By: Jorge Orpinel <[email protected]>

* Update src/components/Community/Meet/index.js

Co-Authored-By: Jorge Orpinel <[email protected]>

* Update src/components/Community/Meet/index.js

Co-Authored-By: Jorge Orpinel <[email protected]>

* Update src/utils/api.js

Co-Authored-By: Jorge Orpinel <[email protected]>

* Restyled by prettier (#999)

Co-authored-by: Ivan Shcheklein <[email protected]>
Co-authored-by: Jorge Orpinel <[email protected]>
Co-authored-by: restyled-io[bot] <32688539+restyled-io[bot]@users.noreply.github.com>
  • Loading branch information
4 people authored Feb 15, 2020
1 parent d34de72 commit 64f4c48
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 103 deletions.
22 changes: 2 additions & 20 deletions pages/community.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
import React from 'react'
import Head from 'next/head'

import {
getLatestIssues,
getLatestTopics,
getLatestPosts
} from '../src/utils/api'

import Community from '../src/components/Community'

import { META_BASE_TITLE } from '../src/consts'

export default function CommunityPage(props) {
export default function CommunityPage() {
return (
<>
<Head>
Expand All @@ -28,19 +22,7 @@ export default function CommunityPage(props) {
/>
<title>Community | {META_BASE_TITLE}</title>
</Head>
<Community {...props} />
<Community />
</>
)
}

CommunityPage.getInitialProps = async ({ req }) => {
const issues = await getLatestIssues(req)
const posts = await getLatestPosts(req)
const topics = await getLatestTopics(req)

return {
issues,
posts,
topics
}
}
34 changes: 13 additions & 21 deletions src/components/Community/Learn/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useState } from 'react'
import React, { useCallback } from 'react'
import PropTypes from 'prop-types'
import format from 'date-fns/format'

Expand All @@ -10,6 +10,7 @@ import CommunityBlock from '../Block'
import CommunityButton from '../Button'
import CommunitySection from '../Section'

import { usePosts, useCommentsCount } from '../../../utils/api'
import { pluralizeComments } from '../../../utils/i18n'

import {
Expand Down Expand Up @@ -45,19 +46,10 @@ function CommunityBlogPost({
commentsUrl,
pictureUrl
}) {
const [count, setCount] = useState()
const loaded = count !== undefined
const logPost = useCallback(() => logEvent('community', 'blog', title), [
title
])

useEffect(() => {
if (commentsUrl) {
fetch(`/api/comments?url=${commentsUrl}`)
.then(result => result.json())
.then(data => setCount(data.count))
}
}, [])
const { error, ready, result } = useCommentsCount(commentsUrl)

return (
<ImageLine key={url}>
Expand All @@ -82,14 +74,14 @@ function CommunityBlogPost({
{title}
</Link>
<Meta>
{loaded && (
{ready && !error && (
<>
<Comments
href={commentsUrl}
target="_blank"
rel="noreferrer noopener"
>
{pluralizeComments(count)}
{pluralizeComments(result)}
</Comments>
{' • '}
</>
Expand Down Expand Up @@ -185,7 +177,9 @@ CommunityDocumentation.propTypes = {
url: PropTypes.string
}

export default function CommunityLearn({ posts, theme }) {
export default function CommunityLearn({ theme }) {
const { error, ready, result: posts } = usePosts()

return (
<Wrapper>
<CommunitySection
Expand Down Expand Up @@ -242,7 +236,7 @@ export default function CommunityLearn({ posts, theme }) {
</HeaderLink>
}
action={
posts.length && (
posts && (
<CommunityButton
theme={theme}
href="https://blog.dvc.org"
Expand All @@ -255,17 +249,16 @@ export default function CommunityLearn({ posts, theme }) {
)
}
>
{posts.length ? (
{!ready && <Placeholder>Loading...</Placeholder>}
{error && <Placeholder>Blog unavailable right now</Placeholder>}
{posts &&
posts.map(post => (
<CommunityBlogPost
{...post}
key={post.url}
color={theme.color}
/>
))
) : (
<Placeholder>Blog is unavailable right now</Placeholder>
)}
))}
</CommunityBlock>
</Item>
<Item>
Expand All @@ -286,7 +279,6 @@ export default function CommunityLearn({ posts, theme }) {
}

CommunityLearn.propTypes = {
posts: PropTypes.array,
theme: PropTypes.shape({
backgroundColor: PropTypes.string,
color: PropTypes.string
Expand Down
36 changes: 20 additions & 16 deletions src/components/Community/Meet/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import CommunitySection from '../Section'

import { pluralizeComments } from '../../../utils/i18n'
import { logEvent } from '../../../utils/ga'
import { useIssues, useTopics } from '../../../utils/api'

import data from '../data'

Expand Down Expand Up @@ -110,7 +111,10 @@ CommunityIssue.propTypes = {
color: PropTypes.string
}

export default function CommunityMeet({ issues, theme, topics }) {
export default function CommunityMeet({ theme }) {
const { erorr: issuesError, ready: issuesReady, result: issues } = useIssues()
const { erorr: topicsError, ready: topicsReady, result: topics } = useTopics()

return (
<Wrapper>
<CommunitySection
Expand Down Expand Up @@ -177,7 +181,7 @@ export default function CommunityMeet({ issues, theme, topics }) {
</HeaderLink>
}
action={
topics.length && (
topics && (
<CommunityButton
theme={theme}
href="https://discuss.dvc.org"
Expand All @@ -191,17 +195,18 @@ export default function CommunityMeet({ issues, theme, topics }) {
}
icon="/static/img/community/discourse.svg"
>
{topics.length ? (
{!topicsReady && <Placeholder>Loading...</Placeholder>}
{topicsError && (
<Placeholder>Forum unavailable right now</Placeholder>
)}
{topics &&
topics.map(topic => (
<CommunityTopic
{...topic}
key={topic.url}
color={theme.color}
/>
))
) : (
<Placeholder>Forum is unavailable right now</Placeholder>
)}
))}
</CommunityBlock>
</Item>
<Item>
Expand All @@ -217,7 +222,7 @@ export default function CommunityMeet({ issues, theme, topics }) {
</HeaderLink>
}
action={
issues.length && (
issues && (
<CommunityButton
theme={theme}
href="https://github.com/iterative/dvc/issues"
Expand All @@ -231,17 +236,18 @@ export default function CommunityMeet({ issues, theme, topics }) {
}
icon="/static/img/community/github.svg"
>
{issues.length ? (
{!issuesReady && <Placeholder>Loading...</Placeholder>}
{issuesError && (
<Placeholder>Github unavailable right now</Placeholder>
)}
{issues &&
issues.map(issue => (
<CommunityIssue
{...issue}
key={issue.url}
color={theme.color}
/>
))
) : (
<Placeholder>Github is unavailable right now</Placeholder>
)}
))}
</CommunityBlock>
</Item>
</Items>
Expand All @@ -251,10 +257,8 @@ export default function CommunityMeet({ issues, theme, topics }) {
}

CommunityMeet.propTypes = {
issues: PropTypes.array,
theme: PropTypes.shape({
backgroundColor: PropTypes.string,
color: PropTypes.string
}),
topics: PropTypes.array
})
}
13 changes: 3 additions & 10 deletions src/components/Community/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react'
import PropTypes from 'prop-types'

import Page from '../Page'
import Subscribe from '../Subscribe'
Expand All @@ -18,23 +17,17 @@ const themes = {
purple: { backgroundColor: '#DCD6F1', color: '#955DD6' }
}

export default function Community({ issues, posts, topics }) {
export default function Community() {
return (
<Page stickHeader={true}>
<PageWrapper>
<CommunityHero />
<CommunityMeet issues={issues} topics={topics} theme={themes.purple} />
<CommunityMeet theme={themes.purple} />
<CommunityContribute theme={themes.orange} />
<CommunityLearn posts={posts} theme={themes.green} />
<CommunityLearn theme={themes.green} />
<CommunityEvents theme={themes.purple} />
<Subscribe />
</PageWrapper>
</Page>
)
}

Community.propTypes = {
issues: PropTypes.array,
posts: PropTypes.array,
topics: PropTypes.array
}
87 changes: 51 additions & 36 deletions src/utils/api.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useEffect, useState } from 'react'
import fetch from 'isomorphic-fetch'

export function makeAbsoluteURL(req, uri) {
Expand All @@ -7,50 +8,64 @@ export function makeAbsoluteURL(req, uri) {
return `${protocol}//${host}${uri}`
}

export async function getLatestIssues(req) {
try {
const res = await fetch(makeAbsoluteURL(req, '/api/github'))

if (res.status !== 200) return []

const { issues } = await res.json()

return issues
} catch (e) {
console.error(e)

return []
}
const useAPICall = url => {
const [ready, setReady] = useState(false)
const [error, setError] = useState(false)
const [result, setResult] = useState(null)

useEffect(() => {
let cancelled = false

const fetchData = async () => {
try {
const res = await fetch(url)

if (!cancelled) {
if (res.status !== 200) {
setError('Bad response status')
} else {
setResult(await res.json())
}
}
} catch {
if (!cancelled) setError('Error loading request')
} finally {
if (!cancelled) setReady(true)
}
}

fetchData()

return () => {
cancelled = true
}
}, [])

return { error, ready, result }
}

export async function getLatestPosts(req) {
try {
const res = await fetch(makeAbsoluteURL(req, '/api/blog'))
export function useIssues() {
const { error, ready, result } = useAPICall('/api/github')

if (res.status !== 200) return []

const { posts } = await res.json()
return { error, ready, result: result && result.issues }
}

return posts
} catch (e) {
console.error(e)
export function usePosts() {
const { error, ready, result } = useAPICall('/api/blog')

return []
}
return { error, ready, result: result && result.posts }
}

export async function getLatestTopics(req) {
try {
const res = await fetch(makeAbsoluteURL(req, '/api/discourse'))
export function useTopics() {
const { error, ready, result } = useAPICall('/api/discourse')

if (res.status !== 200) return []

const { topics } = await res.json()
return { error, ready, result: result && result.topics }
}

return topics
} catch (e) {
console.error(e)
export function useCommentsCount(commentsUrl) {
const { error, ready, result } = useAPICall(
`/api/comments?url=${commentsUrl}`
)

return []
}
return { error, ready, result: result && result.count }
}

0 comments on commit 64f4c48

Please sign in to comment.