Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()
Comment thread
shcheklein marked this conversation as resolved.

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 }
}