diff --git a/client/config/development/webpack.js b/client/config/development/webpack.js index 87af036..c71a86c 100644 --- a/client/config/development/webpack.js +++ b/client/config/development/webpack.js @@ -25,7 +25,7 @@ module.exports = { loader: 'json' }, { test: /\.rt/, - loader: "react-templates-loader" + loader: "react-templates-loader?targetVersion=0.14.0" } ] }, diff --git a/client/dashboard/energy/energy.component.js b/client/dashboard/energy/energy.component.js index 264c930..a7d1df3 100644 --- a/client/dashboard/energy/energy.component.js +++ b/client/dashboard/energy/energy.component.js @@ -1,6 +1,5 @@ import React from 'react'; import Templates from 'config/templates'; -import House from './../../models/house'; import {RouteHelper} from './../routes'; class EnergyComponent extends React.Component { @@ -8,34 +7,14 @@ class EnergyComponent extends React.Component { constructor(props){ super(props); var energy = this; - energy.state = { - loading_energy_data: true - }; } componentDidMount(){ - var energy = this, - house = energy.context.house; - if (!house || energy.context.loading_energy_data) return false; - house.setEnergyData() - .then(()=>{ - energy.setState({loading_energy_data: false}); - }); + var energy = this; } componentDidUpdate(prev_props, prev_state, prev_context){ - var energy = this, - house = energy.context.house; - if (!house) return false; - if (!prev_context.house || - prev_context.house.data.id != energy.context.house.data.id || - !house.matchesYearState(prev_props.params)) { - energy.setState({loading_energy_data: true}); - house.setEnergyData() - .then(()=>{ - energy.setState({loading_energy_data: false}); // will update graph or table. - }); - } + var energy = this; } setParam(event){ @@ -43,19 +22,9 @@ class EnergyComponent extends React.Component { param = event.target.dataset.param, value = event.target.dataset.value, update = {}, route_helper; - override[param] = value; - route_helper = new RouteHelper(energy.context.house, energy.props); - if (route_helper.routeUpdated()){ - route_helper.updateHouseState(); - energy.context.router.push(makeRoute(house, energy.props, override)); - } - } - - getChildContext(){ - var layout = this; - return { - loading_energy_data: layout.state.loading_energy_data - }; + update[param] = value; + route_helper = new RouteHelper(energy.props, update); + if (route_helper.routeUpdated()) route_helper.updateRoute(); } render() { @@ -64,13 +33,7 @@ class EnergyComponent extends React.Component { } } - -EnergyComponent.childContextTypes = { - loading_energy_data: React.PropTypes.bool.isRequired -}; - EnergyComponent.contextTypes = { - house: React.PropTypes.instanceOf(House), router: React.PropTypes.object.isRequired }; diff --git a/client/dashboard/energy/energy.rt b/client/dashboard/energy/energy.rt index 89b1a94..659567b 100644 --- a/client/dashboard/energy/energy.rt +++ b/client/dashboard/energy/energy.rt @@ -1,5 +1,5 @@
-
+
Retrieving energy data...
@@ -8,13 +8,13 @@
diff --git a/client/dashboard/energy/graph/graph.component.js b/client/dashboard/energy/graph/graph.component.js index 8683695..929da07 100644 --- a/client/dashboard/energy/graph/graph.component.js +++ b/client/dashboard/energy/graph/graph.component.js @@ -7,26 +7,27 @@ import House from './../../../models/house'; class GraphComponent extends React.Component { componentDidMount(){ - var energy_graph = this, - house = energy_graph.context.house; - if (!energy_graph.context.loading_energy_data) energy_graph.updateGraph(); + var energy_graph = this; + if (energy_graph.house) energy_graph.updateGraph(); + } + + get house(){ + return this.props.location.state && this.props.location.state.house; } componentDidUpdate(prev_props, prev_state, prev_context){ - var energy_graph = this, - house = energy_graph.context.house; - if (energy_graph.context.loading_energy_data) {return false;} - if (!prev_context.house || - prev_context.loading_energy_data || - prev_context.house.id != energy_graph.context.house.id) { - energy_graph.updateGraph(); - } + var energy_graph = this; + if (energy_graph.shouldUpdateGraph(prev_props)) { energy_graph.updateGraph(); } } + shouldUpdateGraph(prev_props){ + var energy_graph = this; + return energy_graph.house && !prev_props.location.state.house || + prev_props.location.state.house.id != energy_graph.house.id; + } updateGraph(){ var energy_graph = this, - house = energy_graph.context.house, graph_attr = energy_graph.props.params.graph_attr; if (energy_graph.graph === undefined){ @@ -56,7 +57,7 @@ class GraphComponent extends React.Component { css_class: '', min_range: 0, max_range: 150, - values: house.energy_data + values: energy_graph.house.energy_data }); } @@ -68,8 +69,6 @@ class GraphComponent extends React.Component { } GraphComponent.contextTypes = { - house: React.PropTypes.instanceOf(House), - loading_energy_data: React.PropTypes.bool.isRequired, router: React.PropTypes.object.isRequired }; diff --git a/client/dashboard/energy/table/table.component.js b/client/dashboard/energy/table/table.component.js index 9a7d596..d45f8a9 100644 --- a/client/dashboard/energy/table/table.component.js +++ b/client/dashboard/energy/table/table.component.js @@ -13,7 +13,6 @@ class TableComponent extends React.Component { } TableComponent.contextTypes = { - house: React.PropTypes.instanceOf(House), router: React.PropTypes.object.isRequired }; diff --git a/client/dashboard/energy/table/table.rt b/client/dashboard/energy/table/table.rt index 72a6da7..6d042e5 100644 --- a/client/dashboard/energy/table/table.rt +++ b/client/dashboard/energy/table/table.rt @@ -1,4 +1,4 @@ - +
@@ -8,7 +8,7 @@ - + diff --git a/client/dashboard/house/house.component.js b/client/dashboard/house/house.component.js index c75e99f..034f141 100644 --- a/client/dashboard/house/house.component.js +++ b/client/dashboard/house/house.component.js @@ -10,23 +10,26 @@ class HouseComponent extends React.Component { constructor(props){ super(props); this.renders = 0; + this.updates = 0; + } + + get house(){ + return this.props.location.state && this.props.location.state.house; } setParam(event){ var house_component = this, - house = house_component.context.house, param = event.target.dataset.param, value = event.target.dataset.value, update = {}, route_helper; update[param] = value; - route_helper = new RouteHelper(house, house_component.props, update); - if (route_helper.routeUpdated()){ - route_helper.updateHouseState(); - if (house_component.renders < 10){ - house_component.context.router.push(route_helper.newRoute()); - house_component.renders += 1; - } - } + route_helper = new RouteHelper(house_component.props, update); + if (route_helper.routeUpdated()) route_helper.updateRoute(); + } + + componentDidUpdate(){ + this.updates += 1; + console.log(this.updates, ') HouseComponent#componentDidUpdate'); } graphSelected(){ @@ -57,7 +60,6 @@ class HouseComponent extends React.Component { }; HouseComponent.contextTypes = { - house: React.PropTypes.instanceOf(House), router: React.PropTypes.object.isRequired }; diff --git a/client/dashboard/house/house.rt b/client/dashboard/house/house.rt index e2bb0e5..d83635f 100644 --- a/client/dashboard/house/house.rt +++ b/client/dashboard/house/house.rt @@ -31,16 +31,16 @@ type="button" class="btn btn-primary">Table -
+

Select dates:


diff --git a/client/dashboard/layout/layout.component.js b/client/dashboard/layout/layout.component.js index 502afb5..a7ccaba 100644 --- a/client/dashboard/layout/layout.component.js +++ b/client/dashboard/layout/layout.component.js @@ -12,8 +12,13 @@ class LayoutComponent extends React.Component { this.state = { houses: null, house: null, - requesting_data: true + loading_house_data: true }; + this.updates = 0 + } + + get house(){ + return this.props.location.state && this.props.location.state.house; } componentDidMount() { @@ -22,30 +27,34 @@ class LayoutComponent extends React.Component { var house = null; if (layout.props.params.house_id != undefined){ house = houses.find((h)=>{ return h.data.id == layout.props.params.house_id; }); - var route_helper = new RouteHelper(house, layout.props); - if (route_helper.paramsHaveDateState()) route_helper.updateHouseToParams(); } layout.setState({ houses: houses, - requesting_data: false, - house: house }); + loading_house_data: false + }, ()=>{ + if (house){ + var route_helper = new RouteHelper(layout.context.router, layout.props, {house: house}); + route_helper.updateRoute(); + } + }); }); } + componentDidUpdate(){ + var layout = this; + + this.updates += 1; + console.log(this.updates, ') LayoutComponent#componentDidUpdate'); + } + setHouse(event){ var layout = this, - house_id = event.target.value, - old_house = layout.state.house, - house = layout.state.houses.find((house)=>{ return house.data.id == house_id }); - if (!old_house || old_house.id != house_id){ - var route_helper = new RouteHelper(house, layout.props); - route_helper.updateHouseToParams(); - layout.setState({house: house}, ()=>{ - if (layout.renders < 10){ - layout.context.router.push(route_helper.newRoute()); - layout.renders += 1 - } - if (old_house) old_house.closeDb(); + house_id = event.target.value; + if (!layout.house || layout.house.id != house_id){ + House.ensureHouses().then((houses)=>{ + var new_house = houses.find((h)=>{ return h.data.id == house_id }), + route_helper = new RouteHelper(layout.context.router, layout.props, {house: new_house}); + route_helper.updateRoute(); }); } } @@ -63,11 +72,6 @@ class LayoutComponent extends React.Component { }); } - getChildContext(){ - var layout = this; - return {house: layout.state.house}; - } - render() { var layoutRt = Templates.forComponent('layout'); return layoutRt.call(this); @@ -78,7 +82,4 @@ LayoutComponent.contextTypes = { router: React.PropTypes.object.isRequired }; -LayoutComponent.childContextTypes = { - house: React.PropTypes.instanceOf(House) -}; export default LayoutComponent; diff --git a/client/dashboard/layout/layout.rt b/client/dashboard/layout/layout.rt index 68578d2..1c81e6d 100644 --- a/client/dashboard/layout/layout.rt +++ b/client/dashboard/layout/layout.rt @@ -1,11 +1,11 @@
-
Retrieving houses...
+
Retrieving houses...

Select household:

- + {this.props.children}
diff --git a/client/dashboard/power/graph/graph.component.js b/client/dashboard/power/graph/graph.component.js index 3854725..8a4e016 100644 --- a/client/dashboard/power/graph/graph.component.js +++ b/client/dashboard/power/graph/graph.component.js @@ -7,23 +7,28 @@ import SplineStackChart from './../../../d3/line/spline_stack'; class GraphComponent extends React.Component { componentDidMount(){ - var power_graph = this, - house = power_graph.context.house; + var power_graph = this; power_graph.graph_title = ' '; - if (!power_graph.context.loading_power_data) power_graph.updateGraph(); + if (power_graph.house) power_graph.updateGraph(); + } + + get house(){ + return this.props.location.state && this.props.location.state.house; } componentDidUpdate(prev_props, prev_state, prev_context){ - var power_graph = this, - house = power_graph.context.house; - if (power_graph.context.loading_power_data) {return false;} - if (!prev_context.house || - prev_context.loading_power_data || - prev_context.house.id != power_graph.context.house.id) { + var power_graph = this; + if (power_graph.shouldUpdateGraph(prev_props)) { power_graph.updateGraph(); } } + shouldUpdateGraph(prev_props){ + var power_graph = this; + return (power_graph.house && !prev_props.location.state.house || + prev_props.location.state.house.id != power_graph.props.location.state.house.id); + } + updateGraph(){ var power_graph = this, house = power_graph.context.house; @@ -83,8 +88,6 @@ class GraphComponent extends React.Component { } GraphComponent.contextTypes = { - house: React.PropTypes.instanceOf(House), - loading_power_data: React.PropTypes.bool.isRequired, router: React.PropTypes.object.isRequired }; diff --git a/client/dashboard/power/power.component.js b/client/dashboard/power/power.component.js index 137d7da..faf1c0b 100644 --- a/client/dashboard/power/power.component.js +++ b/client/dashboard/power/power.component.js @@ -12,36 +12,43 @@ class PowerComponent extends React.Component { constructor(props){ super(props); var power = this; - power.state = { - loading_power_data: true }; power.updates = 0; } + get house(){ + console.log('PowerComponent#get house', this.props.location.state && this.props.location.state.house) + return this.props.location.state && this.props.location.state.house; + } + componentDidMount(){ var power = this, - house = power.context.house; + house = power.props.location.state.house; + + console.log(this.updates, ') PowerComponent#componentDidMount') + console.log(this.house) power.renders = 0; if (!house) return false; power.initDateRange(); - house.setPowerData() - .then(()=>{ - power.setState({loading_power_data: false }); }); } componentDidUpdate(prev_props, prev_state, prev_context){ + this.updates += 1 + console.log(this.updates, ') PowerComponent#componentDidUpdate') + console.log(this.house) var power = this, - house = power.context.house; - if (!house) return false; - var route_helper = new RouteHelper(house, power.props); - if ((!prev_context.house || prev_context.house.data.id != power.context.house.data.id) || - !house.matchesPowerRange(prev_props.location.query['dates[]'] || [])) { - power.setState({loading_power_data: true}); - house.setPowerData() - .then(()=>{ - power.initDateRange(); - power.setState({loading_power_data: false}); // will update graph or table. - }); - } else if (!house.matchesMonthState(prev_props.params)) power.initDateRange(); + route_helper = new RouteHelper(power.props); + if (!route_helper.house) return false; + if (power.shouldInitDateRange(prev_props)) { + power.initDateRange(); + } + } + + shouldInitDateRange(prev_props){ + var power = this, + route_helper = new RouteHelper(power.props); + return !prev_props.location.state.house || + prev_props.location.state.house.data.id != power.context.house.data.id || + !route_helper.house.matchesPowerRange(prev_props.params, prev_props.location.query['dates[]'] || []); } initDateRange(){ @@ -69,8 +76,7 @@ class PowerComponent extends React.Component { var power_range = [Math.round(min.getTime() / 1000), Math.round(max.getTime() / 1000)], route_helper = new RouteHelper(house, power.props, {power_range: power_range}); - route_helper.updateHouseState(); - power.context.router.push(route_helper.newRoute()); + route_helper.updateRoute(); }, 500); }; power.date_range_slider.drawData({ @@ -95,25 +101,13 @@ class PowerComponent extends React.Component { } } - getChildContext(){ - var layout = this; - return { - loading_power_data: layout.state.loading_power_data - }; - } - render() { var powerRt = Templates.forComponent('power'); return powerRt.call(this); } } -PowerComponent.childContextTypes = { - loading_power_data: React.PropTypes.bool.isRequired -}; - PowerComponent.contextTypes = { - house: React.PropTypes.instanceOf(House), router: React.PropTypes.object.isRequired }; diff --git a/client/dashboard/power/power.rt b/client/dashboard/power/power.rt index d18a796..ebd6513 100644 --- a/client/dashboard/power/power.rt +++ b/client/dashboard/power/power.rt @@ -1,16 +1,16 @@
-
+
Retrieving power data...
diff --git a/client/dashboard/power/table/table.component.js b/client/dashboard/power/table/table.component.js index 51471b2..10d81e7 100644 --- a/client/dashboard/power/table/table.component.js +++ b/client/dashboard/power/table/table.component.js @@ -12,7 +12,6 @@ class TableComponent extends React.Component { } TableComponent.contextTypes = { - house: React.PropTypes.instanceOf(House), router: React.PropTypes.object.isRequired }; diff --git a/client/dashboard/routes.js b/client/dashboard/routes.js index a44be41..f9fcf8b 100644 --- a/client/dashboard/routes.js +++ b/client/dashboard/routes.js @@ -42,13 +42,19 @@ export const ROUTES = [{ export class RouteHelper { - constructor(house, props, update){ + constructor(router, props, update){ + update = update || {}; var route_helper = this; - route_helper.house = house; route_helper.props = props; + route_helper.router = router; route_helper.update = update || {}; } + get house(){ + var route_helper = this; + return route_helper.update.house || route_helper.props.location.state && route_helper.props.location.state.house; + } + get view(){ var route_helper = this; return route_helper.update.view || (route_helper.tableSelected() ? 'table' : 'graph'); @@ -65,8 +71,13 @@ export class RouteHelper { } get power_range(){ - var route_helper = this; - return route_helper.update.power_range || route_helper.props.location.query['dates[]']; + var route_helper = this, + range = route_helper.update.power_range || route_helper.props.location.query.dates; + if (range) { + range[0] = +range[0]; + range[1] = +range[1]; + } + return range; } get date_params(){ @@ -76,11 +87,22 @@ export class RouteHelper { year: route_helper.update.year || route_helper.house.year }; } + get new_state(){ + var route_helper = this; + return Object.keys(route_helper.update).reduce((state, key)=>{ + if (['house'].indexOf(key) >= 0) state[key] = route_helper.update[key]; + return state; + }, {}); + } + + + // compare house state to updates or params. routeUpdated(){ var route_helper = this, house = route_helper.house; return (route_helper.energySelected() && !house.matchesYearState(route_helper.date_params)) || - (route_helper.powerSelected() && !house.matchesMonthState(route_helper.date_params) || !house.matchesPowerRange(route_helper.power_range)); + (route_helper.powerSelected() && !house.matchesMonthState(route_helper.date_params) || !house.matchesPowerRange(route_helper.power_range)) && + (!route_helper.update.view || route_helper.update.view !== route_helper.view); } // This will update the house state acccording to passed update parameters. @@ -88,24 +110,25 @@ export class RouteHelper { var route_helper = this, house = route_helper.house; house.setMonthState(route_helper.date_params, route_helper.update.power_range); + if (route_helper.energySelected()){ + route_helper.router.push({state: {loading_energy_data: true}}) + return house.setEnergyData().then(()=>{ return {loading_energy_data: false} }); + } else if (route_helper.powerSelected()) { + route_helper.router.push({state: {loading_power_data: true}}) + return house.setPowerData().then(()=>{ return {loading_power_data: false} }); + } else return Promise.resolve({}); } - paramsHaveDateState(){ + updateRoute(){ var route_helper = this; - return !!route_helper.props.params.year; - } - - // This will update the house according to URL parameters. - updateHouseToParams(){ - var route_helper = this, - house = route_helper.house, - power_range; - if (route_helper.props.location.query['dates[]']){ - power_range = []; - power_range[0] = +route_helper.props.location.query['dates[]'][0]; - power_range[1] = +route_helper.props.location.query['dates[]'][1]; - } - house.setMonthState(route_helper.props.params, power_range); + return route_helper.updateHouseState() + .then((data_state)=>{ + route_helper.router.push({ + pathname: route_helper.newRoute(), + query: route_helper.newQuery(), + state: Object.assign(data_state, route_helper.new_state) + }); + }); } // should be run AFTER updateHouseState is called. @@ -115,10 +138,16 @@ export class RouteHelper { if (route_helper.dataset === 'energy'){ return `/houses/${house.data.id}/energy/${house.state.year}/${route_helper.graph_attr}/${route_helper.view}`; } else { - return `/houses/${house.data.id}/power/${house.state.month}/${house.state.year}/${route_helper.view}?${jQuery.param({dates: house.state.power_range})}`; + return `/houses/${house.data.id}/power/${house.state.month}/${house.state.year}/${route_helper.view}`; } } + newQuery(){ + var route_helper = this; + if (route_helper.dataset === 'power') return {dates: route_helper.house.state.power_range}; + else return {}; + } + graphSelected(){ return RouteHelper.graphSelected(this.props.routes); } diff --git a/client/models/house.js b/client/models/house.js index ee9b589..06ac46a 100644 --- a/client/models/house.js +++ b/client/models/house.js @@ -133,9 +133,9 @@ class House { return params.month == house.state.month && params.year == house.state.year; } - matchesPowerRange(dates){ + matchesPowerRange(params, dates){ var house = this; - return house.state.power_range[0] == dates[0] && house.state.power_range[1] == dates[1]; + return house.matchesMonthState(params) && house.state.power_range[0] == dates[0] && house.state.power_range[1] == dates[1]; } offset_diff(unix){ diff --git a/server/app.express.js b/server/app.express.js index 47f6fe7..910d64c 100644 --- a/server/app.express.js +++ b/server/app.express.js @@ -62,20 +62,9 @@ import logger from 'morgan'; app.use(favicon(__dirname + '/public/favicon.ico')); app.use(logger('dev')); -// serve fonts in /assets/fonts -import assets from "connect-assets"; - // TODO: These routes need to match references in the bootstrap and font awesome files. app.use("/assets/fonts", express.static("bootstrap/dist/fonts")); app.use("/assets/fonts", express.static("font-awesome/fonts")); -// serve compiled vendor assets and application.css. -app.use(assets({ - paths: ["./../node_modules"], - build: true, - buildDir: false, - // compile: false, - compress: true -})); // serve public static files. dev_server.app.use('/', express.static(path.resolve(__dirname, 'public')));
{energy_datum.day_to_s} {energy_datum.consumption_to_s}