add initial react app

This commit is contained in:
Berkeley Martinez
2015-06-17 21:04:28 -07:00
parent bfddc0330f
commit a8540bee35
42 changed files with 299 additions and 244 deletions

3
client/README.md Normal file
View File

@ -0,0 +1,3 @@
This is the entry point for the client
Code that should only run on the client should be put here.
NOTE(berks): For react specific stuff this should be the entry point

20
client/index.js Normal file
View File

@ -0,0 +1,20 @@
import BrowserHistory from 'react-router/lib/BrowserHistory';
import debugFactory from 'debug';
import { Cat } from 'thundercats';
import AppFactory from '../common/app/appFactory';
const debug = debugFactory('fcc:client');
const DOMContianer = document.getElemenetById('#fCC');
const fcc = new Cat();
// returns an observable
fcc.render(AppFactory(BrowserHistory), DOMContianer)
.subscribe(
function() {
debug('react rendered');
},
function(err) {
debug('an error has occured', err.stack);
}
);

25
common/app/App.jsx Normal file
View File

@ -0,0 +1,25 @@
import React, { PropTypes } from 'react';
import Nav from './components/Nav';
import Footer from './components/Footer';
export default class extends React.Component {
constructor(props) {
super(props);
}
static displayName = 'FreeCodeCamp'
static propTypes = {
children: PropTypes.node
}
render() {
return (
<div>
<Nav />
{ this.props.children }
<Footer />
</div>
);
}
}

18
common/app/appFactory.jsx Normal file
View File

@ -0,0 +1,18 @@
import React from 'react';
import { Router, Route } from 'react-router';
// components
import App from './App.jsx';
import Jobs from './screens/App/screens/Jobs';
module.exports = function appFactory(history) {
return (
<Router history={ history }>
<Route handler={ App }>
<Route
component={ Jobs }
path='/jobs' />
</Route>
</Router>
);
};

View File

@ -0,0 +1,50 @@
import React from 'react';
import { Col, Row, Grid } from 'react-bootstrap';
import links from './links.json';
export default class extends React.Component {
static displayName = 'Footer'
renderLinks(mobile) {
return links.map(link => {
return (
<a
className={ link.className}
href={ link.href }
target={ link.target }>
{ this.renderContent(mobile, link.content) }
</a>
);
});
}
renderContent(mobile, content) {
if (mobile) {
return (
<span className='sr-only'>
content;
</span>
);
}
return content;
}
render() {
return (
<Grid className='fcc-footer'>
<Row>
<Col
className='hidden-xs hidden-sm'
xs={ 12 }>
{ this.renderLinks() }
</Col>
<Col
className='visible-xs visible-sm'
xs={ 12 }>
{ this.renderLinks(true) }
</Col>
</Row>
</Grid>
);
}
}

View File

@ -0,0 +1 @@
export { default as Footer } from './Footer.jsx';

View File

@ -0,0 +1,44 @@
[
{
"className": "ion-speakerphone",
"content": "&nbsp;Blog&nbsp;&nbsp;",
"href": "http://blog.freecodecamp.com",
"target": "_blank"
},
{
"className": "ion-social-twitch-outline",
"content": "&nbsp;Twitch&nbsp;&nbsp;",
"href": "http://www.twitch.tv/freecodecamp",
"target": "_blank"
},
{
"className": "ion-social-github",
"content": "&nbsp;Github&nbsp;&nbsp;",
"href": "http://github.com/freecodecamp",
"target": "_blank"
},
{
"className": "ion-social-twitter",
"content": "&nbsp;Twitter&nbsp;&nbsp;",
"href": "http://twitter.com/freecodecamp",
"target": "_blank"
},
{
"className": "ion-social-facebook",
"content": "&nbsp;Facebook&nbsp;&nbsp;",
"href": "http://facebook.com/freecodecamp",
"target": "_blank"
},
{
"className": "ion-information-circled",
"content": "&nbsp;About&nbsp;&nbsp;",
"href": "/learn-to-code",
"target": "_self"
},
{
"className": "ion-locked",
"content": "&nbsp;Privacy&nbsp;&nbsp;",
"href": "/privacy'",
"target": "_self"
}
]

View File

@ -1,31 +1,30 @@
var React = require('react'),
bootStrap = require('react-bootstrap'),
Navbar = bootStrap.Navbar,
Nav = bootStrap.Nav,
NavItem = bootStrap.NavItem,
NavItemFCC = require('./NavItem.jsx');
import React from 'react';
import { Nav, Navbar, NavItem } from 'react-bootstrap';
import NavItemFCC from './NavItem.jsx';
var NavBarComp = React.createClass({
export default class extends React.Component {
constructor(props) {
super(props);
}
propTypes: { signedIn: React.PropTypes.bool },
static displayName = 'Nav'
static propTypes = {
signedIn: React.PropTypes.bool
}
getDefaultProps: function() {
return { signedIn: false };
},
_renderBrand: function() {
renderBrand() {
var fCClogo = 'https://s3.amazonaws.com/freecodecamp/freecodecamp_logo.svg';
return (
<a href='/'>
<img
src={ fCClogo }
alt='learn to code javascript at Free Code Camp logo'
className='img-responsive nav-logo' />
className='img-responsive nav-logo'
src={ fCClogo } />
</a>
);
},
}
_renderSignin: function() {
renderSignin() {
if (this.props.signedIn) {
return (
<NavItem
@ -36,27 +35,26 @@ var NavBarComp = React.createClass({
} else {
return (
<NavItemFCC
aClassName='btn signup-btn signup-btn-nav'
eventKey={ 2 }
href='/login'
aClassName='btn signup-btn signup-btn-nav'>
Sign In
href='/login'>
Sign In
</NavItemFCC>
);
}
},
render: function() {
}
render() {
return (
<Navbar
brand={ this._renderBrand() }
className='nav-height'
fixedTop={ true }
toggleNavKey={ 0 }
className='nav-height'>
toggleNavKey={ 0 }>
<Nav
right={ true }
className='hamburger-dropdown'
eventKey={ 0 }
className='hamburger-dropdown'>
right={ true }>
<NavItem
eventKey={ 1 }
href='/Challenges'>
@ -77,5 +75,4 @@ var NavBarComp = React.createClass({
</Navbar>
);
}
});
module.exports = NavBarComp;
}

View File

@ -0,0 +1 @@
export { default as Nav } from './Nav.jsx';

View File

@ -0,0 +1 @@
things like NavBar and Footer go here

View File

@ -0,0 +1 @@
in case we ever want an admin panel

View File

@ -0,0 +1 @@
This folder contains things relative to the bonfires screens

View File

@ -0,0 +1,6 @@
export default {
path: 'bonfires/(:bonfireName)',
getComponents(cb) {
// TODO(berks): add bonfire component
}
};

View File

@ -0,0 +1 @@
future home of FAVS app

View File

@ -0,0 +1 @@
This folder contains everything relative to Jobs board

View File

@ -0,0 +1,15 @@
import { Actions } from 'thundercats';
export default class JobsActions extends Actions {
constructor() {
super();
}
static displayName = 'JobsActions'
getJob(id) {
return { id };
}
getJobs(params) {
return { params };
}
}

View File

@ -0,0 +1,28 @@
import React, { PropTypes } from 'react';
import { createContainer } from 'thundercats';
import { Grid, Row } from 'react-bootstrap';
@createContainer({
store: 'JobsStore'
})
export default class extends React.Component {
constructor(props) {
super(props);
}
static displayName = 'Jobs'
static propTypes = {
jobs: PropTypes.array
}
render() {
return (
<Grid>
<Row>
foo
</Row>
</Grid>
);
}
}

View File

@ -0,0 +1,13 @@
import React, { PropTypes } from 'react';
export default class extends React.Component {
constructor(props) {
super(props);
}
static displayName = 'JobsList'
static propTypes = {}
render() {
return null;
}
}

View File

@ -0,0 +1,9 @@
import { Store } from 'thundercats';
export default class JobsStore extends Store {
constructor(cat) {
super();
let JobsActions = cat.getActions('JobsActions');
}
static displayName = 'JobsStore'
}

View File

@ -0,0 +1,19 @@
/*
* show: /jobs
* showOne: /jobs/:id
* edit /jobs/:id
* delete /jobs/:id
* createOne /jobs/new
*/
export default {
path: '/jobs/(:jobId)',
getComponents(cb) {
require.ensure([], require => {
cb(null, [
require('./components/Jobs')
]);
});
}
};

View File

@ -0,0 +1,11 @@
export default {
path: '/',
getRoutes(cb) {
require.ensure([], require => {
cb(null, [
// require('./Bonfires'),
require('./Jobs')
]);
});
}
};

View File

@ -0,0 +1 @@
Here is where all components that are shared between multiple views

View File

@ -1,19 +0,0 @@
var React = require('react'),
RouteHandler = require('react-router').RouteHandler,
// ## components
Nav = require('./nav'),
Footer = require('./footer');
var App = React.createClass({
render: function() {
return (
<div>
<Nav />
<RouteHandler />
<Footer />
</div>
);
}
});
module.exports = App;

View File

@ -1,34 +0,0 @@
var React = require('react'),
// react router
Router = require('react-router'),
Route = Router.Route,
// NotFound = Router.NotFoundRoute,
DefaultRoute = Router.DefaultRoute,
// # Components
App = require('./App.jsx'),
Bonfires = require('./bonfires');
var routes = (
<Route
name='app'
path='/'
handler={ App }>
<Route
name='bonfires'
path='/bonfires/?:bonfireName?'
handler={ Bonfires } />
<DefaultRoute
handler={ Bonfires } />
</Route>
);
module.exports = function(Location) {
return Router.create({
routes: routes,
location: Location
});
};

View File

@ -1 +0,0 @@
module.exports = require('./Bonfires.jsx');

View File

@ -1,34 +0,0 @@
var debug = require('debug')('freecc:context'),
BonfireActions = require('../bonfires/Actions'),
BonfireStore = require('../bonfires/Store');
var {
Action,
waitFor
} = require('thundercats');
var actions = Action.createActions([
'setContext',
'renderToUser'
]);
actions
.setContext
.filter(function(ctx) {
return ctx.state.path.indexOf('/bonfire') !== -1;
})
.subscribe(function(ctx) {
debug('set ctx');
BonfireActions.getBonfire(ctx.state.params);
waitFor(BonfireStore)
.firstOrDefault()
.catch(function(err) {
// handle timeout error
debug('err', err);
})
.subscribe(function() {
actions.renderToUser(ctx);
});
});
module.exports = actions;

View File

@ -1,18 +0,0 @@
var Store = require('thundercats').Store,
ContextActions = require('./Actions');
var ContextStore = Store.create({
getInitialValue: function() {
return {};
},
getOperations: function() {
return ContextActions
.renderToUser
.map(function(ctx) {
return { value: ctx };
});
}
});
module.exports = ContextStore;

View File

@ -1,106 +0,0 @@
var React = require('react');
var Footer = React.createClass({
render: function() {
return (
<div className='fcc-footer'>
<div className='col-xs-12 hidden-xs hidden-sm'>
<a
href='http://blog.freecodecamp.com'
target='_blank' className='ion-speakerphone'>
&nbsp;Blog&nbsp;&nbsp;
</a>
<a
ref='http://www.twitch.tv/freecodecamp'
target='_blank' className='ion-social-twitch-outline'>
&nbsp;Twitch&nbsp;&nbsp;
</a>
<a
href='http://github.com/freecodecamp'
target='_blank'
className='ion-social-github'>
&nbsp;Github&nbsp;&nbsp;
</a>
<a
href='http://twitter.com/freecodecamp'
target='_blank' className='ion-social-twitter'>
&nbsp;Twitter&nbsp;&nbsp;
</a>
<a
href='http://facebook.com/freecodecamp'
target='_blank'
className='ion-social-facebook'>
&nbsp;Facebook&nbsp;&nbsp;
</a>
<a
ref='/learn-to-code'
className='ion-information-circled'>
&nbsp;About&nbsp;&nbsp;
</a>
<a
href='/privacy'
className='ion-locked'>
&nbsp;Privacy&nbsp;&nbsp;
</a>
</div>
<div className='col-xs-12 visible-xs visible-sm'>
<a
href='http://blog.freecodecamp.com'
target='_blank' className='ion-speakerphone'>
<span className='sr-only'>
Free Code Camp\'s Blog
</span>
</a>
<a
href='http://www.twitch.tv/freecodecamp'
target='_blank'
className='ion-social-twitch-outline'>
<span className='sr-only'>
Free Code Camp Live Pair Programming on Twitch.tv
</span>
</a>
<a
href='http://github.com/freecodecamp'
target='_blank'
className='ion-social-github'>
<span className='sr-only'>
Free Code Camp on GitHub
</span>
</a>
<a
href='http://twitter.com/freecodecamp'
target='_blank'
className='ion-social-twitter'>
<span className='sr-only'>
Free Code Camp on Twitter
</span>
</a>
<a
href='http://facebook.com/freecodecamp'
target='_blank'
className='ion-social-facebook'>
<span className='sr-only'>
Free Code Camp on Facebook
</span>
</a>
<a
href='/learn-to-code'
className='ion-information-circled'>
<span className='sr-only'>
About Free Code Camp
</span>
</a>
<a
href='/privacy'
className='ion-locked'>
<span className='sr-only'>
Free Code Camp's Privacy Policy
</span>
</a>
</div>
</div>
);
}
});
module.exports = Footer;

View File

@ -1 +0,0 @@
module.exports = require('./Footer.jsx');

View File

@ -1 +0,0 @@
module.exports = require('./Nav.jsx');

View File

@ -72,7 +72,6 @@
"node-uuid": "^1.4.3",
"nodemailer": "~1.3.0",
"passport-facebook": "^2.0.0",
"passport-google-oauth": "^0.2.0",
"passport-google-oauth2": "^0.1.6",
"passport-linkedin-oauth2": "^1.2.1",
"passport-local": "^1.0.0",
@ -80,9 +79,13 @@
"passport-twitter": "^1.0.3",
"pmx": "^0.3.16",
"ramda": "~0.10.0",
"react": "^0.13.3",
"react-bootstrap": "^0.23.4",
"react-router": "^1.0.0-beta1",
"request": "~2.53.0",
"rx": "^2.5.3",
"sanitize-html": "~1.6.1",
"thundercats": "^2.0.0-rc6",
"twit": "~1.1.20",
"uglify-js": "~2.4.15",
"validator": "~3.22.1",