React and ES2016 done

This commit is contained in:
Martin Donnelly 2017-11-08 00:51:34 +00:00
parent d332140d32
commit 88d5987979
22 changed files with 3111 additions and 19882 deletions

3
.babelrc Normal file
View File

@ -0,0 +1,3 @@
{
"presets": [ "es2015", "react"]
}

6
.gitignore vendored
View File

@ -144,3 +144,9 @@ fabric.properties
!.elasticbeanstalk/*.global.yml
/src/bundle.js
/src/bundle.js.map
/src/react/bundle.js
/src/backbone/bundle.js
/src/react/bundle.js.map
/src/es2016/bundle.js
/src/es2016/bundle.js.map
/src/backbone/bundle.js.map

View File

@ -1,26 +1,32 @@
'use strict';
const browserify = require('browserify');
const gulp = require('gulp');
const browserify = require('gulp-browserify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const uglify = require('gulp-uglify-es').default;
const sourcemaps = require('gulp-sourcemaps');
const gutil = require('gulp-util');
const rename = require('gulp-rename');
const buffer = require('vinyl-buffer');
const sourcemaps = require('gulp-sourcemaps');
gulp.task('bundleBackbone', function () {
// Single entry point to browserify
gulp.src(['./src/backbone/js/app.js'])
.pipe(browserify({
'insertGlobals' : true,
'debug' : true
}))
// set up the browserify instance on a task basis
const b = browserify({
'debug': true,
'entries': './src/backbone/js/app.js'
});
return b.bundle()
.pipe(source('app.js'))
.pipe(buffer())
// optional, remove if you dont want sourcemaps
.pipe(sourcemaps.init({ 'loadMaps': true })) // loads map from browserify file
// Add transformation tasks to the pipeline here.
.pipe(sourcemaps.write('./src/backbone/')) // writes .map file
.pipe(rename('bundle.js'))
// .pipe(uglify())
.pipe(gulp.dest('./src/backbone/'));
.pipe(sourcemaps.init({ 'loadMaps': true }))
// Add transformation tasks to the pipeline here.
.pipe(uglify())
.on('error', gutil.log)
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('./src/backbone'));
});
gulp.task('buildBackbone', ['bundleBackbone'], function() {

35
gulp/es.js Normal file
View File

@ -0,0 +1,35 @@
'use strict';
const browserify = require('browserify');
const gulp = require('gulp');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const uglify = require('gulp-uglify-es').default;
const sourcemaps = require('gulp-sourcemaps');
const gutil = require('gulp-util');
const rename = require('gulp-rename');
gulp.task('bundleES', function () {
// set up the browserify instance on a task basis
const b = browserify({
'debug': true,
'entries': './src/es2016/js/app.js'
});
return b.bundle()
.pipe(source('app.js'))
.pipe(buffer())
.pipe(rename('bundle.js'))
.pipe(sourcemaps.init({ 'loadMaps': true }))
// Add transformation tasks to the pipeline here.
.pipe(uglify())
.on('error', gutil.log)
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('./src/es2016'));
});
gulp.task('buildES', ['bundleES'], function() {
gulp.watch('src/es2016/js/**/*.js', ['bundleES']);
});

33
gulp/react.js vendored Normal file
View File

@ -0,0 +1,33 @@
'use strict';
const gulp = require('gulp');
const browserify = require('browserify');
const rename = require('gulp-rename');
const babelify = require( 'babelify');
const buffer = require('vinyl-buffer');
const sourcemaps = require('gulp-sourcemaps');
const source = require('vinyl-source-stream');
const uglify = require('gulp-uglify-es').default;
function bundle_js(bundler) {
return bundler.bundle()
// .on('error', map_error)
.pipe(source('app.js'))
.pipe(buffer())
.pipe(rename('bundle.js'))
.pipe(sourcemaps.init({ 'loadMaps': true }))
// capture sourcemaps from transforms
.pipe(uglify())
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('./src/react'));
}
gulp.task('bundleReact', function () {
const bundler = browserify('./src/react/js/app.js', { 'debug': true }).transform(babelify, { 'presets': ['es2015', 'react'] });
return bundle_js(bundler);
});
gulp.task('buildReact', ['bundleReact'], function() {
gulp.watch('src/react/js/**/*.js', ['bundleReact']);
});

View File

@ -3,3 +3,5 @@ const gulp = require('gulp');
const requireDir = require('require-dir');
requireDir('./gulp');
gulp.task('BuildAll', ['bundleBackbone', 'bundleReact', 'bundleES']);

2885
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -22,29 +22,45 @@
"homepage": "https://github.com/martind2000/wiprotest#readme",
"dependencies": {
"apicache": "^1.1.0",
"babelify": "^8.0.0",
"backbone": "^1.3.3",
"browserify": "^14.4.0",
"express": "^4.16.1",
"browserify": "^14.5.0",
"es6-promise": "^4.1.1",
"express": "^4.16.2",
"fecha": "^2.3.1",
"fetch-everywhere": "^1.0.5",
"jquery": "^3.2.1",
"log4js": "^2.3.4",
"moment": "^2.18.1",
"openweather-apis": "^3.3.2",
"log4js": "^2.3.11",
"moment": "^2.19.1",
"openweather-apis": "^3.3.5",
"react": "^16.0.0",
"uglifyify": "^4.0.4",
"react-dom": "^16.0.0",
"underscore": "^1.8.3"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"eslint": "^4.10.0",
"eslint-plugin-react": "^7.4.0",
"expect.js": "^0.3.1",
"gulp": "^3.9.1",
"gulp-babel": "^7.0.0",
"gulp-browserify": "^0.5.1",
"gulp-rename": "^1.2.2",
"gulp-sourcemaps": "^2.6.1",
"gulp-streamify": "^1.0.2",
"gulp-tasks": "0.0.2",
"gulp-uglify": "^3.0.0",
"gulp-uglify-es": "^0.1.3",
"gulp-util": "^3.0.8",
"gulp-webpack": "^1.5.0",
"lodash.assign": "^4.2.0",
"mocha": "^3.5.3",
"require-dir": "^0.3.2",
"sinon": "^4.0.0",
"sinon": "^4.1.1",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0",
"watchify": "^3.9.0"

File diff suppressed because one or more lines are too long

View File

@ -1,25 +1,5 @@
const moment = require('moment');
const Backbone = require('backbone');
function reduceOpenWeather(item) {
// Openweather returns timestamps in seconds. Moment requires them in milliseconds.
const ts = moment(item.dt * 1000);
const weatherBlock = item.weather[0];
return {
'timestamp': item.dt,
'icon': `wi-owm-${weatherBlock.id}`,
'summary': weatherBlock.description,
'tempHigh': parseInt(item.temp.max, 10),
'tempLow': parseInt(item.temp.min, 10),
'datelong': ts.format(),
'time': item.dt,
'date': ts.format('D/M'),
'day': ts.format('ddd')
};
}
const { reduceOpenWeather } = require('../../../common/weatherReducer');
const WCollection = Backbone.Collection.extend({
'url': '/weather',

View File

@ -0,0 +1,24 @@
const fecha = require('fecha');
function reduceOpenWeather(item) {
// Openweather returns timestamps in seconds. Moment requires them in milliseconds.
// Replaced Moment with Fecha.
const fts = new Date(item.dt * 1000);
const weatherBlock = item.weather[0];
return {
'timestamp': item.dt,
'icon': `wi-owm-${weatherBlock.id}`,
'summary': weatherBlock.description,
'tempHigh': parseInt(item.temp.max, 10),
'tempLow': parseInt(item.temp.min, 10),
'datelong': fecha.format(fts, 'YYYY-MM-DDTHH:mm:ss.SSSZZ'),
'time': item.dt,
'date': fecha.format(fts, 'D/M'),
'day': fecha.format(fts, 'ddd')
};
}
module.exports = { reduceOpenWeather };

View File

@ -17,7 +17,7 @@
<div id="weather"></div>
</div>
<script src="//cdn.muicss.com/mui-0.9.26/js/mui.min.js"></script>
<script type='module' src="bundle.js"></script>
</body>
</html>

39
src/es2016/js/app.js Normal file
View File

@ -0,0 +1,39 @@
const fetchWeather = require( './fetchWeather');
(function (w) {
const el = document.getElementById('weather');
class Template {
constructor(item) {
this.data = `<div class="card mui--z1 mui-col-md-6 mui-col-lg-4" id="${item.day}">
<div class="mui-col-md-3">
<div class="mui--text-accent mui--text-title day mui--text-center">${item.day }</div>
<div class="mui--text-dark-secondary mui--text-subhead mui--text-center">${item.date }</div>
</div>
<div class="mui-col-md-9">
<div>
<i class="mui--text-headline wi ${item.icon}"></i>
<span class="mui--text-display1 temp${ item.tempHigh }">${item.tempHigh}°</span> /
<span class="mui--text-headline temp${ item.tempLow }">${item.tempLow}°</span></div>
<div class="mui--text-caption summary">${ item.summary }</div>
</div>
</div>`;
}
toString() {
return this.data;
}
}
function render(data) {
const html = [];
for (const item of data)
html.push(new Template(item).toString());
return(html.join(''));
}
fetchWeather().then((data) => {
el.innerHTML = render(data);
});
})(window);

View File

@ -0,0 +1,24 @@
const { reduceOpenWeather } = require('../../common/weatherReducer');
const url = '/weather';
const fetchWeather = () => {
return new Promise(function(resolve, reject) {
fetch(url)
.then(function(response) {
if (response.status >= 400) {
throw new Error('Bad response from server');
reject('error');
}
return response.json();
})
.then(function(data) {
resolve( data.list.map((item) => {
// Reduce the data
return reduceOpenWeather(item);
}));
});
});
};
module.exports = fetchWeather;

24
src/react/.eslintrc.json Normal file
View File

@ -0,0 +1,24 @@
{
"plugins": [
"react"
],
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"env": {
"es6": true,
"browser": true,
"node": true,
"mocha": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended"
],
"rules": {
}
}

View File

@ -16,8 +16,9 @@
<div class="mui--text-display3">Weather React</div>
<div id="weather"></div>
</div>
<div id="root"></div>
<script src="//cdn.muicss.com/mui-0.9.26/js/mui.min.js"></script>
<script type='module' src="bundle.js"></script>
</body>
</html>

7
src/react/js/app.js Normal file
View File

@ -0,0 +1,7 @@
const React = require('react');
const render = require( 'react-dom').render;
const Weather = require( './component/weather');
// import Weather from './component/weather'
render(<Weather />, document.getElementById('weather'));

View File

@ -0,0 +1,30 @@
const React = require('react');
const fetchWeather = require( '../services/weather');
const WeatherView = require('../view/weatherView');
class Weather extends React.Component {
constructor(props) {
super(props);
this.state = {loaded: false, weather:[]};
}
componentWillMount() {
this.getWeatherData();
}
getWeatherData() {
fetchWeather().then((d) => {
const newState = {loaded:true, weather:d};
this.setState(newState);
});
}
render() {
return (
<WeatherView weather={this.state.weather}/>
);
}
}
module.exports = Weather;

View File

@ -0,0 +1,21 @@
const React = require('react');
const weatherItem = props => (
<div className="card mui--z1 mui-col-md-6 mui-col-lg-4" id={props.day}>
<div className="mui-col-md-3">
<div className="mui--text-accent mui--text-title day mui--text-center">{ props.day }</div>
<div className="mui--text-dark-secondary mui--text-subhead mui--text-center">{ props.date }</div>
</div>
<div className="mui-col-md-9">
<div>
<i className={`mui--text-headline wi ${props.icon}`}></i>
<span className={`mui--text-display1 temp${ props.tempHigh }`}>{props.tempHigh}°</span> /
<span className={`mui--text-headline temp${ props.tempLow }`}>{props.tempLow}°</span></div>
<div className="mui--text-caption summary">{ props.summary }</div>
</div>
</div>
);
module.exports = weatherItem;

View File

@ -0,0 +1,28 @@
require('es6-promise').polyfill();
require('fetch-everywhere');
const { reduceOpenWeather } = require('../../../common/weatherReducer');
const url = '/weather';
const fetchWeather = () => {
return new Promise(function(resolve, reject) {
fetch(url)
.then(function(response) {
if (response.status >= 400) {
throw new Error('Bad response from server');
reject('error');
}
return response.json();
})
.then(function(data) {
resolve( data.list.map((item) => {
// Reduce the data
return reduceOpenWeather(item);
}));
});
});
};
module.exports = fetchWeather;

View File

@ -0,0 +1,21 @@
const React = require('react');
const WeatherItem = require('../partials/weatherItem');
const WeatherView = function(props) {
return (
<div>
{
props.weather.length === 0 ? ( <div></div>) :
( <div>
{
props.weather.map((item, index) => (
<WeatherItem {...item} />
))
}
</div>
)}
</div>
);
};
module.exports = WeatherView;

21
webpack.config.js Normal file
View File

@ -0,0 +1,21 @@
const webpack = require('webpack');
const path = require('path');
const BUILD_DIR = path.resolve(__dirname, 'src/react/public');
const APP_DIR = path.resolve(__dirname, 'src/react/js');
const config = {
entry: APP_DIR + '/app.js',
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
module: {
loaders: [
{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
{ test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/ }
]
}
};
module.exports = config;