initial react app(WIP)

pull/1319/head^2
Berkeley Martinez 2015-06-29 09:50:25 -07:00
parent 05c6dcdf0f
commit a5e7009a57
19 changed files with 46917 additions and 68 deletions

3
.babelrc Normal file
View File

@ -0,0 +1,3 @@
{
"stage": 0
}

View File

@ -2,14 +2,17 @@ import BrowserHistory from 'react-router/lib/BrowserHistory';
import debugFactory from 'debug';
import { Cat } from 'thundercats';
import AppFactory from '../common/app/appFactory';
import app$ from '../common/app/app$.jsx';
const debug = debugFactory('fcc:client');
const DOMContianer = document.getElemenetById('#fCC');
const fcc = new Cat();
// returns an observable
fcc.render(AppFactory(BrowserHistory), DOMContianer)
app$(BrowserHistory)
.flatMap(app => {
return fcc.render(app, DOMContianer);
})
.subscribe(
function() {
debug('react rendered');

25
common/app/app-stream.jsx Normal file
View File

@ -0,0 +1,25 @@
import Rx from 'rx';
import React from 'react';
import { Route, Router } from 'react-router';
// components
import App from './App.jsx';
import Jobs from './routes/Jobs';
import NotFound from './components/NotFound';
const router$ = Rx.Observable.fromNodeCallback(Router.run, Router);
export const routes = (
<Route handler={ App }>
<Route
component={ Jobs }
path='/jobs' />
<Route
component={ NotFound }
path='*' />
</Route>
);
export default function app$(location) {
return router$(routes, location);
}

View File

@ -1,18 +0,0 @@
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

@ -1,6 +1,5 @@
import React from 'react';
import { Nav, Navbar, NavItem } from 'react-bootstrap';
import NavItemFCC from './NavItem.jsx';
export default class extends React.Component {
constructor(props) {
@ -34,12 +33,12 @@ export default class extends React.Component {
);
} else {
return (
<NavItemFCC
aClassName='btn signup-btn signup-btn-nav'
<NavItem
className='btn signup-btn signup-btn-nav'
eventKey={ 2 }
href='/login'>
Sign In
</NavItemFCC>
</NavItem>
);
}
}

View File

@ -1,12 +1,13 @@
var React = require('react/addons');
var joinClasses = require('react-bootstrap/lib/utils/joinClasses');
var classSet = React.addons.classSet;
var BootstrapMixin = require('react-bootstrap').BootstrapMixin;
import React from 'react';
import classnames from 'classnames';
var NavItem = React.createClass({
mixins: [BootstrapMixin],
export default class extends React.Component {
constructor(props) {
super(props);
}
propTypes: {
static displayName = 'NavItem'
static propTypes = {
onSelect: React.PropTypes.func,
active: React.PropTypes.bool,
disabled: React.PropTypes.bool,
@ -14,31 +15,41 @@ var NavItem = React.createClass({
title: React.PropTypes.string,
eventKey: React.PropTypes.any,
target: React.PropTypes.string
},
}
getDefaultProps: function () {
return {
href: '#'
handleClick(e) {
if (this.props.onSelect) {
e.preventDefault();
if (!this.props.disabled) {
this.props.onSelect(
this.props.eventKey,
this.props.href,
this.props.target
);
}
}
}
render() {
const {
disabled,
active,
href,
title,
target,
children,
} = this.props;
const classes = {
'active': active,
'disabled': disabled
};
},
render: function () {
var {
disabled,
active,
href,
title,
target,
children,
} = this.props,
props = this.props,
classes = {
'active': active,
'disabled': disabled
};
return (
<li {...props} className={joinClasses(props.className, classSet(classes))}>
<li
className={ joinClasses(props.className, classSet(classes)) }
{ ...this.props }>
<a
href={href}
title={title}
@ -50,17 +61,5 @@ var NavItem = React.createClass({
</a>
</li>
);
},
handleClick: function (e) {
if (this.props.onSelect) {
e.preventDefault();
if (!this.props.disabled) {
this.props.onSelect(this.props.eventKey, this.props.href, this.props.target);
}
}
}
});
module.exports = NavItem;
}

View File

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

View File

@ -12,7 +12,7 @@ export default {
getComponents(cb) {
require.ensure([], require => {
cb(null, [
require('./components/Jobs')
require('./components/Jobs.jsx')
]);
});
}

View File

@ -12,6 +12,11 @@ var gulp = require('gulp'),
envify = require('envify/custom'),
toVinylWithName = require('vinyl-source-stream'),
// react app
webpack = require('gulp-webpack'),
webpackConfig = require('./webpack.config.js'),
webpackConfigNode = require('./webpack.config.node.js'),
// server process
nodemon = require('gulp-nodemon'),
sync = require('browser-sync'),
@ -41,6 +46,16 @@ var paths = {
clientName: 'lbApp'
},
client: {
src: './client',
dest: 'public/js'
},
node: {
src: './client',
dest: 'server/server'
},
syncWatch: [
'public/**/*.*'
]
@ -83,6 +98,20 @@ gulp.task('loopback', function() {
.pipe(gulp.dest(paths.publicJs));
});
gulp.task('pack-client', function() {
return gulp.src(paths.client.src)
.pipe(webpack(webpackConfig))
.pipe(gulp.dest(paths.client.dest));
});
gulp.task('pack-node', function() {
return gulp.src(paths.node.src)
.pipe(webpack(webpackConfigNode))
.pipe(gulp.dest(paths.node.dest));
});
gulp.task('pack', ['pack-client', 'pack-node']);
gulp.task('serve', function(cb) {
var called = false;
nodemon({

View File

@ -29,10 +29,13 @@
"dependencies": {
"accepts": "~1.2.5",
"async": "~0.9.0",
"babel-core": "^5.6.15",
"babel-loader": "^5.2.2",
"bcrypt-nodejs": "~0.0.3",
"body-parser": "~1.9.3",
"chai-jquery": "~2.0.0",
"cheerio": "~0.18.0",
"classnames": "^2.1.2",
"clockwork": "~0.1.1",
"compression": "~1.2.1",
"connect-mongo": "~0.7.0",
@ -45,16 +48,20 @@
"express": "~4.10.4",
"express-flash": "~0.0.2",
"express-session": "~1.9.2",
"express-state": "^1.2.0",
"express-validator": "~2.8.0",
"fetchr": "^0.4.16",
"font-awesome": "~4.3.0",
"forever": "~0.14.1",
"frameguard": "^0.2.2",
"github-api": "~0.7.0",
"gulp-less": "^3.0.3",
"gulp-minify-css": "~0.5.1",
"gulp-webpack": "^1.5.0",
"helmet": "~0.9.0",
"helmet-csp": "^0.2.3",
"jade": "~1.8.0",
"json-loader": "^0.5.2",
"less": "~1.7.5",
"less-middleware": "~2.0.1",
"lodash": "^3.9.3",
@ -67,6 +74,7 @@
"moment": "~2.10.2",
"mongodb": "^2.0.33",
"morgan": "~1.5.0",
"node-libs-browser": "^0.5.2",
"node-slack": "0.0.7",
"node-uuid": "^1.4.3",
"nodemailer": "~1.3.0",
@ -80,15 +88,17 @@
"pmx": "^0.3.16",
"ramda": "~0.10.0",
"react": "^0.13.3",
"react-bootstrap": "^0.23.4",
"react-bootstrap": "^0.23.5",
"react-router": "^1.0.0-beta1",
"request": "~2.53.0",
"rx": "^2.5.3",
"sanitize-html": "~1.6.1",
"source-map-support": "^0.3.2",
"thundercats": "^2.0.0-rc6",
"twit": "~1.1.20",
"uglify-js": "~2.4.15",
"validator": "~3.22.1",
"webpack": "^1.9.12",
"yui": "~3.18.1"
},
"devDependencies": {

57
server/boot/a-react.js Normal file
View File

@ -0,0 +1,57 @@
// appFactory is an es6 module
var debug = require('debug')('freecc:servereact');
var app$ = require('../common/app/app-stream.jsx').default;
var Cat = require('thundercats').Cat;
var routes = [
'/jobs'
];
module.exports = function(app) {
var router = app.Router();
routes.forEach(function(route) {
router.get(route, serveReactApp);
});
app.use(router);
function serveReactApp(req, res, next) {
var fcc = new Cat();
var decodedUrl = decodeURI(req.path);
// returns a router wrapped app
app$(decodedUrl)
// if react-router does not find a route send down the chain
.filter(function(data) {
var state = data.state;
// this may not work with react-router 1.0.0
var notFound = state.routes.some(route => route.isNotFound);
if (notFound) {
debug('tried to find %s but got 404', state.path);
next();
}
return !notFound;
})
.flatMap(function(app) {
// call thundercats renderToString
// prefetches data and sets up it up for current state
return fcc.renderToString(app);
})
// makes sure we only get one onNext and closes subscription
.firstOrDefault()
.flatMap(function(dats) {
debug('react rendered');
res.expose(dats.data, 'data');
// now render jade file with markup injected from react
return res.render$('layout-react', { markup: dats.markup });
})
.subscribe(
function(markup) {
debug('jade rendered');
res.send(markup);
},
next
);
}
};

View File

@ -22,6 +22,7 @@ var R = require('ramda'),
lessMiddleware = require('less-middleware'),
passportProviders = require('./passport-providers'),
rxMiddleware = require('./utils/rx').rxMiddleware,
/**
* API keys and Passport configuration.
*/
@ -175,19 +176,22 @@ app.use(helmet.csp({
passportConfigurator.init();
// add rx methods to express
app.use(rxMiddleware());
app.use(function(req, res, next) {
// Make user object available in templates.
res.locals.user = req.user;
next();
});
app.use(
loopback.static(path.join(__dirname, '../public'), {
maxAge: 86400000
})
);
// track when connecting to db starts
var startTime = Date.now();
boot(app, {
appRootDir: __dirname,

79
server/server/1.fcc.js Normal file
View File

@ -0,0 +1,79 @@
exports.ids = [1];
exports.modules = {
/***/ 309:
/***/ function(module, exports, __webpack_require__) {
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }
var _react = __webpack_require__(53);
var _react2 = _interopRequireDefault(_react);
var _thundercats = __webpack_require__(22);
var _reactBootstrap = __webpack_require__(233);
var _default = (function (_React$Component) {
var _class = function _default(props) {
_classCallCheck(this, _class2);
_get(Object.getPrototypeOf(_class2.prototype), 'constructor', this).call(this, props);
};
_inherits(_class, _React$Component);
var _class2 = _class;
_createClass(_class2, [{
key: 'render',
value: function render() {
return _react2['default'].createElement(
_reactBootstrap.Grid,
null,
_react2['default'].createElement(
_reactBootstrap.Row,
null,
'foo'
)
);
}
}], [{
key: 'displayName',
value: 'Jobs',
enumerable: true
}, {
key: 'propTypes',
value: {
jobs: _react.PropTypes.array
},
enumerable: true
}]);
_class = (0, _thundercats.createContainer)({
store: 'JobsStore'
})(_class) || _class;
return _class;
})(_react2['default'].Component);
exports['default'] = _default;
module.exports = exports['default'];
/***/ }
};;
//# sourceMappingURL=1.fcc.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["webpack:///./common/app/routes/Jobs/components/Jobs.jsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;kCAAiC,EAAO;;;;wCACR,EAAa;;2CACnB,GAAiB;;;gBAM9B,kBAAC,KAAK,EAAE;;;AACjB,oFAAM,KAAK,EAAE;IACd;;;;;;;;YAQK,kBAAG;AACP,cACE;yBAlBG,IAAI;;SAmBL;2BAnBO,GAAG;;;UAqBJ;QACD,CACP;MACH;;;YAboB,MAAM;;;;YACR;AACjB,WAAI,EAAE,OAfM,SAAS,CAeL,KAAK;MACtB;;;;YAZF,iBAHQ,eAAe,EAGP;AACf,UAAK,EAAE,WAAW;IACnB,CAAC;;IAC2B,mBAAM,SAAS","file":"1.fcc.js","sourcesContent":["import React, { PropTypes } from 'react';\nimport { createContainer } from 'thundercats';\nimport { Grid, Row } from 'react-bootstrap';\n\n@createContainer({\n store: 'JobsStore'\n})\nexport default class extends React.Component {\n constructor(props) {\n super(props);\n }\n\n\n static displayName = 'Jobs'\n static propTypes = {\n jobs: PropTypes.array\n }\n\n render() {\n return (\n <Grid>\n <Row>\n foo\n </Row>\n </Grid>\n );\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./common/app/routes/Jobs/components/Jobs.jsx\n **/"],"sourceRoot":""}

46548
server/server/fcc.js Normal file

File diff suppressed because it is too large Load Diff

1
server/server/fcc.js.map Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,9 @@
doctype html
html(ng-app='profileValidation', lang='en')
head
include partials/universal-head
body.top-and-bottom-margins
.container
include partials/flash
#fcc!= markup
script!= state

32
webpack.config.js Normal file
View File

@ -0,0 +1,32 @@
var path = require('path');
module.exports = {
devtool: 'sourcemap',
entry: './client',
output: {
filename: 'fcc.js',
path: path.join(__dirname, '/public/js'),
publicPath: 'public/'
},
module: {
loaders: [
{
test: /\.jsx?$/,
include: [
path.join(__dirname, 'client/'),
path.join(__dirname, 'common/')
],
loaders: [
'babel-loader'
]
},
{
test: /\.json$/,
loaders: [
'json-loader'
]
}
]
},
plugins: []
};

54
webpack.config.node.js Normal file
View File

@ -0,0 +1,54 @@
var fs = require('fs');
var path = require('path');
var webpack = require('webpack');
var nodeModules = fs.readdirSync('node_modules')
.filter(function(x) {
return ['.bin'].indexOf(x) === -1;
})
.reduce(function(nodeModules, module) {
nodeModules[module] = 'commonjs ' + module;
return nodeModules;
}, {});
module.exports = {
devtool: 'sourcemap',
target: 'node',
entry: './server/appEntry',
// keeps webpack from bundling modules
externals: nodeModules,
output: {
filename: 'fcc.js',
path: path.join(__dirname, '/public/js'),
publicPath: 'public/'
},
module: {
loaders: [
{
test: /\.jsx?$/,
include: [
path.join(__dirname, 'client/'),
path.join(__dirname, 'common/')
],
loaders: [
'babel-loader'
]
},
{
test: /\.json$/,
loaders: [
'json-loader'
]
}
]
},
plugins: [
new webpack.BannerPlugin(
'require("source-map-support").install();',
{
raw: true,
entryOnly: false
}
)
]
};