Changed build process, with auth (login, registration, and couunt) components and containers

This commit is contained in:
Andrew Revinsky (DART)
2016-02-12 21:59:24 +03:00
parent 7f1f2af188
commit bfd04ef726
16 changed files with 346 additions and 13 deletions

View File

@@ -1,4 +1,4 @@
node_modules
build
dist
#dist
dist-intermediate

View File

@@ -20,9 +20,12 @@ gulp.task('dist', () => runSequence('dist:clean', 'dist:build', 'dist:index'));
gulp.task('clean', ['dist:clean', 'serve:clean']);
gulp.task('open', () => open('http://localhost:3000'));
gulp.task('export', () => runSequence('dist:clean', 'dist:build', 'dist:index', 'export:clean', 'export:copy'));
// Remove all built files
gulp.task('serve:clean', cb => del('build', {dot: true}, cb));
gulp.task('dist:clean', cb => del(['dist', 'dist-intermediate'], {dot: true}, cb));
gulp.task('export:clean', cb => del(['../prebuilt-web-client/**'], {dot: true, force: true}, cb));
// Copy static files across to our final directory
gulp.task('serve:static', () =>
@@ -42,6 +45,11 @@ gulp.task('dist:static', () =>
.pipe($.size({title: 'static'}))
);
gulp.task('export:copy', () => {
return gulp.src(['dist/**'])
.pipe(gulp.dest('../prebuilt-web-client'));
});
// Copy our index file and inject css/script imports for this build
gulp.task('serve:index', () => {
return gulp
@@ -73,7 +81,8 @@ gulp.task('serve:start', ['serve:static'], () => {
return new WebpackDevServer(webpack(config), {
contentBase: 'build',
publicPath: config.output.publicPath,
watchDelay: 100
watchDelay: 100,
historyApiFallback: true
})
.listen(PORT, '0.0.0.0', (err) => {
if (err) throw new $.util.PluginError('webpack-dev-server', err);

View File

@@ -32,7 +32,7 @@
"gulp-load-plugins": "^0.10.0",
"gulp-size": "^1.2.1",
"gulp-util": "^3.0.5",
"json-loader": "^0.5.3",
"json-loader": "^0.5.4",
"less": "^2.5.3",
"less-loader": "^2.2.0",
"node-libs-browser": "^0.5.2",
@@ -47,15 +47,21 @@
"dependencies": {
"babel-polyfill": "6.1.4",
"babel-runtime": "6.0.14",
"history": "1.17.0",
"invariant": "^2.1.1",
"object-pick": "^0.1.1",
"react": "^0.14.0",
"react": "^0.14.7",
"react-bootstrap": "^0.28.3",
"react-dom": "^0.14.0",
"react-pacomo": "^0.5.1",
"react-redux": "^4.4.0",
"react-router": "^1.0.3",
"redux": "^3.0.2",
"redux-auth": "0.0.2",
"redux-batched-subscribe": "^0.1.4",
"redux-multi": "^0.1.9",
"redux-thunk": "^1.0.0",
"redux-router": "^1.0.0-beta7",
"redux-thunk": "^1.0.3",
"uniloc": "^0.2.0"
}
}

178
js-frontend/src/App.js Normal file
View File

@@ -0,0 +1,178 @@
/**
* Created by andrew on 12/02/16.
*/
import { AuthGlobals } from "redux-auth/bootstrap-theme";
import React from "react";
import { Provider} from "react-redux";
import { ReduxRouter} from "redux-router";
import { Route, IndexRoute} from "react-router";
import { configure, authStateReducer} from "redux-auth";
import { createStore, compose, applyMiddleware} from "redux";
import { createHistory, createMemoryHistory} from "history";
import { routerStateReducer, reduxReactRouter as clientRouter} from "redux-router";
import { reduxReactRouter as serverRouter } from "redux-router/server";
import { combineReducers} from "redux";
import thunk from "redux-thunk";
//import demoButtons from "./reducers/request-test-buttons";
//import demoUi from "./reducers/demo-ui";
//import Container from "./views/partials/Container";
//import Main from "./views/Main";
import Account from "./views/Account";
import SignIn from "./views/SignIn";
import SignUp from "./views/SignUp";
//import GlobalComponents from "./views/partials/GlobalComponents";
// TODO: !!!!
class App extends React.Component {
render() {
return (
<Container>
<GlobalComponents />
<AuthGlobals />
{this.props.children}
</Container>
);
}
}
class Main extends React.Component {
render() {
return (
<div className="well">
Component: Main <br/>
{this.props.children}
</div>
);
}
}
class GlobalComponents extends React.Component {
render() {
return (
<div className="well">
Component: GlobalComponents <br/>
{this.props.children}
</div>
);
}
}
class Container extends React.Component {
render() {
return (
<div className="well">
Component: Container <br/>
{this.props.children}
</div>
);
}
}
export function initialize({cookies, isServer, currentLocation, userAgent} = {}) {
const reducer = combineReducers({
auth: authStateReducer,
router: routerStateReducer
//demoButtons,
//demoUi
});
let store;
// access control method, used above in the "account" route
const requireAuth = (nextState, transition, cb) => {
// the setTimeout is necessary because of this bug:
// https://github.com/rackt/redux-router/pull/62
// this will result in a bunch of warnings, but it doesn't seem to be a serious problem
setTimeout(() => {
debugger;
if (!store.getState().auth.getIn(["user", "isSignedIn"])) {
transition(null, "/login");
}
cb();
}, 0);
};
// define app routes
const routes = (
<Route path="/" component={App}>
<IndexRoute component={Main} />
<Route path="login" component={SignIn} />
<Route path="register" component={SignUp} />
<Route path="account" component={Account} onEnter={requireAuth} />
</Route>
);
// these methods will differ from server to client
var reduxReactRouter = clientRouter;
var createHistoryMethod = createHistory;
if (isServer) {
reduxReactRouter = serverRouter;
createHistoryMethod = createMemoryHistory;
}
// create the redux store
store = compose(
applyMiddleware(thunk),
reduxReactRouter({
createHistory: createHistoryMethod,
routes
})
)(createStore)(reducer);
/**
* The React Router 1.0 routes for both the server and the client.
*/
return store.dispatch(configure([
{
default: {
//apiUrl: __API_URL__
apiUrl: '/api'
}
}, {
evilUser: {
//apiUrl: __API_URL__,
apiUrl: '/api',
signOutPath: "/mangs/sign_out",
emailSignInPath: "/mangs/sign_in",
emailRegistrationPath: "/mangs",
accountUpdatePath: "/mangs",
accountDeletePath: "/mangs",
passwordResetPath: "/mangs/password",
passwordUpdatePath: "/mangs/password",
tokenValidationPath: "/mangs/validate_token",
authProviderPaths: {
github: "/mangs/github",
facebook: "/mangs/facebook",
google: "/mangs/google_oauth2"
}
}
}
], {
cookies,
isServer,
currentLocation
})).then(({redirectPath, blank} = {}) => {
// hack for material-ui server-side rendering.
// see https://github.com/callemall/material-ui/pull/2007
if (userAgent) {
global.navigator = {userAgent};
}
return ({
blank,
store,
redirectPath,
provider: (
<Provider store={store} key="provider">
<ReduxRouter children={routes} />
</Provider>
)
});
});
}

View File

@@ -1,6 +1,6 @@
import React from 'react'
import ReactDOM from 'react-dom'
import Application from '../Application'
import Application from '../App'
// Store a reference to our application's root DOM node to prevent repeating

26
js-frontend/src/client.js Normal file
View File

@@ -0,0 +1,26 @@
/**
* Created by andrew on 12/02/16.
*/
import React from "react";
import ReactDOM from "react-dom";
import { initialize } from "./app";
/**
* Fire-up React Router.
*/
const reactRoot = window.document.getElementById("react-app");
initialize().then(({ provider }) => {
ReactDOM.render(provider, reactRoot);
});
/**
* Detect whether the server-side render has been discarded due to an invalid checksum.
*/
if (process.env.NODE_ENV !== "production") {
if (!reactRoot.firstChild || !reactRoot.firstChild.attributes ||
!reactRoot.firstChild.attributes["data-react-checksum"]) {
console.error("Server-side React render was discarded. Make sure that your initial render does not contain any client-side code.");
}
}

View File

@@ -2,6 +2,6 @@ import uniloc from 'uniloc'
export default uniloc({
root: 'GET /',
documentList: 'GET /documents',
documentEdit: 'GET /documents/:id',
login: 'GET /login',
register: 'GET /register',
})

View File

@@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Unicorn Standard Boilerplate</title>
<title>Money Transfer App</title>
<!-- inject:app:css -->
<!-- endinject -->

View File

@@ -11,14 +11,14 @@ import rootReducer from './reducers'
// Add middleware to allow our action creators to return functions and arrays
const createStoreWithMiddleware = applyMiddleware(
reduxThunk,
reduxMulti,
)(createStore)
reduxMulti
)(createStore);
// Ensure our listeners are only called once, even when one of the above
// middleware call the underlying store's `dispatch` multiple times
const createStoreWithBatching = batchedSubscribe(
fn => fn()
)(createStoreWithMiddleware)
)(createStoreWithMiddleware);
// Create a store with our application reducer
const store = createStoreWithBatching(rootReducer)

View File

@@ -0,0 +1,19 @@
/**
* Created by andrew on 12/02/16.
*/
import React from "react";
import { PageHeader } from "react-bootstrap";
import { connect } from "react-redux";
export class Account extends React.Component {
render () {
return (
<div>
<PageHeader>Account page</PageHeader>
<p>This page should only visible to authenticated users.</p>
</div>
);
}
}
export default connect(({auth}) => ({auth}))(Account);

View File

@@ -0,0 +1,18 @@
/**
* Created by andrew on 12/02/16.
*/
import React from "react";
import { PageHeader } from "react-bootstrap";
import { connect } from "react-redux";
export class SignIn extends React.Component {
render () {
return (
<div>
<PageHeader>Sign In First</PageHeader>
<p>Unauthenticated users can't access the account page.</p>
</div>
);
}
}
export default connect(({routes}) => ({routes}))(SignIn);

View File

@@ -0,0 +1,18 @@
/**
* Created by andrew on 12/02/16.
*/
import React from "react";
import { PageHeader } from "react-bootstrap";
import { connect } from "react-redux";
export class SignUp extends React.Component {
render () {
return (
<div>
<PageHeader>Sign Up Page</PageHeader>
<p>Here you can register.</p>
</div>
);
}
}
export default connect(({routes}) => ({routes}))(SignUp);

View File

@@ -9,7 +9,7 @@ export default (DEBUG, PATH, PORT=3000) => ({
] : []).concat([
'./src/main.less',
'babel-polyfill',
'./src/main',
'./src/client',
]),
output: {
@@ -38,6 +38,12 @@ export default (DEBUG, PATH, PORT=3000) => ({
}
},
//json
{
test: /\.json$/,
loader: 'json-loader'
},
// Load styles
{ test: /\.less$/,
loader: DEBUG

View File

@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Money Transfer App</title>
<!-- inject:app:css -->
<link rel="stylesheet" href="/style.css">
<!-- endinject -->
</head>
<body>
<div id="react-app"></div>
<!-- inject:app:js -->
<script src="/main-5ca0fc07a6a88cee3ec2.js"></script>
<!-- endinject -->
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
@import url(http://fonts.googleapis.com/css?family=Roboto:300,400,500);*,:after,:before{box-sizing:border-box}#react-app,body,html,main{position:relative;height:100%;min-height:100%}*{margin:0}body,html,main{font-family:Roboto}body{-webkit-tap-highlight-color:transparent}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}.app-ApplicationLayout{position:relative;height:100%}.app-ApplicationLayout-navbar{position:fixed;left:0;top:0;bottom:0;width:192px;border-right:1px solid #000;z-index:2}.app-ApplicationLayout-content{position:relative;padding-left:192px;width:100%;height:100%}.app-ApplicationLayout-link-active{font-weight:700}.app-DocumentForm{width:100%;padding:5px}.app-DocumentForm-errors{list-style:none;padding:0;margin:0}.app-DocumentForm-error{color:red;margin-bottom:5px}.app-DocumentForm-content,.app-DocumentForm-title{display:block;width:100%;margin-bottom:5px}.app-DocumentForm-cancel{margin-right:5px}.app-OneOrTwoColumnLayout{position:relative;height:100%;z-index:1}.app-OneOrTwoColumnLayout-left{position:absolute;left:0;width:50%;height:100%;overflow:hidden}.app-OneOrTwoColumnLayout-right{position:absolute;right:0;width:50%;height:100%;overflow:hidden}.app-OneOrTwoColumnLayout-right-open{border-left:1px solid #000}.app-DocumentList,.app-DocumentList-query{width:100%}.app-DocumentList-header{width:100%;padding:5px}.app-DocumentList-list{list-style:none;margin:0;padding:0}.app-DocumentList-add-item-active,.app-DocumentList-document-item-active{background-color:#f0f0f0}.app-DocumentList-add-link,.app-DocumentList-document-link{display:block;padding:5px}.app-DocumentList-add-link:hover,.app-DocumentList-document-link:hover{background-color:#f8f8f8}