diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3e2e84b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+build/
+node_modules/
diff --git a/app/containers/Application.css b/app/containers/Application.css
new file mode 100644
index 0000000..e69de29
diff --git a/app/containers/Application.jsx b/app/containers/Application.jsx
new file mode 100644
index 0000000..d216b46
--- /dev/null
+++ b/app/containers/Application.jsx
@@ -0,0 +1,13 @@
+import React from "react";
+
+import styles from "./Application.css";
+
+export default class Application extends React.Component {
+ render() {
+ return
+
This is an applidjfcation container
+ { this.props.children }
+
+ }
+}
+
diff --git a/app/containers/Login.css b/app/containers/Login.css
new file mode 100644
index 0000000..e69de29
diff --git a/app/containers/Login.jsx b/app/containers/Login.jsx
new file mode 100644
index 0000000..f399000
--- /dev/null
+++ b/app/containers/Login.jsx
@@ -0,0 +1,12 @@
+import React from "react";
+
+import styles from "./Login.css";
+
+export default class Login extends React.Component {
+ render() {
+ return
+
This is a login component
+
+ }
+}
+
diff --git a/app/redux/store.js b/app/redux/store.js
new file mode 100644
index 0000000..062b137
--- /dev/null
+++ b/app/redux/store.js
@@ -0,0 +1,31 @@
+import { createStore, applyMiddleware, compose } from 'redux';
+
+//TODO: implement middleware for async actions
+// import createMiddleware from './middleware/clientMiddleware';
+
+export default function createApiClientStore(client, data) {
+ const middleware = createMiddleware(client);
+ let finalCreateStore;
+ if (__DEVELOPMENT__ && __CLIENT__ && __DEVTOOLS__) {
+ const { devTools, persistState } = require('redux-devtools');
+ finalCreateStore = compose(
+ applyMiddleware(middleware),
+ devTools(),
+ persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/))
+ )(createStore);
+ } else {
+ finalCreateStore = applyMiddleware(middleware)(createStore);
+ }
+
+ const reducer = require('./modules/reducer');
+ const store = finalCreateStore(reducer, data);
+ store.client = client;
+
+ if (__DEVELOPMENT__ && module.hot) {
+ module.hot.accept('./modules/reducer', () => {
+ store.replaceReducer(require('./modules/reducer'));
+ });
+ }
+
+ return store;
+}
diff --git a/app/route-handlers/Application.jsx b/app/route-handlers/Application.jsx
new file mode 100644
index 0000000..367ae19
--- /dev/null
+++ b/app/route-handlers/Application.jsx
@@ -0,0 +1,7 @@
+import Application from "containers/Application";
+
+//TODO: eventually we will want to connect to store using react-redux;
+// export default connect(mapStateToProps)(Application)
+
+export default Application;
+
diff --git a/app/route-handlers/Login.jsx b/app/route-handlers/Login.jsx
new file mode 100644
index 0000000..5bfe850
--- /dev/null
+++ b/app/route-handlers/Login.jsx
@@ -0,0 +1,6 @@
+import Login from "containers/Login";
+
+//TODO: eventually we will want to connect to store using react-redux;
+// export default connect(mapStateToProps)(Application)
+
+export default Login;
diff --git a/app/routes.jsx b/app/routes.jsx
new file mode 100644
index 0000000..9a5c62a
--- /dev/null
+++ b/app/routes.jsx
@@ -0,0 +1,15 @@
+import React from "react";
+import { Route } from "react-router";
+
+import Application from "route-handlers/Application";
+import Login from "route-handlers/Login";
+
+//TODO: research necessity of Object.assign polyfill
+
+//TODO: switch to es6 export
+
+module.exports = (
+
+
+
+)
diff --git a/config/loadersByExtension.js b/config/loadersByExtension.js
new file mode 100644
index 0000000..a5581ef
--- /dev/null
+++ b/config/loadersByExtension.js
@@ -0,0 +1,28 @@
+function extsToRegExp(exts) {
+ return new RegExp("\\.(" + exts.map(function(ext) {
+ return ext.replace(/\./g, "\\.");
+ }).join("|") + ")(\\?.*)?$");
+}
+
+module.exports = function loadersByExtension(obj) {
+ var loaders = [];
+ Object.keys(obj).forEach(function(key) {
+ var exts = key.split("|");
+ var value = obj[key];
+ var entry = {
+ extensions: exts,
+ test: extsToRegExp(exts)
+ };
+ if(Array.isArray(value)) {
+ entry.loaders = value;
+ } else if(typeof value === "string") {
+ entry.loader = value;
+ } else {
+ Object.keys(value).forEach(function(valueKey) {
+ entry[valueKey] = value[valueKey];
+ });
+ }
+ loaders.push(entry);
+ });
+ return loaders;
+};
diff --git a/config/mainRenderer.jsx b/config/mainRenderer.jsx
new file mode 100644
index 0000000..50fa54d
--- /dev/null
+++ b/config/mainRenderer.jsx
@@ -0,0 +1,13 @@
+
+import React from "react";
+import { Router } from "react-router";
+import routes from "../app/routes";
+
+
+//TODO: will need to wrap in redux provider element
+React.render((
+
+ { routes }
+
+), document.getElementById("content"));
+
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..e6a8728
--- /dev/null
+++ b/index.html
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/make-webpack-config.js b/make-webpack-config.js
new file mode 100644
index 0000000..bc9dc24
--- /dev/null
+++ b/make-webpack-config.js
@@ -0,0 +1,130 @@
+var path = require("path");
+var webpack = require("webpack");
+var ExtractTextPlugin = require("extract-text-webpack-plugin");
+var StatsPlugin = require("stats-webpack-plugin");
+
+
+var loadersByExtension = require("./config/loadersByExtension");
+
+module.exports = function(options) {
+ var entry = {
+ main: "./config/mainRenderer"
+ };
+ var loaders = {
+ "jsx": options.hotComponents ? ["react-hot-loader", "babel-loader?stage=0"] : "babel-loader?stage=0",
+ "js": {
+ loader: "babel-loader?stage=0",
+ include: path.join(__dirname, "app")
+ },
+ "json": "json-loader",
+ "json5": "json5-loader",
+ "txt": "raw-loader",
+ "png|jpg|jpeg|gif|svg": "url-loader?limit=10000",
+ "woff|woff2": "url-loader?limit=100000",
+ "ttf|eot": "file-loader",
+ "wav|mp3": "file-loader",
+ "html": "html-loader",
+ "md|markdown": ["html-loader", "markdown-loader"]
+ };
+ var cssLoader = options.minimize ? "css-loader?module" : "css-loader?module&localIdentName=[path][name]---[local]---[hash:base64:5]";
+ var stylesheetLoaders = {
+ "css": cssLoader,
+ "less": [cssLoader, "less-loader"],
+ "styl": [cssLoader, "stylus-loader"],
+ "scss|sass": [cssLoader, "sass-loader"]
+ };
+ var additionalLoaders = [
+ // { test: /some-reg-exp$/, loader: "any-loader" }
+ ];
+
+ var modulesDirectories = [ "node_modules" ];
+ var extensions = ["", ".web.js", ".js", ".jsx"];
+
+ var root = path.join(__dirname, "app");
+ var publicPath = options.devServer ?
+ "http://localhost:2992/_assets/" :
+ "/_assets/";
+ var output = {
+ path: path.join(__dirname, "build", "public"),
+ publicPath: publicPath,
+ filename: "[name].js" + (options.longTermCaching ? "?[chunkhash]" : ""),
+ chunkFilename: (options.devServer ? "[id].js" : "[name].js") + (options.longTermCaching ? "?[chunkhash]" : ""),
+ sourceMapFilename: "debugging/[file].map",
+ pathinfo: options.debug
+ };
+
+ var excludeFromStats = [
+ /node_modules[\\\/]react(-router)?[\\\/]/
+ ];
+
+ var plugins = [
+ new webpack.PrefetchPlugin("react"),
+ new webpack.PrefetchPlugin("react/lib/ReactComponentBrowserEnvironment"),
+ new StatsPlugin(path.join(__dirname, "build", "stats.json"), {
+ chunkModules: true,
+ exclude: excludeFromStats
+ })
+ ];
+
+ if (options.commonsChunk) {
+ //TODO: investigate necesit of this, do i need commons entry?
+ plugins.push(new webpack.optimize.CommonsChunkPlugin(
+ "commons", "commons.js" + (options.longTermCaching ? "?[chunkhash]" : "")));
+ }
+
+ Object.keys(stylesheetLoaders).forEach(function(ext) {
+ var stylesheetLoader = stylesheetLoaders[ext];
+ if(Array.isArray(stylesheetLoader)) stylesheetLoader = stylesheetLoader.join("!");
+ if(options.separateStylesheet) {
+ stylesheetLoaders[ext] = ExtractTextPlugin.extract("style-loader", stylesheetLoader);
+ } else {
+ stylesheetLoaders[ext] = "style-loader!" + stylesheetLoader;
+ }
+ });
+
+ if(options.separateStylesheet) {
+ plugins.push(new ExtractTextPlugin("[name].css" + (options.longTermCaching ? "?[contenthash]" : "")));
+ }
+
+ //TODO this doesn't seem to be minfiying
+ if(options.minimize) {
+ plugins.push(
+ new webpack.optimize.UglifyJsPlugin({
+ compressor: {
+ warnings: false
+ }
+ }),
+ new webpack.optimize.DedupePlugin(),
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: JSON.stringify("production")
+ }
+ }),
+ new webpack.NoErrorsPlugin()
+ );
+ }
+
+ return {
+ entry: entry,
+ output: output,
+ module: {
+ loaders: loadersByExtension(loaders).concat(loadersByExtension(stylesheetLoaders)).concat(additionalLoaders)
+ },
+ debug: options.debug,
+ resolveLoader: {
+ root: path.join(__dirname, "node_modules")
+ },
+ resolve: {
+ root: root,
+ modulesDirectories: modulesDirectories,
+ extensions: extensions
+ },
+ plugins: plugins,
+ devServer: {
+ stats: {
+ cached: false,
+ exclude: excludeFromStats
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..6fde38c
--- /dev/null
+++ b/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "console",
+ "version": "0.0.0",
+ "description": "Coroner web client.",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "dev-server": "webpack-dev-server --config webpack-dev-server.config.js --progress --colors --port 2992 --inline",
+ "hot-dev-server": "webpack-dev-server --config webpack-hot-dev-server.config.js --hot --progress --colors --port 2992 --inline",
+ "build": "webpack --config webpack-production.config.js --progress --profile --colors"
+ },
+ "author": "Matt Marcelo",
+ "license": "ISC",
+ "dependencies": {
+ "babel-core": "^5.8.25",
+ "babel-loader": "^5.3.2",
+ "css-loader": "^0.19.0",
+ "extract-text-webpack-plugin": "^0.8.2",
+ "file-loader": "^0.8.4",
+ "html-loader": "^0.3.0",
+ "json-loader": "^0.5.3",
+ "json5": "^0.4.0",
+ "json5-loader": "^0.6.0",
+ "less": "^2.5.1",
+ "less-loader": "^2.2.1",
+ "markdown-loader": "^0.1.7",
+ "node-sass": "^3.3.3",
+ "raw-loader": "^0.5.1",
+ "react": "^0.13.3",
+ "react-hot-loader": "^1.3.0",
+ "react-router": "^1.0.0-rc1",
+ "redux": "^3.0.0",
+ "sass-loader": "^2.0.1",
+ "stats-webpack-plugin": "^0.2.1",
+ "style-loader": "^0.12.4",
+ "stylus-loader": "^1.3.0",
+ "url-loader": "^0.5.6",
+ "webpack": "^1.12.2"
+ }
+}
diff --git a/webpack-dev-server.config.js b/webpack-dev-server.config.js
new file mode 100644
index 0000000..229489d
--- /dev/null
+++ b/webpack-dev-server.config.js
@@ -0,0 +1,4 @@
+module.exports = require("./make-webpack-config")({
+ devServer: true,
+ debug: true
+})
diff --git a/webpack-production.config.js b/webpack-production.config.js
new file mode 100644
index 0000000..b253a81
--- /dev/null
+++ b/webpack-production.config.js
@@ -0,0 +1,5 @@
+module.exports = require("./make-webpack-config")({
+ longTermCaching: true,
+ seperateStylesheet: true,
+ minimize: true
+})