Loading public/stylesheets/style.css +2 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,8 @@ html { body { background-image: url("../assets/SfondoSito.jpg"); background-repeat: no-repeat; background-size: cover; } @media (max-width: 991px) { Loading src/components/App/WrapApp.js +12 −2 Original line number Diff line number Diff line import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { Route, withRouter } from 'react-router-dom'; import { Route, withRouter, Switch } from 'react-router-dom'; import { doGetData } from '../../models/data'; import { doGetTranslations } from '../../models/i18n'; import Navbar from '../Navbar'; import PM from '../PM'; import Home from '../Home'; import Footer from '../Footer'; class WrapApp extends PureComponent { static propTypes = { Loading @@ -23,7 +25,11 @@ class WrapApp extends PureComponent { <div className="app-inner"> <div className="app-inner"> <Navbar lang={this.props.lang} location={this.props.location} dispatch={this.props.dispatch} /> <Switch> <Route path="/" exact component={Home} /> <Route path="/PM" exact component={PM} /> </Switch> <Footer /> </div> </div> ); Loading @@ -34,6 +40,10 @@ class WrapApp extends PureComponent { this.props.dispatch(doGetTranslations(lang)); this.props.dispatch(doGetData()); } componentDidUpdate(prevProps, prevState, snapshot) { console.log('updated WrapApp'); } } function mapStateToProps(state) { Loading src/components/Home/Home.scss +1 −32 Original line number Diff line number Diff line @import "../shared.scss"; @media (min-width: 1200px) { .graphs-group { padding: 1rem; .graph-wrapper { padding: 1rem; margin: 2rem 2rem 0 0; } } } .select { padding:0 0 1rem 1rem; select { background-color: #fff; } } .graphs-group { .graph-wrapper { background-color: #fff; position: relative; margin-bottom: 2rem; padding: 1rem 0; .rv-discrete-color-legend-item { padding: 0.1rem 0.5rem; } } } @import '../shared.scss'; src/components/Home/index.js +2 −218 Original line number Diff line number Diff line import React, { PureComponent } from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import 'react-vis/dist/style.css'; import './Home.scss'; import TempChart from '../charts/TempChart'; import HumChart from '../charts/HumChart'; import PmChart from '../charts/PmChart'; const MILLS_IN_DAY = 60 * 60 * 24 * 1000; const MILLS_IN_WEEK = MILLS_IN_DAY * 7; const MILLS_IN_MONTH = MILLS_IN_DAY * 30; class Home extends PureComponent { static propTypes = { data: PropTypes.object.isRequired }; state = { timeframe: 'last day', width: undefined }; constructor(props) { super(props); this.refCol = React.createRef(); } render() { if (!this.props.data.loaded) { return <div>Loading...</div>; } if (this.props.data.error) { return <div>Ops, unable to load data</div>; } const { timeframe } = this.state; const data = this.props.data.data.filter(item => { let tmin = 0; let tmax = new Date().getTime(); switch (timeframe) { case 'last day': tmin = tmax - MILLS_IN_DAY; break; case 'last week': tmin = tmax - MILLS_IN_WEEK; break; case 'last month': tmin = tmax - MILLS_IN_MONTH; break; case 'last year': tmin = tmax - MILLS_IN_MONTH * 12; break; default: // } const { daily, hour, min } = item; item.ts = new Date(`${daily}T${hour}:${min}:00`); return item.ts > tmin && item.ts < tmax; }); let dataTemp; let dataHum; let dataPm1; let dataPm2_5; let dataPm10; switch (timeframe) { case 'last week': case 'last month': dataTemp = this.getAvg(data, 'temp', item => item.daily); dataHum = this.getAvg(data, 'hum', item => item.daily); dataPm1 = this.getAvg(data, 'pm1', item => item.daily); dataPm2_5 = this.getAvg(data, 'pm2_5', item => item.daily); dataPm10 = this.getAvg(data, 'pm10', item => item.daily); break; case 'last year': dataTemp = this.getAvg(data, 'temp', item => item.year + '-' + item.month + '-01'); dataHum = this.getAvg(data, 'hum', item => item.year + '-' + item.month + '-01'); dataPm1 = this.getAvg(data, 'pm1', item => item.year + '-' + item.month + '-01'); dataPm2_5 = this.getAvg(data, 'pm2_5', item => item.year + '-' + item.month + '-01'); dataPm10 = this.getAvg(data, 'pm10', item => item.year + '-' + item.month + '-01'); break; default: dataTemp = data.map((item, i) => { const { ts, temp } = item; return { x: ts, y: temp }; }); dataHum = data.map((item, i) => { const { ts, hum } = item; return { x: ts, y: hum }; }); dataPm1 = data.map((item, i) => { const { ts, pm1 } = item; return { x: ts, y: pm1 }; }); dataPm2_5 = data.map((item, i) => { const { ts, pm2_5 } = item; return { x: ts, y: pm2_5 }; }); dataPm10 = data.map((item, i) => { const { ts, pm10 } = item; return { x: ts, y: pm10 }; }); } const getDateTime = function(value) { switch (timeframe) { case 'last week': case 'last month': return value.toLocaleDateString(); default: return value.toLocaleDateString() + ' ' + value.toLocaleTimeString(); } }; return ( <div className="home-page"> <div className="container-fluid"> <div className="select"> <h6 style={{ color: '#e3e3e3' }}>Choose timeframe</h6> <select value={timeframe} onChange={e => this.setState({ timeframe: e.target.value })}> <option value="last day">Last day</option> <option value="last week">Last week</option> <option value="last month">Last month</option> <option value="last year">Last year</option> </select> </div> <div className="graphs-group text-center row"> <div className="col-12 col-md-6" ref={this.refCol}> {this.state.width && <TempChart data={dataTemp} getDateTime={getDateTime} width={this.state.width} />} </div> <div className="col-12 col-md-6"> {this.state.width && ( <PmChart dataPm1={dataPm1} dataPm2_5={dataPm2_5} dataPm10={dataPm10} getDateTime={getDateTime} width={this.state.width} /> )} </div> <div className="col-12 col-md-6"> {this.state.width && <HumChart data={dataHum} getDateTime={getDateTime} width={this.state.width} />} </div> </div> </div> </div> ); } componentDidMount() { if (this.refCol && this.refCol.current) { this.setState({ width: this.refCol.current.offsetWidth }); } return <h1>#FuoriComeUnBalcone</h1>; } componentDidUpdate(prevProps, prevState, snapshot) { if (this.state.width === undefined) { if (this.refCol && this.refCol.current) { this.setState({ width: this.refCol.current.offsetWidth }); } } } getAvg(data, field, groupBy) { const _data = []; const _tmp = {}; let lastDay = false; const addItem = what => { _data.push({ x: new Date(`${what}T00:00:00`), y: Math.round(_tmp[what].s / _tmp[what].c, 2) }); }; data.forEach(item => { const daily = groupBy(item); const val = item[field]; if (!_tmp[daily]) { if (lastDay) { addItem(lastDay); } lastDay = daily; _tmp[daily] = { s: val, c: 1, min: val, max: val }; } else { _tmp[daily].s += val; _tmp[daily].c++; if (val > _tmp[daily].max) { _tmp[daily].max = val; } if (val < _tmp[daily].min) { _tmp[daily].min = val; } } }); addItem(lastDay); return _data; } } function mapStateToProps(state) { const { data } = state; return { data }; } export default connect(mapStateToProps)(Home); export default Home; src/components/Navbar/index.js +3 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ class Navbar extends PureComponent { <NavLink strict to="/" exact className="nav-link nav-item"> {I18n.translate('navbar', 'home')} </NavLink> <NavLink strict to="/PM" exact className="nav-link nav-item"> {I18n.translate('navbar', 'PM')} </NavLink> <button onClick={e => { Loading Loading
public/stylesheets/style.css +2 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,8 @@ html { body { background-image: url("../assets/SfondoSito.jpg"); background-repeat: no-repeat; background-size: cover; } @media (max-width: 991px) { Loading
src/components/App/WrapApp.js +12 −2 Original line number Diff line number Diff line import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { Route, withRouter } from 'react-router-dom'; import { Route, withRouter, Switch } from 'react-router-dom'; import { doGetData } from '../../models/data'; import { doGetTranslations } from '../../models/i18n'; import Navbar from '../Navbar'; import PM from '../PM'; import Home from '../Home'; import Footer from '../Footer'; class WrapApp extends PureComponent { static propTypes = { Loading @@ -23,7 +25,11 @@ class WrapApp extends PureComponent { <div className="app-inner"> <div className="app-inner"> <Navbar lang={this.props.lang} location={this.props.location} dispatch={this.props.dispatch} /> <Switch> <Route path="/" exact component={Home} /> <Route path="/PM" exact component={PM} /> </Switch> <Footer /> </div> </div> ); Loading @@ -34,6 +40,10 @@ class WrapApp extends PureComponent { this.props.dispatch(doGetTranslations(lang)); this.props.dispatch(doGetData()); } componentDidUpdate(prevProps, prevState, snapshot) { console.log('updated WrapApp'); } } function mapStateToProps(state) { Loading
src/components/Home/Home.scss +1 −32 Original line number Diff line number Diff line @import "../shared.scss"; @media (min-width: 1200px) { .graphs-group { padding: 1rem; .graph-wrapper { padding: 1rem; margin: 2rem 2rem 0 0; } } } .select { padding:0 0 1rem 1rem; select { background-color: #fff; } } .graphs-group { .graph-wrapper { background-color: #fff; position: relative; margin-bottom: 2rem; padding: 1rem 0; .rv-discrete-color-legend-item { padding: 0.1rem 0.5rem; } } } @import '../shared.scss';
src/components/Home/index.js +2 −218 Original line number Diff line number Diff line import React, { PureComponent } from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import 'react-vis/dist/style.css'; import './Home.scss'; import TempChart from '../charts/TempChart'; import HumChart from '../charts/HumChart'; import PmChart from '../charts/PmChart'; const MILLS_IN_DAY = 60 * 60 * 24 * 1000; const MILLS_IN_WEEK = MILLS_IN_DAY * 7; const MILLS_IN_MONTH = MILLS_IN_DAY * 30; class Home extends PureComponent { static propTypes = { data: PropTypes.object.isRequired }; state = { timeframe: 'last day', width: undefined }; constructor(props) { super(props); this.refCol = React.createRef(); } render() { if (!this.props.data.loaded) { return <div>Loading...</div>; } if (this.props.data.error) { return <div>Ops, unable to load data</div>; } const { timeframe } = this.state; const data = this.props.data.data.filter(item => { let tmin = 0; let tmax = new Date().getTime(); switch (timeframe) { case 'last day': tmin = tmax - MILLS_IN_DAY; break; case 'last week': tmin = tmax - MILLS_IN_WEEK; break; case 'last month': tmin = tmax - MILLS_IN_MONTH; break; case 'last year': tmin = tmax - MILLS_IN_MONTH * 12; break; default: // } const { daily, hour, min } = item; item.ts = new Date(`${daily}T${hour}:${min}:00`); return item.ts > tmin && item.ts < tmax; }); let dataTemp; let dataHum; let dataPm1; let dataPm2_5; let dataPm10; switch (timeframe) { case 'last week': case 'last month': dataTemp = this.getAvg(data, 'temp', item => item.daily); dataHum = this.getAvg(data, 'hum', item => item.daily); dataPm1 = this.getAvg(data, 'pm1', item => item.daily); dataPm2_5 = this.getAvg(data, 'pm2_5', item => item.daily); dataPm10 = this.getAvg(data, 'pm10', item => item.daily); break; case 'last year': dataTemp = this.getAvg(data, 'temp', item => item.year + '-' + item.month + '-01'); dataHum = this.getAvg(data, 'hum', item => item.year + '-' + item.month + '-01'); dataPm1 = this.getAvg(data, 'pm1', item => item.year + '-' + item.month + '-01'); dataPm2_5 = this.getAvg(data, 'pm2_5', item => item.year + '-' + item.month + '-01'); dataPm10 = this.getAvg(data, 'pm10', item => item.year + '-' + item.month + '-01'); break; default: dataTemp = data.map((item, i) => { const { ts, temp } = item; return { x: ts, y: temp }; }); dataHum = data.map((item, i) => { const { ts, hum } = item; return { x: ts, y: hum }; }); dataPm1 = data.map((item, i) => { const { ts, pm1 } = item; return { x: ts, y: pm1 }; }); dataPm2_5 = data.map((item, i) => { const { ts, pm2_5 } = item; return { x: ts, y: pm2_5 }; }); dataPm10 = data.map((item, i) => { const { ts, pm10 } = item; return { x: ts, y: pm10 }; }); } const getDateTime = function(value) { switch (timeframe) { case 'last week': case 'last month': return value.toLocaleDateString(); default: return value.toLocaleDateString() + ' ' + value.toLocaleTimeString(); } }; return ( <div className="home-page"> <div className="container-fluid"> <div className="select"> <h6 style={{ color: '#e3e3e3' }}>Choose timeframe</h6> <select value={timeframe} onChange={e => this.setState({ timeframe: e.target.value })}> <option value="last day">Last day</option> <option value="last week">Last week</option> <option value="last month">Last month</option> <option value="last year">Last year</option> </select> </div> <div className="graphs-group text-center row"> <div className="col-12 col-md-6" ref={this.refCol}> {this.state.width && <TempChart data={dataTemp} getDateTime={getDateTime} width={this.state.width} />} </div> <div className="col-12 col-md-6"> {this.state.width && ( <PmChart dataPm1={dataPm1} dataPm2_5={dataPm2_5} dataPm10={dataPm10} getDateTime={getDateTime} width={this.state.width} /> )} </div> <div className="col-12 col-md-6"> {this.state.width && <HumChart data={dataHum} getDateTime={getDateTime} width={this.state.width} />} </div> </div> </div> </div> ); } componentDidMount() { if (this.refCol && this.refCol.current) { this.setState({ width: this.refCol.current.offsetWidth }); } return <h1>#FuoriComeUnBalcone</h1>; } componentDidUpdate(prevProps, prevState, snapshot) { if (this.state.width === undefined) { if (this.refCol && this.refCol.current) { this.setState({ width: this.refCol.current.offsetWidth }); } } } getAvg(data, field, groupBy) { const _data = []; const _tmp = {}; let lastDay = false; const addItem = what => { _data.push({ x: new Date(`${what}T00:00:00`), y: Math.round(_tmp[what].s / _tmp[what].c, 2) }); }; data.forEach(item => { const daily = groupBy(item); const val = item[field]; if (!_tmp[daily]) { if (lastDay) { addItem(lastDay); } lastDay = daily; _tmp[daily] = { s: val, c: 1, min: val, max: val }; } else { _tmp[daily].s += val; _tmp[daily].c++; if (val > _tmp[daily].max) { _tmp[daily].max = val; } if (val < _tmp[daily].min) { _tmp[daily].min = val; } } }); addItem(lastDay); return _data; } } function mapStateToProps(state) { const { data } = state; return { data }; } export default connect(mapStateToProps)(Home); export default Home;
src/components/Navbar/index.js +3 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ class Navbar extends PureComponent { <NavLink strict to="/" exact className="nav-link nav-item"> {I18n.translate('navbar', 'home')} </NavLink> <NavLink strict to="/PM" exact className="nav-link nav-item"> {I18n.translate('navbar', 'PM')} </NavLink> <button onClick={e => { Loading