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