From 109ad432bbf69694dc82b822c4d36f8345a4297d Mon Sep 17 00:00:00 2001 From: Eric Hulburd Date: Mon, 8 Feb 2016 18:23:40 -0600 Subject: [PATCH] make production build --- .gitignore | 3 +- client/app.js | 10 + client/dashboard/base.component.js | 1 - client/dashboard/campaign_orders.component.js | 1 - .../dashboard/energy_time_series.component.js | 1 - client/dashboard/layout/layout.js | 25 + client/dashboard/layout/layout.rt | 6 + client/dashboard/layout/layout.rt.js | 5 + client/dashboard/layout/layout.scss | 9 + .../dashboard/power_time_series.component.js | 51 - ...duction_radiation_time_series.component.js | 1 - client/dashboard/readme.md | 6 - client/react/app.js | 15 - client/style.js | 7 + gulpfile.babel.js | 33 + package.json | 11 +- server/app.express.js | 116 +- server/assets/css/application.scss.css | 0 server/assets/css/vendor.scss.css | 3 - server/assets/js/vendor.js | 3 - server/config/database.js | 1 - server/config/graphql/node.js | 19 - server/config/graphql/schema.graphql | 27 - server/config/graphql/schema.js | 27 - server/config/graphql/schema.json | 1176 ----------------- server/config/react_templates.js | 5 + server/config/webpack/design.js | 1 + server/config/webpack/development.js | 41 + server/config/webpack/production.js | 55 + server/lib/tasks/react_template_compile.js | 58 + server/public/favicon.ico | Bin 0 -> 1150 bytes 31 files changed, 330 insertions(+), 1387 deletions(-) create mode 100644 client/app.js delete mode 100644 client/dashboard/base.component.js delete mode 100644 client/dashboard/campaign_orders.component.js delete mode 100644 client/dashboard/energy_time_series.component.js create mode 100644 client/dashboard/layout/layout.js create mode 100644 client/dashboard/layout/layout.rt create mode 100644 client/dashboard/layout/layout.rt.js create mode 100644 client/dashboard/layout/layout.scss delete mode 100644 client/dashboard/power_time_series.component.js delete mode 100644 client/dashboard/production_radiation_time_series.component.js delete mode 100644 client/dashboard/readme.md delete mode 100644 client/react/app.js create mode 100644 client/style.js delete mode 100644 server/assets/css/application.scss.css delete mode 100644 server/assets/css/vendor.scss.css delete mode 100644 server/assets/js/vendor.js delete mode 100644 server/config/graphql/node.js delete mode 100644 server/config/graphql/schema.graphql delete mode 100644 server/config/graphql/schema.js delete mode 100644 server/config/graphql/schema.json create mode 100644 server/config/react_templates.js create mode 100644 server/config/webpack/design.js create mode 100644 server/config/webpack/development.js create mode 100644 server/config/webpack/production.js create mode 100644 server/lib/tasks/react_template_compile.js create mode 100644 server/public/favicon.ico diff --git a/.gitignore b/.gitignore index 204ade5..cbfb805 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ -bin/ +server/bin/ +client/build/ diff --git a/client/app.js b/client/app.js new file mode 100644 index 0000000..2b52233 --- /dev/null +++ b/client/app.js @@ -0,0 +1,10 @@ +import 'babel-polyfill'; + +import React from 'react'; +import ReactDOM from 'react-dom'; +import Layout from './dashboard/layout/layout'; + +ReactDOM.render( + React.createElement(Layout), + document.getElementById('root') +); diff --git a/client/dashboard/base.component.js b/client/dashboard/base.component.js deleted file mode 100644 index 59bd4a1..0000000 --- a/client/dashboard/base.component.js +++ /dev/null @@ -1 +0,0 @@ -base.widget.js diff --git a/client/dashboard/campaign_orders.component.js b/client/dashboard/campaign_orders.component.js deleted file mode 100644 index fc2ad59..0000000 --- a/client/dashboard/campaign_orders.component.js +++ /dev/null @@ -1 +0,0 @@ -campaign_orders.widget.js diff --git a/client/dashboard/energy_time_series.component.js b/client/dashboard/energy_time_series.component.js deleted file mode 100644 index 0af9d3c..0000000 --- a/client/dashboard/energy_time_series.component.js +++ /dev/null @@ -1 +0,0 @@ -energy_time_series.widget.js diff --git a/client/dashboard/layout/layout.js b/client/dashboard/layout/layout.js new file mode 100644 index 0000000..9aa2d94 --- /dev/null +++ b/client/dashboard/layout/layout.js @@ -0,0 +1,25 @@ +import layoutRt from './layout.rt.js'; + +var Layout = React.createClass({ + getInitialState: function() { + }, + + handleResize: function(e) { + this.setState({windowWidth: window.innerWidth}); + }, + + componentDidMount: function() { + window.addEventListener('resize', this.handleResize); + }, + + setView: function(event) { + var layout = this; + layout.setState({view: event.target.value}); + }, + + render: function() { + return layoutRt.bind(this); + } +}); + +export default Layout; diff --git a/client/dashboard/layout/layout.rt b/client/dashboard/layout/layout.rt new file mode 100644 index 0000000..c7bba6a --- /dev/null +++ b/client/dashboard/layout/layout.rt @@ -0,0 +1,6 @@ +
+ +
diff --git a/client/dashboard/layout/layout.rt.js b/client/dashboard/layout/layout.rt.js new file mode 100644 index 0000000..e3d2e54 --- /dev/null +++ b/client/dashboard/layout/layout.rt.js @@ -0,0 +1,5 @@ +import React from 'react/addons'; +import _ from 'lodash'; +export default function () { + return React.createElement('div', {}, React.createElement('select', { 'onChange': this.setView }, React.createElement('option', { 'value': 'savings' }, 'Savings'), React.createElement('option', { 'value': 'production' }, 'Production'))); +}; \ No newline at end of file diff --git a/client/dashboard/layout/layout.scss b/client/dashboard/layout/layout.scss new file mode 100644 index 0000000..ec5b920 --- /dev/null +++ b/client/dashboard/layout/layout.scss @@ -0,0 +1,9 @@ +#layout { + h1 { + color: red; + } +} +// needless comment +#yada { + div { padding: 200px; } +} diff --git a/client/dashboard/power_time_series.component.js b/client/dashboard/power_time_series.component.js deleted file mode 100644 index d0f94ff..0000000 --- a/client/dashboard/power_time_series.component.js +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react'; -import Relay from 'react-relay'; - -class PowerTimeSeries extends React.Component { - - get timeframes(){ - return [ - {display: "Today", value: 'today'}, - {display: "1 week", value: 'week'}, - {display: "1 month", value: 'month'}, - {display: "6 months", value: 'half_year'}, - {display: "1 year", value: 'year'} - ]; - } - - render() { - var power_time_series = this; - return ( -
-

Power Time Series

- -
- {power_time_series.timeframes.map(timeframe => -
{timeframe.display}
- )} -
-
- ); - } -} - -export default Relay.createContainer(PowerTimeSeries, { - fragments: { - viewer: () => Relay.QL` - fragment on User { - widgets(first: 10) { - edges { - node { - id, - name, - }, - }, - }, - } - `, - }, -}); diff --git a/client/dashboard/production_radiation_time_series.component.js b/client/dashboard/production_radiation_time_series.component.js deleted file mode 100644 index 735f89b..0000000 --- a/client/dashboard/production_radiation_time_series.component.js +++ /dev/null @@ -1 +0,0 @@ -production_radiation_time_series.widget.js diff --git a/client/dashboard/readme.md b/client/dashboard/readme.md deleted file mode 100644 index c0a4b44..0000000 --- a/client/dashboard/readme.md +++ /dev/null @@ -1,6 +0,0 @@ -## Dashboard Widgets - -After initialized: -1. They get/ check the data they need. -2. Render default graph settings. -3. Update graphs based on user input. diff --git a/client/react/app.js b/client/react/app.js deleted file mode 100644 index e3d8963..0000000 --- a/client/react/app.js +++ /dev/null @@ -1,15 +0,0 @@ -import 'babel-polyfill'; - -import App from './components/App'; -import AppHomeRoute from './routes/AppHomeRoute'; -import React from 'react'; -import ReactDOM from 'react-dom'; -import Relay from 'react-relay'; - -ReactDOM.render( - , - document.getElementById('root') -); diff --git a/client/style.js b/client/style.js new file mode 100644 index 0000000..bbe7490 --- /dev/null +++ b/client/style.js @@ -0,0 +1,7 @@ +// Vendor Stylesheets +require('bootstrap/dist/css/bootstrap.min.css'); +require('font-awesome/css/font-awesome.min.css'); + + +// Component Stylesheets +require(__dirname + '/dashboard/layout/layout.scss'); diff --git a/gulpfile.babel.js b/gulpfile.babel.js index 13eeb46..7eab4d2 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -1,8 +1,12 @@ import gulp from 'gulp'; import yargs from 'yargs'; +import webpack from 'webpack'; +import gutil from 'gulp-util'; import DB from './server/config/database'; import {PowerDataSeed, HouseSeed} from './server/lib/tasks/seed_data'; +import rtCompile from './server/lib/tasks/react_template_compile'; +import rt_config from './server/config/react_templates'; gulp.task('generate_power_csv', function(done){ DB.sync().then(()=>{ @@ -21,3 +25,32 @@ gulp.task('save_house_csv', function(done){ HouseSeed.saveCsv(yargs.argv, done); }); }); + +gulp.task('compile_react_templates', function() { + gulp.src('./client/react/**/*.rt') + .pipe(rtCompile(rt_config)) + .pipe(gulp.dest('./client/react')); +}); + + +gulp.task('build', function(done) { + var config, env; + + if (yargs.argv.production){ + env = 'production'; + } else if (yargs.argv.design){ + env = 'design'; + } else { + throw new gutil.PluginError("webpack", "Must add '--production' or '--design' option."); + } + config = require(`${__dirname}/server/config/webpack/${env}`); + // run webpack + webpack(config, function(err, stats) { + if(err) throw new gutil.PluginError("webpack", err); + gutil.log("[webpack]", stats.toString({ + // output options + })); + done(); + }); + +}); diff --git a/package.json b/package.json index 3816a0b..9a2d91f 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,6 @@ "jade": "~1.9.2", "morgan": "~1.5.1", "serve-favicon": "~2.2.0", - "connect-assets": "~4.7.0", - "connect-jade-static": "~0.2.2", "node-forge": "~0.6.26", "sequelize": "~3.15.1", "pg": "~4.4.3", @@ -36,20 +34,23 @@ "react-dom": "0.14.3", "webpack": "1.12.9", "webpack-dev-server": "1.14.0", + "extract-text-webpack-plugin": "1.0.1", "jquery": "2.2.0", "bootstrap": "3.3.6", "d3": "3.5.12", "font-awesome": "4.5.0", - "css-loader": "^0.15.5", + "raw-loader": "0.5.1", + "sass-loader": "3.1.2", "style-loader": "^0.12.3", - "connect-assets":"~4.7.0", "node-sass": "3.4.2", "moment-timezone":"0.5.0", "yargs": "3.32.0", - "extend": "3.0.0" + "extend": "3.0.0", + "through2": "2.0.1" }, "devDependencies": { "gulp": "^3.9.0", + "gulp-util": "3.0.7", "babel-cli": "^6.3.17", "babel-standalone": "6.4.4", "react-templates": "0.4.1" diff --git a/server/app.express.js b/server/app.express.js index 52261ca..56b634f 100644 --- a/server/app.express.js +++ b/server/app.express.js @@ -3,55 +3,26 @@ */ import express from 'express'; -import graphQLHTTP from 'express-graphql'; import path from 'path'; import webpack from 'webpack'; import WebpackDevServer from 'webpack-dev-server'; import schema from './config/graphql/schema'; import DB from './config/database'; +import routes from './routes'; const APP_PORT = 3000; -const GRAPHQL_PORT = 8080; +const JS_PORT = 3000; -var rest_api = express(); +var app = express(); DB.sync().then(()=>{ - rest_api -}); -/* - * Compile and Serve Relay App w/ Webpack - */ - -var compiler = webpack({ - entry: { - app: path.resolve(__dirname, 'lib', 'relay', 'app.relay.js') - }, - module: { - loaders: [ - { - exclude: /node_modules/, - loader: 'babel', - query: { - plugins: ['./build/babelRelayPlugin'], - }, - test: /\.js$/ - } - ] - }, - output: {filename: 'application.js', path: '/'} -}); -var dev_server = new WebpackDevServer(compiler, { - contentBase: '/public/', - proxy: {'/graphql': `http://localhost:${GRAPHQL_PORT}`}, - publicPath: '/assets/js/', - stats: {colors: true} -}); +routes(app); /* * Logging, Cookie, JSON Parsing Middleware - * + */ import favicon from 'serve-favicon'; import logger from 'morgan'; @@ -59,11 +30,10 @@ import cookieParser from 'cookie-parser'; import bodyParser from 'bodyParser'; // uncomment after placing your favicon in /public -//app.use(favicon(__dirname + '/public/favicon.ico')); +app.use(favicon(__dirname + '/public/favicon.ico')); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); -app.use(cookieParser());*/ /* * Serve Vendor Scripts, CSS, and Templates @@ -71,11 +41,11 @@ app.use(cookieParser());*/ // serve fonts in /assets/fonts import assets from "connect-assets"; -dev_server.app.use("/assets/fonts", express.static("node_modules/bootstrap/dist/fonts")); -dev_server.app.use("/assets/fonts", express.static("node_modules/font-awesome/fonts")); +app.use("/assets/fonts", express.static("node_modules/bootstrap/dist/fonts")); +app.use("/assets/fonts", express.static("node_modules/font-awesome/fonts")); // serve compiled vendor assets and application.css. -dev_server.app.use(assets({ - paths: ["assets/js", "assets/css", "node_modules"], +app.use(assets({ + paths: ["./assets/js", "./assets/css", "./../node_modules"], build: true, buildDir: false, //compile: false, @@ -85,14 +55,13 @@ dev_server.app.use(assets({ dev_server.app.use('/', express.static(path.resolve(__dirname, 'public'))); // view engine set up -dev_server.app.set('views', path.join(__dirname, 'views')); -dev_server.app.set('view engine', 'jade'); -dev_server.app.get("/", (req, res, next)=>{ +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'jade'); +app.get("/", (req, res, next)=>{ res.render("index"); }); -console.log("launching dev server") -dev_server.listen(APP_PORT, () => { +app.listen(APP_PORT, () => { console.log(`App is now running on http://localhost:${APP_PORT}`); }); @@ -101,13 +70,12 @@ dev_server.listen(APP_PORT, () => { */ // catch 404 and forward to error handler -dev_server.use(function(req, res, next) { +app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); -/* // development error handler // will print stacktrace if (app.get('env') === 'development') { @@ -128,7 +96,57 @@ app.use(function(err, req, res, next) { message: err.message, error: {} }); -});*/ +}); + +}); + +/* + * Development Server + */ + +import ExtractTextPlugin from "extract-text-webpack-plugin"; + +var compiler = webpack({ + entry: { + app: __dirname + '/../client/app.js', + style: __dirname + '/../client/style.scss' + }, + output: { + filename: '[name].js', + path: __dirname + '/../client/build' + }, + externals: { + jquery: "$", + d3: "d3" + }, + module: { + loaders: [ + { + test: /\.scss$/, + loader: ExtractTextPlugin.extract("style-loader", "css-loader!sass-loader") + }, { + test: /\.css$/, + loader: ExtractTextPlugin.extract("style-loader", "css-loader") + } + ] + }, + // Use the plugin to specify the resulting filename (and add needed behavior to the compiler) + plugins: [ + new ExtractTextPlugin("style.css", { + allChunks: true + }) + ] +}); -module.exports = dev_server; +var dev_server = new WebpackDevServer(compiler, { + contentBase: __dirname + '/../client/build', + publicPath: "/assets/", + proxy: { + '/data': `http://localhost:${APP_PORT}` + }, + stats: {colors: true} +}); + + +module.exports = app; diff --git a/server/assets/css/application.scss.css b/server/assets/css/application.scss.css deleted file mode 100644 index e69de29..0000000 diff --git a/server/assets/css/vendor.scss.css b/server/assets/css/vendor.scss.css deleted file mode 100644 index 2a18b12..0000000 --- a/server/assets/css/vendor.scss.css +++ /dev/null @@ -1,3 +0,0 @@ -/*=require bootstrap/dist/css/bootstrap.min - *= require font-awesome/css/font-awesome.min - */ diff --git a/server/assets/js/vendor.js b/server/assets/js/vendor.js deleted file mode 100644 index 69e363b..0000000 --- a/server/assets/js/vendor.js +++ /dev/null @@ -1,3 +0,0 @@ -//= require d3/d3.min -//= require jquery/dist/jquery.min -//= require bootstrap/dist/js/bootstrap.min diff --git a/server/config/database.js b/server/config/database.js index 1b0e226..b3ae7b1 100644 --- a/server/config/database.js +++ b/server/config/database.js @@ -24,7 +24,6 @@ class Database { // add associations for (var model of Database.models){ - console.log(`setting ${model.name}`); model.set(); } diff --git a/server/config/graphql/node.js b/server/config/graphql/node.js deleted file mode 100644 index 1f4b230..0000000 --- a/server/config/graphql/node.js +++ /dev/null @@ -1,19 +0,0 @@ -import { - fromGlobalId, - nodeDefinitions, -} from 'graphql-relay'; - -import DB from './../database' - -var {nodeInterface, nodeField} = nodeDefinitions( - (globalId) => { - var {graphql_type_name, id} = fromGlobalId(globalId), - model = DB[graphql_type_name]; - return model.findOne({where: {id: id}}); - }, - (instance) => { - return instance.Model().graphql_type; - } -); - -export {nodeInterface, nodeField}; diff --git a/server/config/graphql/schema.graphql b/server/config/graphql/schema.graphql deleted file mode 100644 index 836384a..0000000 --- a/server/config/graphql/schema.graphql +++ /dev/null @@ -1,27 +0,0 @@ -type House implements Node { - id: ID! - name: String! - power_data(after: String, first: Int, before: String, last: Int): [PowerDatum] - habitants(after: String, first: Int, before: String, last: Int): [User] -} - -interface Node { - id: ID! -} - -type PowerDatum implements Node { - id: ID! - power: Float - time: Int -} - -type Query { - node(id: ID!): Node - viewer: User -} - -type User implements Node { - id: ID! - username: String! - house: House -} diff --git a/server/config/graphql/schema.js b/server/config/graphql/schema.js deleted file mode 100644 index 995a8e3..0000000 --- a/server/config/graphql/schema.js +++ /dev/null @@ -1,27 +0,0 @@ -import { - GraphQLObjectType, - GraphQLSchema -} from 'graphql'; - -import {nodeField} from './node'; -import DB from './../database'; - -export default function(){ - - var queryType = new GraphQLObjectType({ - name: 'Query', - fields: () => ({ - node: nodeField, - viewer: { - type: DB.User.graphql_type, - resolve: (_, args) => { - return DB.User.findOne({where: {username: 'bethany'}}); - } - }, - }), - }); - - return new GraphQLSchema({ - query: queryType - }); -} diff --git a/server/config/graphql/schema.json b/server/config/graphql/schema.json deleted file mode 100644 index f219e5c..0000000 --- a/server/config/graphql/schema.json +++ /dev/null @@ -1,1176 +0,0 @@ -{ - "data": { - "__schema": { - "queryType": { - "name": "Query" - }, - "mutationType": null, - "subscriptionType": null, - "types": [ - { - "kind": "OBJECT", - "name": "Query", - "description": null, - "fields": [ - { - "name": "node", - "description": "Fetches an object given its ID", - "args": [ - { - "name": "id", - "description": "The ID of an object", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "INTERFACE", - "name": "Node", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "viewer", - "description": null, - "args": [], - "type": { - "kind": "OBJECT", - "name": "User", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ID", - "description": "The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"4\"`) or integer (such as `4`) input value will be accepted as an ID.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INTERFACE", - "name": "Node", - "description": "An object with an ID", - "fields": [ - { - "name": "id", - "description": "The id of the object.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": [ - { - "kind": "OBJECT", - "name": "House", - "ofType": null - }, - { - "kind": "OBJECT", - "name": "PowerDatum", - "ofType": null - }, - { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - ] - }, - { - "kind": "OBJECT", - "name": "House", - "description": "A house", - "fields": [ - { - "name": "id", - "description": "The ID of an object", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "power_data", - "description": "Returns house's power data.", - "args": [ - { - "name": "after", - "description": null, - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "first", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "before", - "description": null, - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "last", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "PowerDatum", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "habitants", - "description": "Returns list of house's habitants.", - "args": [ - { - "name": "after", - "description": null, - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "first", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "before", - "description": null, - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "last", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - { - "kind": "INTERFACE", - "name": "Node", - "ofType": null - } - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "String", - "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Int", - "description": "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^53 - 1) and 2^53 - 1 since represented in JSON as double-precision floating point numbers specifiedby [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "PowerDatum", - "description": "A person who uses our app", - "fields": [ - { - "name": "id", - "description": "The ID of an object", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "power", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "time", - "description": "Time the power was recorded.", - "args": [], - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - { - "kind": "INTERFACE", - "name": "Node", - "ofType": null - } - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Float", - "description": "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "User", - "description": "A house", - "fields": [ - { - "name": "id", - "description": "The ID of an object", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "username", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "house", - "description": "Returns user's house.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "House", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - { - "kind": "INTERFACE", - "name": "Node", - "ofType": null - } - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Schema", - "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.", - "fields": [ - { - "name": "types", - "description": "A list of all types supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type" - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "queryType", - "description": "The type that query operations will be rooted at.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mutationType", - "description": "If this server supports mutation, the type that mutation operations will be rooted at.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "subscriptionType", - "description": "If this server support subscription, the type that subscription operations will be rooted at.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "directives", - "description": "A list of all directives supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Directive" - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Type", - "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.", - "fields": [ - { - "name": "kind", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "__TypeKind", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "fields", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Field", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "interfaces", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "possibleTypes", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "enumValues", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__EnumValue", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inputFields", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ofType", - "description": null, - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "__TypeKind", - "description": "An enum describing what kind of type a given `__Type` is.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "SCALAR", - "description": "Indicates this type is a scalar.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OBJECT", - "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INTERFACE", - "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UNION", - "description": "Indicates this type is a union. `possibleTypes` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM", - "description": "Indicates this type is an enum. `enumValues` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_OBJECT", - "description": "Indicates this type is an input object. `inputFields` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "LIST", - "description": "Indicates this type is a list. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NON_NULL", - "description": "Indicates this type is a non-null. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Boolean", - "description": "The `Boolean` scalar type represents `true` or `false`.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Field", - "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue" - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__InputValue", - "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "defaultValue", - "description": "A GraphQL-formatted string representing the default value for this input value.", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__EnumValue", - "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Directive", - "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL’s execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue" - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "onOperation", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "onFragment", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "onField", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - } - ], - "directives": [ - { - "name": "include", - "description": "Directs the executor to include this field or fragment only when the `if` argument is true.", - "args": [ - { - "name": "if", - "description": "Included when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "defaultValue": null - } - ], - "onOperation": false, - "onFragment": true, - "onField": true - }, - { - "name": "skip", - "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", - "args": [ - { - "name": "if", - "description": "Skipped when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "defaultValue": null - } - ], - "onOperation": false, - "onFragment": true, - "onField": true - } - ] - } - } -} \ No newline at end of file diff --git a/server/config/react_templates.js b/server/config/react_templates.js new file mode 100644 index 0000000..761eead --- /dev/null +++ b/server/config/react_templates.js @@ -0,0 +1,5 @@ +export default { + modules: 'es6', + 'target-version': '0.14.3', + 'suffix': '.rt' +}; diff --git a/server/config/webpack/design.js b/server/config/webpack/design.js new file mode 100644 index 0000000..a9af8e5 --- /dev/null +++ b/server/config/webpack/design.js @@ -0,0 +1 @@ +design.js diff --git a/server/config/webpack/development.js b/server/config/webpack/development.js new file mode 100644 index 0000000..89414d8 --- /dev/null +++ b/server/config/webpack/development.js @@ -0,0 +1,41 @@ +const ROOT = __dirname + '/../../../'; + +module.exports = { + entry: { + app: ROOT + 'client/app', + style: ROOT + 'client/style' + }, + output: { + filename: '[name].js', + path: ROOT + 'client/build/development' + }, + externals: { + jquery: "$", + d3: "d3" + }, + module: { + loaders: [ + { + test: /\.scss$/, + loader: ['style', 'raw', 'sass'] + }, { + test: /\.css$/, + loader: ['style', 'raw'] + } + ] + }, + sassLoader: { + includePaths: [ROOT + 'client', ROOT + 'node_modules'] + }, + // Use the plugin to specify the resulting filename (and add needed behavior to the compiler) + plugins: [ + new ExtractTextPlugin("style.css", { + allChunks: true + }), + new webpack.ProvidePlugin({ + $: "jquery", + jQuery: "jquery", + "window.jQuery": "jquery" + }) + ] +} diff --git a/server/config/webpack/production.js b/server/config/webpack/production.js new file mode 100644 index 0000000..d4aad85 --- /dev/null +++ b/server/config/webpack/production.js @@ -0,0 +1,55 @@ +import ExtractTextPlugin from 'extract-text-webpack-plugin'; +import webpack from 'webpack'; + +const ROOT = __dirname + '/../../../'; + +module.exports = { + entry: { + app: ROOT + 'client/app', + style: ROOT + 'client/style' + }, + devtool: 'source-map', + output: { + filename: '[name].min.js', + path: ROOT + 'client/build/production' + }, + externals: { + jquery: "$", + d3: "d3" + }, + module: { + loaders: [ + { + test: /\.scss$/, + loader: ExtractTextPlugin.extract("style-loader", "raw-loader!sass-loader") + }, { + test: /\.css$/, + loader: ExtractTextPlugin.extract("style-loader", "raw-loader") + }, { + test: /\.js$/, + loader: 'babel' + }, { + test: /\.woff(\?v=[0-9]\.[0-9]\.[0-9])?$/, + loader: "url-loader?limit=10000&minetype=application/font-woff" + }, { + test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, + loader: "file-loader" + } + ] + }, + sassLoader: { + includePaths: [ROOT + 'client', ROOT + 'node_modules'] + }, + // Use the plugin to specify the resulting filename (and add needed behavior to the compiler) + plugins: [ + new ExtractTextPlugin("style.min.css", { + allChunks: true + }), + new webpack.optimize.UglifyJsPlugin({minimize: true}), + new webpack.ProvidePlugin({ + $: "jquery", + jQuery: "jquery", + "window.jQuery": "jquery" + }) + ] +}; diff --git a/server/lib/tasks/react_template_compile.js b/server/lib/tasks/react_template_compile.js new file mode 100644 index 0000000..34e66a1 --- /dev/null +++ b/server/lib/tasks/react_template_compile.js @@ -0,0 +1,58 @@ +'use strict'; +// through2 is a thin wrapper around node transform streams +import through from 'through2'; +import gutil from 'gulp-util'; +import rt from 'react-templates'; +import path from 'path'; +import extend from 'extend'; + +// Consts +const PLUGIN_NAME = 'gulp-react-templates'; +var PluginError = gutil.PluginError; + +function normalizeName(name) { + return name.replace(/-/g, '_'); +} + +export default function (opt) { + function replaceExtension(filePath) { + return filePath + '.js'; + } + + function transform(file, enc, cb) { + if (file.isNull()) { + return cb(null, file); + } + if (file.isStream()) { + return cb(new PluginError(PLUGIN_NAME, 'Streaming not supported')); + } + + var filePath = file.path, + str = file.contents.toString('utf8'), + data; + + var options = extend({ + filename: file.path, + sourceFiles: [file.relative], + generatedFile: replaceExtension(file.relative), + suffix: '.rt' + }, opt); + + if (options.suffix && !options.name) { + options.name = normalizeName(path.basename(filePath, path.extname(filePath))) + options.suffix; + } + + try { + data = rt.convertTemplateToReact(str, options); + } catch (err) { + return cb(new PluginError(PLUGIN_NAME, err)); + } + + file.contents = new Buffer(data); + + file.path = replaceExtension(file.path); + cb(null, file); + } + + return through.obj(transform); +}; diff --git a/server/public/favicon.ico b/server/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..127c0d9f8e80da40f64df92096c826eb737f6399 GIT binary patch literal 1150 zcmaizIZs|hpw+3~_AdP0;c zfp~*Ry_=zG>WSw{4oj2dynYm-7^6<;gS9rctf!9jCRZ6{wV1nh@ zjzuYa`}XEpdjH~4US6(hYiq4oT{fHTQ(cN=r-K6%`fMl9CdW zyuQ9x+=Dg1rpwC8?rUmlq_VP7ii?W{{^EAKrLC<^T3cK1tE#Fp4u``ab9Hs4TrQXL zdc6khmv*~d5JT$g>!qWkLk0&2rLnP57_X(JMb_5Vq@kffs;jHN^!N80h^c%&p9S$U zPN!3vo0~ODp6@+9Ju)>lC3ACgvbwq|>2z9_mX>5@W=3XbXOlS30$(?B&q9J+G~dFn&(_d(Y0_dlYCk`sH@-Q8{O*^5vpB!`EGI){~&6#=8alSK_TWU%UfkB*K?EEbc2 zfdReew`eqKp1-`jtnKvg>+8FTL?R!ChK9618P>*n(O=UxJw2`YlamvP$K$3Q^Kk)R z7i@QkBjIpZi~hWG<}xxeA`1%(LN>?K4&6a6%!dW}rI{mULN+%yWov6o-~GhIgiy>m z$MgMrvJXsmkin8qOu8i literal 0 HcmV?d00001