Permalink
Browse files

React

The commit includes components from the old django based application.
The API calls are stubbed out for the moment.
  • Loading branch information...
edsu committed May 26, 2017
1 parent 2c1d8ad commit bd66e7cefcb3da90ce7a7c859bd9bb0183485a07
View
@@ -1,3 +1,3 @@
{
"presets": ["env"]
"presets": ["env", "react"]
}
View
@@ -80,7 +80,6 @@
"eqeqeq": 2, // http://eslint.org/docs/rules/eqeqeq
"guard-for-in": 2, // http://eslint.org/docs/rules/guard-for-in
"no-caller": 2, // http://eslint.org/docs/rules/no-caller
"no-else-return": 2, // http://eslint.org/docs/rules/no-else-return
"no-eq-null": 2, // http://eslint.org/docs/rules/no-eq-null
"no-eval": 2, // http://eslint.org/docs/rules/no-eval
"no-extend-native": 2, // http://eslint.org/docs/rules/no-extend-native
View
@@ -1,3 +1,2 @@
dist
node_modules
server
View
@@ -1,16 +1,15 @@
{
"scripts": {
"postinstall": "npm run build",
"prestart": "eslint src/server/app.js",
"start": "babel-watch src/server/app.js",
"build:server": "babel src/server/app.js --out-file server.js",
"build:client": "NODE_ENV=production webpack --optimize-minimize --config webpack.prod.config.js --progress",
"prestart": "eslint src",
"start": "nodemon server.js --ignore src/client",
"build:client": "webpack --optimize-minimize --config webpack.prod.config.js --progress",
"build": "better-npm-run build",
"clean": "rimraf dist/*"
},
"betterScripts": {
"build": {
"command": "npm run clean && npm run build:server && npm run build:client",
"command": "npm run clean && npm run build:client",
"env": {
"NODE_ENV": "production"
}
@@ -24,14 +23,16 @@
"babel-eslint": "^7.2.3",
"babel-loader": "^7.0.0",
"babel-preset-env": "^1.4.0",
"babel-watch": "^2.0.6",
"babel-preset-react": "^6.24.1",
"better-npm-run": "0.0.15",
"css-loader": "^0.28.1",
"eslint": "^3.19.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-react": "^7.0.1",
"file-loader": "^0.11.1",
"nodemon": "^1.11.0",
"style-loader": "^0.17.0",
"url-loader": "^0.5.8",
"webpack": "^2.5.1",
"webpack-dev-middleware": "^1.10.2",
"webpack-hot-middleware": "^2.18.0"
View
@@ -0,0 +1,38 @@
#!/usr/bin/env node
require('babel-register')()
const path = require('path')
const webpack = require('webpack')
const express = require('express')
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpackHotMiddleware = require('webpack-hot-middleware')
const api = require('./src/server/api')
const config = require('./webpack.dev.config.js')
const distDir = path.join(__dirname, 'dist')
const htmlFile = path.join(distDir, 'index.html')
const isDevelopment = process.env.NODE_ENV !== 'production'
const defaultPort = 3000
const compiler = webpack(config)
app = express()
app.set('port', process.env.PORT || defaultPort)
if (isDevelopment) {
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
}))
app.use(webpackHotMiddleware(compiler))
app.get('/', (req, res) => {
res.write(compiler.outputFileSystem.readFileSync(htmlFile))
})
} else {
app.get('/', (req, res) => res.sendFile(path.join(distDir, 'index.html')))
app.use(express.static(distDir))
}
app.use('/api/v1', api)
app.listen(app.get('port'))
@@ -0,0 +1,5 @@
body {
margin: 0px;
font-family: "Helvetica Neue",Helvetica,Arial;
font-size: 18pt;
}
@@ -0,0 +1,16 @@
import React, { Component } from 'react'
import Header from './Header'
import Trends from './Trends'
import './App.css'
export default class App extends Component {
render() {
return (
<div>
<Header/>
<Trends/>
</div>
)
}
}
@@ -0,0 +1,22 @@
.Header {
display: flex;
flex-direction: row;
background-color: #eee;
padding-left: 10px;
}
.Logo img {
vertical-align: bottom;
}
.Login {
font-size: 18pt;
margin-left: auto;
line-height: 50px;
padding-right: 10px;
}
.Avatar {
height: 55px;
vertical-align: middle;
}
@@ -0,0 +1,17 @@
import React, { Component } from 'react'
import styles from './Header.css'
import dn from '../images/dn.png'
import Login from './Login'
export default class Header extends Component {
render() {
return (
<header className={styles.Header}>
<div className={styles.Logo}><a href="/">
<img className={styles.Avatar} src={ dn } /></a>
</div>
<div className={styles.Login}><Login /></div>
</header>
)
}
}
@@ -0,0 +1,41 @@
import React, { Component } from 'react'
export default class Login extends Component {
constructor() {
super()
this.state = {user: null, loaded: false}
}
componentWillMount() {
this.getUser()
}
getUser() {
fetch('/api/v1/user', {credentials: 'include'})
.then(resp => resp.json())
.then(result => {
this.setState({user: result, loaded: true})
})
}
render() {
if (! this.state.loaded) {
return null
} else if (this.state.user.username) {
return (
<div>
<img title={ this.state.username } id="avatar" src={ this.state.user.twitter_avatar_url } /> &nbsp; <a href="/accounts/logout">Logout</a>
</div>
)
} else {
return (
<div>
<a href="/accounts/login/">Login</a> &nbsp; <a href="/accounts/signup/">Signup</a>
</div>
)
}
}
}
@@ -0,0 +1,40 @@
.Place {
margin: 10px;
border: thin solid #eee;
}
.Place h3 {
text-align: center;
}
.Place hr {
width: 60%;
}
.Place ul {
margin-left: auto;
margin-right: auto;
text-align: center;
padding: 0;
list-style-type: none;
}
.Place li {
display: inline block;
padding: 3px;
}
/* Medium screens */
@media all and (min-width: 600px) {
.Place {
width: 30%;
font-size: 14pt;
}
}
/* Large screens */
@media all and (min-width: 800px) {
.Place {
font-size: 16pt;
}
}
@@ -0,0 +1,32 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import FlipMove from 'react-flip-move'
import styles from './Place.css'
export default class Place extends Component {
render() {
const trends = this.props.trends.slice(0, 10).map(trend =>
<li key={ trend.name + trend.text }>{ trend.text } [{ trend.tweets }]</li>
)
return (
<div className={styles.Place}>
<h3>{ this.props.name }</h3>
<hr />
<ul>
<FlipMove
duration={2000}
enterAnimation="elevator"
leaveAnimation="fade">
{ trends }
</FlipMove>
</ul>
</div>
)
}
}
Place.propTypes = {
trends: PropTypes.array,
name: PropTypes.string
}
@@ -0,0 +1,15 @@
.Trends {
display: flex 100%;
margin-left: auto;
margin-right: auto;
align-items: center;
justify-content: center;
}
/* Medium screens */
@media all and (min-width: 600px) {
.Trends {
display: flex;
flex-direction: row;
}
}
@@ -0,0 +1,39 @@
import React, { Component } from 'react'
import Place from './Place'
import '../images/dn.png'
import styles from './Trends.css'
export default class Trends extends Component {
constructor() {
super()
this.state = {places: []}
this.getTrends = this.getTrends.bind(this)
}
componentDidMount() {
this.getTrends()
const that = this
setInterval(that.getTrends, 5000)
}
getTrends() {
fetch('/api/v1/trends')
.then(resp => resp.json())
.then(result => {
this.setState({places: result.places})
})
}
render() {
return (
<div className={styles.Trends}>
{this.state.places.map(place =>
<Place key={place.name} trends={place.trends} name={place.name} />
)}
</div>
)
}
}
View
Binary file not shown.
View
@@ -5,7 +5,7 @@
<title>App</title>
</head>
<body>
<div id="hello"></div>
<div id="app"></div>
</body>
</html>
View
@@ -1,10 +1,9 @@
import style from './style.css'
const hello = document.getElementById('hello')
hello.innerHTML = 'Hello World!'
console.log(style)
import React from 'react'
import ReactDOM from 'react-dom'
import App from './components/App'
if (module.hot) {
module.hot.accept()
}
ReactDOM.render(<App/>, document.getElementById('app'))
View

This file was deleted.

Oops, something went wrong.
Oops, something went wrong.

0 comments on commit bd66e7c

Please sign in to comment.