Changed build process, with auth (login, registration, and couunt) components and containers
This commit is contained in:
2
js-frontend/.gitignore
vendored
2
js-frontend/.gitignore
vendored
@@ -1,4 +1,4 @@
|
||||
node_modules
|
||||
build
|
||||
dist
|
||||
#dist
|
||||
dist-intermediate
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
178
js-frontend/src/App.js
Normal 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>
|
||||
)
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -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
26
js-frontend/src/client.js
Normal 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.");
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
})
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -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)
|
||||
|
||||
19
js-frontend/src/views/Account.js
Normal file
19
js-frontend/src/views/Account.js
Normal 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);
|
||||
18
js-frontend/src/views/SignIn.js
Normal file
18
js-frontend/src/views/SignIn.js
Normal 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);
|
||||
18
js-frontend/src/views/SignUp.js
Normal file
18
js-frontend/src/views/SignUp.js
Normal 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);
|
||||
@@ -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
|
||||
|
||||
20
prebuilt-web-client/index.html
Normal file
20
prebuilt-web-client/index.html
Normal 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>
|
||||
32
prebuilt-web-client/main-5ca0fc07a6a88cee3ec2.js
Normal file
32
prebuilt-web-client/main-5ca0fc07a6a88cee3ec2.js
Normal file
File diff suppressed because one or more lines are too long
1
prebuilt-web-client/style.css
Normal file
1
prebuilt-web-client/style.css
Normal 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}
|
||||
Reference in New Issue
Block a user