More react changes

This commit is contained in:
Colin McLeod
2015-11-30 22:55:53 -08:00
parent 79224f4f9a
commit 035f6b3efa
10 changed files with 235 additions and 136 deletions

View File

@@ -9,9 +9,8 @@ cache:
- node_modules
before_script:
- npm install -g gulp
- npm install -g bower
script:
- gulp lint
- gulp build-prod
- gulp test
- npm run lint
- npm test
- npm run build

View File

@@ -1,27 +1,15 @@
var path = require('path');
var express = require('express');
var webpack = require('webpack');
var WebpackDevServer = require("webpack-dev-server");
var config = require('./webpack.config.dev');
var app = express();
var compiler = webpack(config);
app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true,
publicPath: config.output.publicPath
}));
app.use(require('webpack-hot-middleware')(compiler));
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'src/index.html'));
});
app.listen(3300, 'localhost', function(err) {
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
historyApiFallback: true
}).listen(3300, "0.0.0.0", function (err, result) {
if (err) {
console.log(err);
return;
}
console.log('Listening at http://localhost:3000');
console.log("Listening at localhost:3300");
});

59
nginx.conf Normal file
View File

@@ -0,0 +1,59 @@
worker_processes 2;
error_log ./nginx.error.log;
worker_rlimit_nofile 8192;
pid nginx.pid;
events {
worker_connections 1024;
multi_accept on;
}
http {
access_log off;
charset UTF-8;
types {
text/html html htm shtml;
text/css css;
text/xml xml rss;
image/gif gif;
image/jpeg jpeg jpg;
application/x-javascript js;
text/plain txt;
image/png png;
image/svg+xml svg;
image/x-icon ico;
application/pdf pdf;
text/cache-manifest appcache;
}
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
server {
listen 3300;
server_name localhost;
root ./build/;
index index.html;
location ~* \.(?:manifest|appcache|html?|xml|json|css|js|map|jpg|jpeg|gif|png|ico|svg|eot|ttf|woff|woff2)$ {
expires -1;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
access_log off;
}
location / {
try_files $uri $uri/ /index.html =404;
}
}
}

View File

@@ -12,12 +12,16 @@
"license": "MIT",
"scripts": {
"clean": "rimraf build",
"build:prod": "NODE_ENV=production webpack --config webpack.config.prod.js",
"build": "npm run clean && npm run build:prod",
"start": "node devServer.js",
"lint": "eslint src"
"lint": "eslint ./src",
"prod-serve": "nginx -p $(pwd) -c nginx.conf",
"prod-stop": "kill -QUIT $(cat nginx.pid)",
"build": "npm run clean && NODE_ENV=production webpack -d -p --config webpack.config.prod.js",
"rsync": "rsync -e 'ssh -i $CORIOLIS_PEM' -a --delete build/ $CORIOLIS_USER@$CORIOLIS_HOST:~/www",
"deploy": "npm run lint && npm run build && npm run rsync"
},
"devDependencies": {
"appcache-webpack-plugin": "^1.2.1",
"babel-core": "^5.4.7",
"babel-eslint": "^3.1.9",
"babel-loader": "^5.1.2",
@@ -27,11 +31,10 @@
"eslint-plugin-react": "^2.3.0",
"express": "^4.13.3",
"file-loader": "^0.8.4",
"install": "^0.3.0",
"html-webpack-plugin": "^1.7.0",
"json-loader": "^0.5.3",
"less": "^2.5.3",
"less-loader": "^2.2.1",
"npm": "^3.4.0",
"react-transform-catch-errors": "^1.0.0",
"react-transform-hmr": "^1.0.0",
"redbox-react": "^1.0.1",
@@ -39,12 +42,12 @@
"style-loader": "^0.13.0",
"url-loader": "^0.5.6",
"webpack": "^1.9.6",
"webpack-dev-middleware": "^1.2.0",
"webpack-hot-middleware": "^2.0.0"
"webpack-dev-server": "^1.14.0"
},
"dependencies": {
"classnames": "^2.2.0",
"d3": "^3.5.9",
"extract-text-webpack-plugin": "^0.9.1",
"fbemitter": "^2.0.0",
"lz-string": "^1.4.4",
"react": "^0.14.2",

View File

@@ -24,7 +24,6 @@ export default class AvailableModulesMenu extends TranslatedComponent {
for (let i = 0; i < modules.length; i++) {
let m = modules[i];
let classRating = m.class + m.rating;
let mount = null;
let classes = cn(m.name ? 'lc' : 'c', {
active: mountedModule && mountedModule.id === m.id,
@@ -87,7 +86,6 @@ export default class AvailableModulesMenu extends TranslatedComponent {
list.push(<div className={'empty-c upp'} key={'empty'} onClick={this.props.onSelect.bind(null, null)} >{translate('empty')}</div>);
for (let g in modules) {
let grp = modules[g];
let grpCode = grp[Object.keys(grp)[0]].grp; // Nasty operation to get the grp property of the first/any single component
list.push(<div ref={g} key={g} className={'select-group cap'}>{translate(g)}</div>);
list.push(buildGroup(g, modules[g]));
}

View File

@@ -36,7 +36,7 @@ export default class StandardSlotSection extends SlotSection {
}
_getSlots() {
let { formats, translate, units } = this.context.language;
let { translate, units } = this.context.language;
let slots = new Array(8);
let open = this._openMenu;
let select = this._selectModule;
@@ -45,7 +45,6 @@ export default class StandardSlotSection extends SlotSection {
let st = ship.standard;
let avail = ship.getAvailableModules().standard;
let bulkheads = ship.bulkheads;
let bulkheadIndex = bulkheads.id;
let currentMenu = this.state.currentMenu;
slots[0] = (
@@ -61,11 +60,11 @@ export default class StandardSlotSection extends SlotSection {
{currentMenu === bulkheads &&
<div className='select' onClick={ e => e.stopPropagation() }>
<ul>
<li onClick={selBulkhead.bind(this, 0)} className={cn('lc', { active: bulkheads.id=='0' })}>{translate('Lightweight Alloy')}</li>
<li onClick={selBulkhead.bind(this, 1)} className={cn('lc', { active: bulkheads.id=='1' })}>{translate('Reinforced Alloy')}</li>
<li onClick={selBulkhead.bind(this, 2)} className={cn('lc', { active: bulkheads.id=='2' })}>{translate('Military Grade Composite')}</li>
<li onClick={selBulkhead.bind(this, 3)} className={cn('lc', { active: bulkheads.id=='3' })}>{translate('Mirrored Surface Composite')}</li>
<li onClick={selBulkhead.bind(this, 4)} className={cn('lc', { active: bulkheads.id=='4' })}>{translate('Reactive Surface Composite')}</li>
<li onClick={selBulkhead.bind(this, 0)} className={cn('lc', { active: bulkheads.id == '0' })}>{translate('Lightweight Alloy')}</li>
<li onClick={selBulkhead.bind(this, 1)} className={cn('lc', { active: bulkheads.id == '1' })}>{translate('Reinforced Alloy')}</li>
<li onClick={selBulkhead.bind(this, 2)} className={cn('lc', { active: bulkheads.id == '2' })}>{translate('Military Grade Composite')}</li>
<li onClick={selBulkhead.bind(this, 3)} className={cn('lc', { active: bulkheads.id == '3' })}>{translate('Mirrored Surface Composite')}</li>
<li onClick={selBulkhead.bind(this, 4)} className={cn('lc', { active: bulkheads.id == '4' })}>{translate('Reactive Surface Composite')}</li>
</ul>
</div>
}

View File

@@ -136,6 +136,7 @@ export default class ShipyardPage extends Page {
}
render() {
let translate = this.context.language.translate;
let shipSummaries = this.shipSummaries;
let shipPredicate = this.state.shipPredicate;
let shipPredicateIndex = this.state.shipPredicateIndex;
@@ -170,11 +171,6 @@ export default class ShipyardPage extends Page {
}
});
let formats = this.context.language.formats;
let fInt = formats.int;
let fRound = formats.round;
let translate = this.context.language.translate;
for (let s of shipSummaries) {
shipRows.push(s.rowElement);
}

View File

@@ -1,7 +1,8 @@
<!DOCTYPE html>
<html >
<head>
<html {%= o.htmlWebpackPlugin.options.appCache ? 'manifest="/' + o.htmlWebpackPlugin.options.appCache + '"' : '' %} >
<head>
<title>Coriolis</title>
<link rel="stylesheet" href="{%= o.htmlWebpackPlugin.files.css[0] %}">
<!-- Standard headers -->
<meta name="description" content="A ship builder, outfitting and comparison tool for Elite Dangerous">
<meta name="mobile-web-app-capable" content="yes">
@@ -50,27 +51,27 @@
<meta name="msapplication-TileImage" content="/images/logo/mstile-144x144.png">
<meta name="msapplication-config" content="/images/logo/browserconfig.xml">
<meta name="theme-color" content="#000000">
</head>
<body style="background-color:#000;">
</head>
<body style="background-color:#000;">
<section id="coriolis"></section>
<footer>
<div class="right cap">
<a href="https://github.com/cmmcleod/coriolis/releases/" target="_blank" title="Coriolis Github Project"><span translate="version"></span> <!--<%= version %> - <%= date %> /--></a>
<a href="https://github.com/cmmcleod/coriolis/releases/" target="_blank" title="Coriolis Github Project"><span translate="version"></span> {%= o.htmlWebpackPlugin.options.version %} - {%= new Date().toISOString().slice(0, 10) %}</a>
</div>
</footer>
<script src="/lib.js" charset="utf-8"></script>
<script src="/app.js" charset="utf-8" crossorigin></script>
<!-- <% if (uaTracking) { %>
<script src="{%= o.htmlWebpackPlugin.files.chunks.lib.entry %}" charset="utf-8"></script>
<script src="{%= o.htmlWebpackPlugin.files.chunks.app.entry %}" charset="utf-8" crossorigin></script>
{% if (o.htmlWebpackPlugin.options.uaTracking) { %}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', '<%= uaTracking %> ', 'auto');
var GAPI_KEY = '<%= gapiKey %>';
ga('create', '{%= o.htmlWebpackPlugin.options.uaTracking %}', 'auto');
var GAPI_KEY = '{%= o.htmlWebpackPlugin.options.gapiKey %}';
</script>
<% } %> -->
</body>
{% } %}
</body>
</html>

View File

@@ -1,10 +1,13 @@
var path = require('path');
var webpack = require('webpack');
var pkgJson = require('./package');
var HtmlWebpackPlugin = require("html-webpack-plugin");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
devtool: 'eval',
entry: {
app: [ 'webpack-hot-middleware/client', './src/app/index' ],
app: [ 'webpack-dev-server/client?http://localhost:3300', 'webpack/hot/only-dev-server', path.join(__dirname, "src/app/index.js") ],
lib: ['d3', 'react', 'react-dom', 'classnames', 'fbemitter', 'lz-string']
},
resolve: {
@@ -12,7 +15,7 @@ module.exports = {
extensions: ['', '.js', '.jsx', '.json', '.less'],
alias: {
'coriolis-data': path.resolve(__dirname, 'node_modules/coriolis-data')
},
}
},
output: {
path: path.join(__dirname, 'build'),
@@ -21,20 +24,30 @@ module.exports = {
},
plugins: [
new webpack.optimize.CommonsChunkPlugin('lib', 'lib.js'),
new HtmlWebpackPlugin({
inject: false,
template: path.join(__dirname, "src/index.html"),
cdn: '',
version: pkgJson.version
}),
new ExtractTextPlugin('app.css', {
allChunks: true
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
module: {
loaders: [
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader','css-loader') },
{ test: /\.less$/, loader: ExtractTextPlugin.extract('style-loader','css-loader!less-loader') },
{ test: /\.(js|jsx)$/, loaders: [ 'babel' ], include: path.join(__dirname, 'src') },
{ test: /\.less$/, loader: 'style!css!less' },
{ test: /\.json$/, loader: 'json-loader' },
{ test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff' },
{ test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff' },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream' },
{ test: /\.(png|jpg|jpeg|gif)?$/, loader: 'file' },
{ test: /\.(png|jpg|jpeg|gif|ico)$/, loader: 'file-loader?name=/images/[name].[ext]' },
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file' },
{ test: /\.xml$/, loader: 'file' },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml' }
]
}

View File

@@ -1,5 +1,10 @@
var path = require('path');
var exec = require('child_process').exec;
var webpack = require('webpack');
var pkgJson = require('./package');
var HtmlWebpackPlugin = require("html-webpack-plugin");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var AppCachePlugin = require('appcache-webpack-plugin');
var node_modules_dir = path.resolve(__dirname, 'node_modules');
var d3Path = path.resolve(node_modules_dir, 'd3/d3.min.js');
@@ -7,6 +12,18 @@ var reactPath = path.resolve(node_modules_dir, 'react/dist/react.min.js');
var reactDomPath = path.resolve(node_modules_dir, 'react-dom/dist/react-dom.min.js');
var lzStringPath = path.resolve(node_modules_dir, 'lz-string/libs/lz-string.min.js');
function CopyDirPlugin(source, destination) {
this.source = source;
this.destination = destination;
}
CopyDirPlugin.prototype.apply = function(compiler) {
compiler.plugin('done', function() {
console.log(compiler.outputPath, this.destination);
exec('cp -r ' + this.source + ' ' + path.join(compiler.outputPath, this.destination));
}.bind(this));
};
module.exports = {
entry: {
app: path.resolve(__dirname, 'src/app/index'),
@@ -24,34 +41,60 @@ module.exports = {
},
output: {
path: path.join(__dirname, 'build'),
filename: 'app.js'
filename: '[name].[hash:6].js',
publicPath: '//cdn.coriolis.io/'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin('lib', 'lib.js'),
new webpack.optimize.UglifyJsPlugin({
mangle: {
except: []
},
'screw-ie8': true
}),
new webpack.optimize.CommonsChunkPlugin('lib', 'lib.[hash:6].js'),
new HtmlWebpackPlugin({
inject: true,
template: path.join(__dirname, "src/public/index.html"),
favicon: path.join(__dirname, "src/assets/images/favicon.png"),
inject: false,
appCache: 'coriolis.appcache'
minify: {
removeComments: true,
collapseBooleanAttributes: true,
collapseWhitespace: true,
minifyJS: true
}
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttributes: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true
},
template: path.join(__dirname, "src/index.html"),
uaTracking: process.env.CORIOLIS_UA_TRACKING || '',
gapiKey: process.env.CORIOLIS_GAPI_KEY || '',
version: pkgJson.version
}),
new ExtractTextPlugin('[contenthash:6].css', {
allChunks: true
}),
new CopyDirPlugin(path.join(__dirname, 'src/schemas'), 'schemas'),
new AppCachePlugin({
network: ['*'],
settings: ['prefer-online'],
exclude: ['index.html', /.*\.map$/],
output: 'coriolis.appcache'
})
],
module: {
noParse: [d3Path, reactPath, reactDomPath, lzStringPath],
noParse: [d3Path, reactPath, lzStringPath],
loaders: [
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{ test: /\.(js|jsx)$/, loader: 'babel', include: path.join(__dirname, 'src') },
{ test: /\.less$/, loader: 'style!css!less' },
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader','css-loader') },
{ test: /\.less$/, loader: ExtractTextPlugin.extract('style-loader','css-loader!less-loader') },
{ test: /\.(js|jsx)$/, loaders: [ 'babel' ], include: path.join(__dirname, 'src') },
{ test: /\.json$/, loader: 'json-loader' },
{ test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff' },
{ test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff' },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream' },
{ test: /\.(png|jpg|jpeg|gif)?$/, loader: 'file' },
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file' },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml' }
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml' },
{ test: /\.xml$/, loader: 'file' },
{ test: /\.(png|jpg|jpeg|gif|ico)$/, loader: 'file-loader?name=/images/[name].[hash:6].[ext]' }
]
}
};