Skip to content

Commit

Permalink
Community page (iterative#874)
Browse files Browse the repository at this point in the history
* Initial commit for community page

* Add styles to community page blocks

* Addicons to meet blocks

* Remove console.log

* Add styles to Discord block

* Add styles for events

* Add illustration to community blocks

* Add real github api for issues

* Add comment about Github API mock

* Move @octokit/graphql to dependencies

* Add blog api integration

* Real API to get latest blog posts

* Update texts

* Add pluralization to comments count

* Add comments to blog posts

* Cache test

* Rewrote comments API using fetch

* Only show console.log in cache in dev mode

* Add cache to github

* Replace Discord with widget

* Hide events block if there is no upcoming events

* Add simple fallback for api handles

* Mobile version design

* Add dropdown menu to contribute

* Mobile design tweaks

* Fix comments height

* Revert discord widget

* Get discord stats from static file

* Return deleted images

* Revert "Mobile design tweaks"

This reverts commit d10481f.

# Conflicts:
#	src/Community/Block/styles.js
#	src/Community/styles.js

* Mobile styles for section in community

* Small design changes

* Fix lint-staged bug

* Add carousel to community page

* Fix lint error

* Add images to blog posts

* Add mobile banner

* Make all mobile section parts clickable

* Fix forum posts display on desktop

* Remove focus state from carousel dots

* Temporarily disable carousel

* Add small visual fixes

* Fix mobile safari bug

* Update desktop dropdown styles

* Remove carousel

* Add pictures to user content

* Add quick and dirty fix for section animation

* Added some user content

* three pieces of user content

* added the prague event, cleaned up events city + date formatting

* Added WIDS event

* WIDS logo

* Added divops.org

* Fixed divops date, and checked if the banners work as expected

* typo

* Added readable date support

* Change rel for external links to correct one

* Update Cotribute section actions

* Fix menu title

* Replace icons

* Fix non-even columns

* Add json linters

* Add paddings for sections on tablets

* Fix lint errors

* Update banner for Feb 20

* Added image icons to user content

* increase banner resolution

* Fix links and add analytics to community page

* Remove Learn section icons

* Normalize event pictures

* Add placeholder for events images

* Fix image line wrap

* Fix preemptive sendind of errors

* Add ref forwarding to button

* Update top menu styles (no-triangle)

* Update movile menu

* Add github and discord icons to header

* Fix opacity for links

* Make community headers clickable

* Fix Collapsible calculation on resize

* Open section on mobile navigation

* Reduce size of the icons in the head

* Fix bug woth bottom pading on tablet in Communuty

* Add triangle to dropdown menu

* Add subjects to mail links

* Revert issues sorting order

* Open mail links in the new window

* Set correct icon to mail in mobile menu

* Fix not working links in top menu

* update hero banners

* Fix item collapse in mobile safari

* Fix couple of visual bugs

* Refactor Community page in line with other pages

* Change blog api error status to 502

* Rename BareButton to CommunityButton

* Remove mistakenly copied images

* Remove getInitialProps to reenable static optimizations

Co-authored-by: Elle O'Brien <[email protected]>
Co-authored-by: Nate Gadzhibalaev <[email protected]>
Co-authored-by: Ivan Shcheklein <[email protected]>
  • Loading branch information
4 people authored Feb 12, 2020
1 parent 2b4e36d commit c32e687
Show file tree
Hide file tree
Showing 74 changed files with 2,609 additions and 361 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"eslint:recommended",
"plugin:prettier/recommended",
"plugin:react/recommended",
"plugin:jsx-a11y/recommended"
"plugin:jsx-a11y/recommended",
"plugin:json/recommended"
],
"parser": "babel-eslint",
"env": {
Expand Down
10 changes: 3 additions & 7 deletions app.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
{
"addons": [

],
"addons": [],
"buildpacks": [
{
"url": "heroku/nodejs"
}
],
"env": {
},
"env": {},
"formation": {
"web": {
"quantity": 1
}
},
"name": "dvc.org",
"scripts": {
},
"scripts": {},
"stack": "heroku-18"
}
22 changes: 13 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"test": "jest",
"start": "NODE_ENV=production node server.js",
"format-staged": "pretty-quick --staged --no-restage --bail",
"format-check": "prettier --check '{.,pages/**,public/static/docs/**,src/**}/*.{js,md}'",
"lint-check": "eslint src pages",
"format-all": "prettier --write '{.,pages/**,public/static/docs/**,src/**}/*.{js,md}'",
"format-check": "prettier --check '{.,pages/**,public/static/docs/**,src/**}/*.{js,md,json}'",
"lint-check": "eslint --ext .json,.js src pages",
"format-all": "prettier --write '{.,pages/**,public/static/docs/**,src/**}/*.{js,md,json}'",
"format": "prettier --write",
"link-check": "scripts/link-check-git-all.sh",
"link-check-diff": "scripts/link-check-git-diff.sh"
Expand All @@ -28,9 +28,11 @@
},
"homepage": "https://github.com/iterative/dvc.org#readme",
"dependencies": {
"@octokit/graphql": "^4.3.1",
"@sentry/browser": "^5.12.1",
"@zeit/next-source-maps": "^0.0.3",
"color": "^3.1.2",
"date-fns": "^2.8.1",
"dom-scroll-into-view": "^2.0.1",
"github-markdown-css": "^3.0.1",
"isomorphic-fetch": "^2.2.1",
Expand All @@ -41,19 +43,20 @@
"lodash.topairs": "^4.3.0",
"micro-cors": "^0.1.1",
"next": "^9.1.6",
"node-cache": "^5.1.0",
"perfect-scrollbar": "^1.4.0",
"prop-types": "^15.7.2",
"react": "^16.12.0",
"react-collapse": "^4.0.3",
"react-collapse": "^5.0.1",
"react-collapsible": "^2.6.2",
"react-dom": "^16.12.0",
"react-ga": "^2.7.0",
"react-markdown": "^4.2.2",
"react-motion": "^0.5.2",
"react-popover": "^0.5.10",
"react-scroll": "^1.7.13",
"react-slick": "^0.25.2",
"react-syntax-highlighter": "^11.0.2",
"react-use": "^13.24.0",
"request": "^2.88.0",
"styled-components": "^4.4.1",
"styled-reset": "^4.0.8",
Expand All @@ -67,21 +70,22 @@
"babel-plugin-transform-object-assign": "^6.22.0",
"eslint": "^6.7.2",
"eslint-config-prettier": "^6.7.0",
"eslint-plugin-json": "^2.0.1",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-react": "^7.17.0",
"husky": "^3.1.0",
"husky": "^4.0.10",
"jest": "^24.9.0",
"lint-staged": "^10.0.0-1",
"lint-staged": "^10.0.0",
"prettier": "^1.19.1",
"pretty-quick": "^2.0.1"
},
"husky": {
"hooks": {
"pre-commit": "yarn format-staged && lint-staged"
"pre-commit": "yarn format-staged && yarn lint-staged"
}
},
"lint-staged": {
"*.js": "eslint"
"*.{js,json}": "eslint"
}
}
10 changes: 0 additions & 10 deletions pages/_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,6 @@ Sentry.init({
})

class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
let pageProps = {}

if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx)
}

return { pageProps }
}

componentDidCatch(error, errorInfo) {
Sentry.withScope(scope => {
Object.keys(errorInfo).forEach(key => {
Expand Down
19 changes: 19 additions & 0 deletions pages/api/blog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import fetch from 'isomorphic-fetch'

export default async (_, res) => {
try {
const response = await fetch(`https://blog.dvc.org/api/posts.json`)

if (response.status !== 200) {
res.status(502).json({ error: 'Unexpected response from Blog' })

return
}

const data = await response.text()

res.status(200).json(data)
} catch {
res.status(502)
}
}
39 changes: 31 additions & 8 deletions pages/api/comments.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-env node */

/*
* This API endpoint is used by our blog to get comments count for the post, it
* gets discuss.dvc.org topic URL as a param and returns comments count or
Expand All @@ -7,17 +9,22 @@
* potential ability to cache comments count in the future.
*/

import fetch from 'isomorphic-fetch'
import Cors from 'micro-cors'
import request from 'request'
import NodeCache from 'node-cache'

import { BLOG_URL, FORUM_URL } from '../../src/consts'

const cache = new NodeCache({ stdTTL: 900 })

const dev = process.env.NODE_ENV === 'development'

const cors = Cors({
allowedMethods: ['GET', 'HEAD'],
origin: BLOG_URL
})

const getCommentCount = (req, res) => {
const getCommentCount = async (req, res) => {
const {
query: { url }
} = req
Expand All @@ -28,26 +35,42 @@ const getCommentCount = (req, res) => {
return
}

request(`${url}.json`, (error, response, body) => {
if (error || response.statusCode !== 200) {
if (cache.get(url) !== undefined) {
if (dev) console.log(`Using cache for ${url}`)

res.status(200).json({ count: cache.get(url) })

return
} else {
if (dev) console.log(`Not using cache for ${url}`)
}

try {
const response = await fetch(`${url}.json`)

if (response.status !== 200) {
res.status(502).json({ error: 'Unexpected response from Forum' })

return
}

const json = JSON.parse(body)
const data = await response.json()

if (!json.posts_count) {
if (!data.posts_count) {
res.status(502).json({ error: 'Unexpected payload from Forum' })

return
}

// post_count return all posts including topic itself
const count = json.posts_count - 1
const count = data.posts_count - 1

cache.set(url, count)

res.status(200).json({ count })
})
} catch {
res.status(404)
}
}

export default cors(getCommentCount)
51 changes: 51 additions & 0 deletions pages/api/discourse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* eslint-env node */

import fetch from 'isomorphic-fetch'
import NodeCache from 'node-cache'

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

const cache = new NodeCache({ stdTTL: 900 })

const dev = process.env.NODE_ENV === 'development'

export default async (_, res) => {
if (cache.get('topics')) {
if (dev) console.log('Using cache for "topics"')

res.status(200).json(cache.get('topics'))

return
} else {
if (dev) console.log('Not using cache for "topics"')
}

try {
const response = await fetch(`${FORUM_URL}/latest.json?order=created`)

if (response.status !== 200) {
res.status(502).json({ error: 'Unexpected response from Forum' })

return
}

const data = await response.text()

const {
topic_list: { topics: original_topics }
} = JSON.parse(data)

const topics = original_topics.slice(0, 3).map(item => ({
title: item.title,
comments: item.posts_count - 1,
date: item.last_posted_at,
url: `${FORUM_URL}/t/${item.slug}/${item.id}`
}))

cache.set('topics', { topics })

res.status(200).json({ topics })
} catch {
res.status(404)
}
}
67 changes: 67 additions & 0 deletions pages/api/github.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* eslint-env node */

import { graphql } from '@octokit/graphql'
import NodeCache from 'node-cache'

const cache = new NodeCache({ stdTTL: 900 })

const dev = process.env.NODE_ENV === 'development'

export default async (_, res) => {
if (!process.env.GITHUB_TOKEN) {
res.status(200).json({ issues: [] })
} else {
if (cache.get('issues')) {
if (dev) console.log('Using cache for "issues"')

res.status(200).json({ issues: cache.get('issues') })
} else {
console.log('Not using cache for "issues"')
}

try {
const { repository } = await graphql(
`
{
repository(owner: "iterative", name: "dvc") {
issues(
first: 3
states: OPEN
orderBy: { field: CREATED_AT, direction: DESC }
) {
edges {
node {
title
createdAt
url
comments {
totalCount
}
}
}
}
}
}
`,
{
headers: {
authorization: `token ${process.env.GITHUB_TOKEN}`
}
}
)

const issues = repository.issues.edges.map(({ node }) => ({
title: node.title,
url: node.url,
comments: node.comments.totalCount,
date: node.createdAt
}))

cache.set('issues', issues)

res.status(200).json({ issues })
} catch (e) {
res.status(404)
}
}
}
46 changes: 46 additions & 0 deletions pages/community.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
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) {
return (
<>
<Head>
<link
rel="stylesheet"
type="text/css"
charSet="UTF-8"
href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css"
/>
<link
rel="stylesheet"
type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css"
/>
<title>Community | {META_BASE_TITLE}</title>
</Head>
<Community {...props} />
</>
)
}

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

return {
issues,
posts,
topics
}
}
Loading

0 comments on commit c32e687

Please sign in to comment.