-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit d9019f2
Showing
27 changed files
with
8,149 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# See https://help.github.com/ignore-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
|
||
# testing | ||
/coverage | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* |
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,17 @@ | ||
# React Hacker News | ||
|
||
Yet another React Hacker News clone | ||
|
||
**Demo:** [https://ya-react-hn.now.sh](https://ya-react-hn.now.sh) | ||
|
||
Featuring: | ||
|
||
- [React 16](https://reactjs.org/) | ||
- [React Router 4](https://reacttraining.com/react-router) | ||
- [React Redux](https://redux.js.org/docs/basics/UsageWithReact.html) | ||
- [Redux Thunk](https://github.com/gaearon/redux-thunk) | ||
- [HN API](https://github.com/cheeaun/node-hnapi) | ||
- CSS variables | ||
- unread link highlighting | ||
- clickable links in comments | ||
|
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,27 @@ | ||
{ | ||
"name": "react-hn", | ||
"version": "0.1.0", | ||
"private": true, | ||
"dependencies": { | ||
"anchorme": "^1.1.2", | ||
"dompurify": "^1.0.3", | ||
"react": "^16.2.0", | ||
"react-dom": "^16.2.0", | ||
"react-redux": "^5.0.6", | ||
"react-router-dom": "^4.2.2", | ||
"react-scripts": "1.1.0", | ||
"redux": "^3.7.2", | ||
"redux-thunk": "^2.2.0", | ||
"serve": "^6.4.9" | ||
}, | ||
"scripts": { | ||
"start": "react-scripts start", | ||
"now-start": "serve --single ./build", | ||
"build": "react-scripts build", | ||
"test": "react-scripts test --env=jsdom", | ||
"eject": "react-scripts eject" | ||
}, | ||
"devDependencies": { | ||
"redux-devtools": "^3.4.1" | ||
} | ||
} |
Binary file not shown.
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,17 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||
<meta name="theme-color" content="#20232a"> | ||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json"> | ||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> | ||
<title>React HN</title> | ||
</head> | ||
<body> | ||
<noscript> | ||
You need to enable JavaScript to run this app. | ||
</noscript> | ||
<div id="root"></div> | ||
</body> | ||
</html> |
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,15 @@ | ||
{ | ||
"short_name": "React HN", | ||
"name": "React Hacker News clone", | ||
"icons": [ | ||
{ | ||
"src": "favicon.ico", | ||
"sizes": "64x64 32x32 24x24 16x16", | ||
"type": "image/x-icon" | ||
} | ||
], | ||
"start_url": "./index.html", | ||
"display": "standalone", | ||
"theme_color": "#20232a", | ||
"background_color": "#ffffff" | ||
} |
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,9 @@ | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import App from './App'; | ||
|
||
it('renders without crashing', () => { | ||
const div = document.createElement('div'); | ||
ReactDOM.render(<App />, div); | ||
ReactDOM.unmountComponentAtNode(div); | ||
}); |
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,101 @@ | ||
import React, { Component } from 'react'; | ||
import { connect } from 'react-redux'; | ||
import { Redirect } from 'react-router-dom'; | ||
import { getCollection } from './actions'; | ||
import Item from './components/Item'; | ||
import Pagination from './components/Pagination'; | ||
import { scrollToTop, renderLoading } from './helpers'; | ||
|
||
class Collection extends Component { | ||
|
||
componentDidMount() { | ||
this.getData(this.props.type); | ||
scrollToTop(); | ||
} | ||
|
||
componentWillReceiveProps(nextProps) { | ||
const typeChanged = this.props.type !== nextProps.type; | ||
const pageChanged = this.props.match.params.page !== nextProps.match.params.page | ||
if ( typeChanged || pageChanged ) { | ||
this.getData(nextProps.type, nextProps.match.params.page); | ||
} | ||
} | ||
|
||
getData(type, page = null) { | ||
if (page === null) { | ||
page = this.props.match.params.page || 1; | ||
} | ||
this.props.dispatch(getCollection(type, page)); | ||
} | ||
|
||
renderContent(content) { | ||
if (! content) return; | ||
const page = this.props.match.params.page || 1; | ||
if (content.length > 0) { | ||
return ( | ||
<div> | ||
{this.renderList(content, content.length)} | ||
<Pagination page={page} type={this.props.type} /> | ||
</div> | ||
); | ||
} | ||
if (! this.props.isFetching) { | ||
const url = this.props.match.path.replace(':page?', page - 1); | ||
return ( | ||
<div className="container content"> | ||
<p>There's nothing to show here…</p> | ||
<a href={url}> | ||
Try the previous page? | ||
</a> | ||
</div> | ||
); | ||
} | ||
renderLoading(); | ||
} | ||
|
||
renderList(data, perPage) { | ||
let classNames = "collection content"; | ||
if (this.props.isFetching) { | ||
classNames = `${classNames} is-fetching`; | ||
} | ||
return ( | ||
<div className={classNames}> | ||
<ol className="collection__list"> | ||
{this.renderItems(data, perPage)} | ||
</ol> | ||
</div> | ||
); | ||
} | ||
|
||
renderItems(data, perPage) { | ||
const page = this.props.match.params.page || 1; | ||
return data.map((data, index) => ( | ||
<li key={index}> | ||
<Item | ||
key={index} | ||
index={index} | ||
data={data} | ||
page={page} | ||
perPage={perPage} | ||
/> | ||
</li> | ||
)); | ||
} | ||
|
||
render() { | ||
if (this.props.match.params.page > 10) { | ||
return ( | ||
<Redirect to={this.props.match.path.replace(':page', 10)}/> | ||
); | ||
} | ||
return ( | ||
<div className="container"> | ||
{ this.renderContent(this.props[this.props.type]) } | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
const mapStateToProps = state => state.collections; | ||
|
||
export default connect(mapStateToProps)(Collection); |
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,117 @@ | ||
import React, { Component, Fragment } from 'react'; | ||
import { connect } from 'react-redux'; | ||
import { Link } from 'react-router-dom'; | ||
import { getSingle } from './actions'; | ||
import Comment from './components/Comment'; | ||
import discussion from './components/discussion'; | ||
import { scrollToTop, renderLoading } from './helpers'; | ||
|
||
class Story extends Component { | ||
|
||
componentWillMount() { | ||
const { id } = this.props.match.params; | ||
this.props.dispatch(getSingle('item', id)); | ||
} | ||
|
||
componentDidMount() { | ||
scrollToTop(); | ||
} | ||
|
||
renderStory(data) { | ||
if (data && Object.hasOwnProperty.call(data, 'comments')) { | ||
return ( | ||
<div className="single container content"> | ||
<h1 className="single__title"> | ||
<a | ||
className="single__link" | ||
href={data.url} | ||
> | ||
{data.title} | ||
{data.domain && | ||
<Fragment> | ||
| ||
<span className="single__domain">({data.domain})</span> | ||
</Fragment> | ||
} | ||
</a> | ||
</h1> | ||
<div className="single__meta"> | ||
{data.points && ( | ||
<Fragment> | ||
{data.points} {data.points === 1 ? 'point ' : 'points '} | ||
by <Link to={`/user/${data.user}`}>{data.user}</Link> | ||
</Fragment> | ||
)} | ||
{discussion(data) && | ||
<Fragment> | ||
| | ||
{discussion(data)} | ||
</Fragment> | ||
} | ||
</div> | ||
</div> | ||
); | ||
} | ||
if (! this.props.isFetching) { | ||
return ( | ||
<p>Nothing to show…</p> | ||
) | ||
} | ||
return renderLoading(); | ||
} | ||
|
||
|
||
renderComments(data) { | ||
if (data && Object.hasOwnProperty.call(data, 'id')) { | ||
if (! data.comments || data.comments.length === 0) return; | ||
const commentsAmount = `Showing ${data.comments.length} ${data.comments.length === 1 ? 'comment' : 'comments'}`; | ||
return ( | ||
<div className="container content"> | ||
{commentsAmount} | ||
{this.renderCommentsCollection(data.comments)} | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
renderCommentsCollection(comments) { | ||
return ( | ||
<ul className="comments__list"> | ||
{comments.map((comment, index) => ( | ||
<li | ||
key={index} | ||
className="comments__listItem" | ||
> | ||
<Comment data={comment} /> | ||
</li> | ||
))} | ||
</ul> | ||
) | ||
} | ||
|
||
renderContents(data) { | ||
let classNames; | ||
if (this.props.isFetching) { | ||
classNames = 'is-fetching'; | ||
} | ||
return ( | ||
<div className={classNames}> | ||
{this.renderStory(data)} | ||
{this.renderComments(data)} | ||
</div> | ||
); | ||
} | ||
|
||
render() { | ||
const { state } = this.props; | ||
return ( | ||
<div className="container"> | ||
{this.renderContents(state)} | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
const mapStateToProps = state => state.data; | ||
|
||
export default connect(mapStateToProps)(Story); |
Oops, something went wrong.