1
0
mirror of https://github.com/home-assistant/frontend.git synced 2025-12-24 12:49:19 +00:00

Remove last ES6

This commit is contained in:
Paulus Schoutsen
2016-07-18 21:28:42 -07:00
parent 57f40725d9
commit 43940d067a
38 changed files with 1522 additions and 1491 deletions

View File

@@ -1 +1,220 @@
<link rel="import" href="../../bower_components/polymer/polymer.html">
<script>
(function () {
'use strict';
function range(start, end) {
var result = [];
for (let i = start; i < end; i++) {
result.push(i);
}
return result;
}
function saveParseFloat(value) {
var parsed = parseFloat(value);
return !isNaN(parsed) && isFinite(parsed) ? parsed : null;
}
Polymer({
is: 'state-history-chart-line',
properties: {
data: {
type: Object,
observer: 'dataChanged',
},
unit: {
type: String,
},
isSingleDevice: {
type: Boolean,
value: false,
},
isAttached: {
type: Boolean,
value: false,
observer: 'dataChanged',
},
chartEngine: {
type: Object,
},
},
created: function () {
this.style.display = 'block';
},
attached: function () {
this.isAttached = true;
},
dataChanged: function () {
this.drawChart();
},
drawChart: function () {
var unit = this.unit;
var deviceStates = this.data;
var options;
var startTime;
var endTime;
var dataTables;
var finalDataTable;
if (!this.isAttached) {
return;
}
if (!this.chartEngine) {
this.chartEngine = new window.google.visualization.LineChart(this);
}
if (deviceStates.length === 0) {
return;
}
options = {
legend: { position: 'top' },
interpolateNulls: true,
titlePosition: 'none',
vAxes: {
// Adds units to the left hand side of the graph
0: { title: unit },
},
hAxis: {
format: 'H:mm',
},
chartArea: { left: '60', width: '95%' },
explorer: {
actions: ['dragToZoom', 'rightClickToReset', 'dragToPan'],
keepInBounds: true,
axis: 'horizontal',
maxZoomIn: 0.1,
},
};
if (this.isSingleDevice) {
options.legend.position = 'none';
options.vAxes[0].title = null;
options.chartArea.left = 40;
options.chartArea.height = '80%';
options.chartArea.top = 5;
options.enableInteractivity = false;
}
startTime = new Date(Math.min.apply(null, deviceStates.map(function (states) {
return states[0].lastChangedAsDate;
})));
endTime = new Date(startTime);
endTime.setDate(endTime.getDate() + 1);
if (endTime > new Date()) {
endTime = new Date();
}
dataTables = deviceStates.map(function (states) {
var last = states[states.length - 1];
var domain = last.domain;
var name = last.entityDisplay;
var data = [];
var dataTable = new window.google.visualization.DataTable();
// array containing [time, value1, value2, etc]
var prevValues;
var hasTargetRange;
var processState;
var noInterpolations;
dataTable.addColumn({ type: 'datetime', id: 'Time' });
function pushData(values, noInterpolationValues) {
if (prevValues && noInterpolationValues) {
// if we have to prevent interpolation, we add an old value for each
// value that should not be interpolated at the same time that our new
// line will be published.
data.push([values[0]].concat(prevValues.slice(1).map(
function (val, index) {
return noInterpolationValues[index] ? val : null;
})));
}
data.push(values);
prevValues = values;
}
if (domain === 'thermostat') {
// We differentiate between thermostats that have a target temperature
// range versus ones that have just a target temperature
hasTargetRange = states.reduce(
(cum, cur) => cum || cur.attributes.target_temp_high !== cur.attributes.target_temp_low,
false);
dataTable.addColumn('number', `${name} current temperature`);
if (hasTargetRange) {
dataTable.addColumn('number', `${name} target temperature high`);
dataTable.addColumn('number', `${name} target temperature low`);
noInterpolations = [false, true, true];
processState = function (state) {
var curTemp = saveParseFloat(state.attributes.current_temperature);
var targetHigh = saveParseFloat(state.attributes.target_temp_high);
var targetLow = saveParseFloat(state.attributes.target_temp_low);
pushData([state.lastUpdatedAsDate, curTemp, targetHigh, targetLow], noInterpolations);
};
} else {
dataTable.addColumn('number', `${name} target temperature`);
noInterpolations = [false, true];
processState = function (state) {
var curTemp = saveParseFloat(state.attributes.current_temperature);
var target = saveParseFloat(state.attributes.temperature);
pushData([state.lastUpdatedAsDate, curTemp, target], noInterpolations);
};
}
states.forEach(processState);
} else {
dataTable.addColumn('number', name);
// Only disable interpolation for sensors
noInterpolations = domain !== 'sensor' && [true];
states.forEach(function (state) {
var value = saveParseFloat(state.state);
pushData([state.lastChangedAsDate, value], noInterpolations);
});
}
// Add an entry for final values
pushData([endTime].concat(prevValues.slice(1)), false);
dataTable.addRows(data);
return dataTable;
});
if (dataTables.length === 1) {
finalDataTable = dataTables[0];
} else {
finalDataTable = dataTables.slice(1).reduce(
function (tot, cur) {
return window.google.visualization.data.join(
tot, cur, 'full', [[0, 0]],
range(1, tot.getNumberOfColumns()),
range(1, cur.getNumberOfColumns()));
},
dataTables[0]);
}
this.chartEngine.draw(finalDataTable, options);
},
});
}());
</script>

View File

@@ -1,206 +0,0 @@
import Polymer from '../polymer';
function range(start, end) {
const result = [];
for (let i = start; i < end; i++) {
result.push(i);
}
return result;
}
function saveParseFloat(value) {
const parsed = parseFloat(value);
return !isNaN(parsed) && isFinite(parsed) ? parsed : null;
}
export default new Polymer({
is: 'state-history-chart-line',
properties: {
data: {
type: Object,
observer: 'dataChanged',
},
unit: {
type: String,
},
isSingleDevice: {
type: Boolean,
value: false,
},
isAttached: {
type: Boolean,
value: false,
observer: 'dataChanged',
},
chartEngine: {
type: Object,
},
},
created() {
this.style.display = 'block';
},
attached() {
this.isAttached = true;
},
dataChanged() {
this.drawChart();
},
drawChart() {
if (!this.isAttached) {
return;
}
if (!this.chartEngine) {
this.chartEngine = new window.google.visualization.LineChart(this);
}
const unit = this.unit;
const deviceStates = this.data;
if (deviceStates.length === 0) {
return;
}
const options = {
legend: { position: 'top' },
interpolateNulls: true,
titlePosition: 'none',
vAxes: {
// Adds units to the left hand side of the graph
0: { title: unit },
},
hAxis: {
format: 'H:mm',
},
chartArea: { left: '60', width: '95%' },
explorer: {
actions: ['dragToZoom', 'rightClickToReset', 'dragToPan'],
keepInBounds: true,
axis: 'horizontal',
maxZoomIn: 0.1,
},
};
if (this.isSingleDevice) {
options.legend.position = 'none';
options.vAxes[0].title = null;
options.chartArea.left = 40;
options.chartArea.height = '80%';
options.chartArea.top = 5;
options.enableInteractivity = false;
}
const startTime = new Date(Math.min.apply(
null, deviceStates.map(states => states[0].lastChangedAsDate)));
let endTime = new Date(startTime);
endTime.setDate(endTime.getDate() + 1);
if (endTime > new Date()) {
endTime = new Date();
}
const dataTables = deviceStates.map(states => {
const last = states[states.length - 1];
const domain = last.domain;
const name = last.entityDisplay;
const dataTable = new window.google.visualization.DataTable();
dataTable.addColumn({ type: 'datetime', id: 'Time' });
const data = [];
// array containing [time, value1, value2, etc]
let prevValues;
function pushData(values, noInterpolations) {
if (prevValues && noInterpolations) {
// if we have to prevent interpolation, we add an old value for each
// value that should not be interpolated at the same time that our new
// line will be published.
data.push([values[0]].concat(prevValues.slice(1).map(
(val, index) => (noInterpolations[index] ? val : null))));
}
data.push(values);
prevValues = values;
}
if (domain === 'thermostat') {
// We differentiate between thermostats that have a target temperature
// range versus ones that have just a target temperature
const hasTargetRange = states.reduce(
(cum, cur) => cum || cur.attributes.target_temp_high !== cur.attributes.target_temp_low,
false);
dataTable.addColumn('number', `${name} current temperature`);
let processState;
if (hasTargetRange) {
dataTable.addColumn('number', `${name} target temperature high`);
dataTable.addColumn('number', `${name} target temperature low`);
const noInterpolations = [false, true, true];
processState = state => {
const curTemp = saveParseFloat(state.attributes.current_temperature);
const targetHigh = saveParseFloat(state.attributes.target_temp_high);
const targetLow = saveParseFloat(state.attributes.target_temp_low);
pushData([state.lastUpdatedAsDate, curTemp, targetHigh, targetLow], noInterpolations);
};
} else {
dataTable.addColumn('number', `${name} target temperature`);
const noInterpolations = [false, true];
processState = state => {
const curTemp = saveParseFloat(state.attributes.current_temperature);
const target = saveParseFloat(state.attributes.temperature);
pushData([state.lastUpdatedAsDate, curTemp, target], noInterpolations);
};
}
states.forEach(processState);
} else {
dataTable.addColumn('number', name);
// Only disable interpolation for sensors
const noInterpolation = domain !== 'sensor' && [true];
states.forEach(state => {
const value = saveParseFloat(state.state);
pushData([state.lastChangedAsDate, value], noInterpolation);
});
}
// Add an entry for final values
pushData([endTime].concat(prevValues.slice(1)), false);
dataTable.addRows(data);
return dataTable;
});
let finalDataTable;
if (dataTables.length === 1) {
finalDataTable = dataTables[0];
} else {
finalDataTable = dataTables.slice(1).reduce(
(tot, cur) => window.google.visualization.data.join(
tot, cur, 'full', [[0, 0]],
range(1, tot.getNumberOfColumns()),
range(1, cur.getNumberOfColumns())),
dataTables[0]);
}
this.chartEngine.draw(finalDataTable, options);
},
});

View File

@@ -1,10 +1,122 @@
<link rel="import" href="../../bower_components/polymer/polymer.html">
<dom-module is='state-history-chart-timeline'>
<style>
:host {
display: block;
<script>
Polymer({
is: 'state-history-chart-timeline',
properties: {
data: {
type: Object,
observer: 'dataChanged',
},
isAttached: {
type: Boolean,
value: false,
observer: 'dataChanged',
},
},
created: function () {
this.style.display = 'block';
},
attached: function () {
this.isAttached = true;
},
dataChanged: function () {
this.drawChart();
},
drawChart: function () {
var root = Polymer.dom(this);
var stateHistory = this.data;
var chart;
var dataTable;
var startTime;
var endTime;
var numTimelines;
if (!this.isAttached) {
return;
}
</style>
<template></template>
</dom-module>
while (root.node.lastChild) {
root.node.removeChild(root.node.lastChild);
}
if (!stateHistory || stateHistory.length === 0) {
return;
}
chart = new window.google.visualization.Timeline(this);
dataTable = new window.google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Entity' });
dataTable.addColumn({ type: 'string', id: 'State' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
function addRow(entityDisplay, stateStr, start, end) {
var stateDisplay = stateStr.replace(/_/g, ' ');
dataTable.addRow([entityDisplay, stateDisplay, start, end]);
}
startTime = new Date(
stateHistory.reduce(
function (minTime, stateInfo) {
return Math.min(minTime, stateInfo[0].lastChangedAsDate);
}, new Date()));
// end time is Math.min(curTime, start time + 1 day)
endTime = new Date(startTime);
endTime.setDate(endTime.getDate() + 1);
if (endTime > new Date()) {
endTime = new Date();
}
numTimelines = 0;
// stateHistory is a list of lists of sorted state objects
stateHistory.forEach(function (stateInfo) {
var entityDisplay;
var newLastChanged;
var prevState = null;
var prevLastChanged = null;
if (stateInfo.length === 0) return;
entityDisplay = stateInfo[0].entityDisplay;
stateInfo.forEach(function (state) {
if (prevState !== null && state.state !== prevState) {
newLastChanged = state.lastChangedAsDate;
addRow(entityDisplay, prevState, prevLastChanged, newLastChanged);
prevState = state.state;
prevLastChanged = newLastChanged;
} else if (prevState === null) {
prevState = state.state;
prevLastChanged = state.lastChangedAsDate;
}
});
addRow(entityDisplay, prevState, prevLastChanged, endTime);
numTimelines++;
});
chart.draw(dataTable, {
height: 55 + (numTimelines * 42),
timeline: {
showRowLabels: stateHistory.length > 1,
},
hAxis: {
format: 'H:mm',
},
});
},
});
</script>

View File

@@ -1,109 +0,0 @@
import Polymer from '../polymer';
export default new Polymer({
is: 'state-history-chart-timeline',
properties: {
data: {
type: Object,
observer: 'dataChanged',
},
isAttached: {
type: Boolean,
value: false,
observer: 'dataChanged',
},
},
attached() {
this.isAttached = true;
},
dataChanged() {
this.drawChart();
},
drawChart() {
if (!this.isAttached) {
return;
}
const root = Polymer.dom(this);
const stateHistory = this.data;
while (root.node.lastChild) {
root.node.removeChild(root.node.lastChild);
}
if (!stateHistory || stateHistory.length === 0) {
return;
}
const chart = new window.google.visualization.Timeline(this);
const dataTable = new window.google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Entity' });
dataTable.addColumn({ type: 'string', id: 'State' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
function addRow(entityDisplay, stateStr, start, end) {
const stateDisplay = stateStr.replace(/_/g, ' ');
dataTable.addRow([entityDisplay, stateDisplay, start, end]);
}
const startTime = new Date(
stateHistory.reduce((minTime, stateInfo) => Math.min(
minTime, stateInfo[0].lastChangedAsDate), new Date())
);
// end time is Math.min(curTime, start time + 1 day)
let endTime = new Date(startTime);
endTime.setDate(endTime.getDate() + 1);
if (endTime > new Date()) {
endTime = new Date();
}
let numTimelines = 0;
// stateHistory is a list of lists of sorted state objects
stateHistory.forEach((stateInfo) => {
if (stateInfo.length === 0) return;
const entityDisplay = stateInfo[0].entityDisplay;
/* eslint-disable prefer-const */
let newLastChanged;
/* eslint-enable prefer-const */
let prevState = null;
let prevLastChanged = null;
stateInfo.forEach((state) => {
if (prevState !== null && state.state !== prevState) {
newLastChanged = state.lastChangedAsDate;
addRow(entityDisplay, prevState, prevLastChanged, newLastChanged);
prevState = state.state;
prevLastChanged = newLastChanged;
} else if (prevState === null) {
prevState = state.state;
prevLastChanged = state.lastChangedAsDate;
}
});
addRow(entityDisplay, prevState, prevLastChanged, endTime);
numTimelines++;
});
chart.draw(dataTable, {
height: 55 + (numTimelines * 42),
timeline: {
showRowLabels: stateHistory.length > 1,
},
hAxis: {
format: 'H:mm',
},
});
},
});

View File

@@ -25,7 +25,7 @@
<template>
<google-legacy-loader on-api-load="googleApiLoaded"></google-legacy-loader>
<div hidden$="{{!isLoading}}" class='loading-container'>
<div hidden$="[[!isLoading]]" class='loading-container'>
<loading-box>Updating history data</loading-box>
</div>
@@ -40,10 +40,116 @@
</state-history-chart-timeline>
<template is='dom-repeat' items='[[groupedStateHistory.line]]'>
<state-history-chart-line unit='[[extractUnit(item)]]'
data='[[extractData(item)]]' is-single-device='[[isSingleDevice]]'>
<state-history-chart-line
unit='[[item.unit]]'
data='[[item.data]]'
is-single-device='[[isSingleDevice]]'>
</state-history-chart-line>
</template>
</div>
</template>
</dom-module>
<script>
Polymer({
is: 'state-history-charts',
properties: {
stateHistory: {
type: Object,
},
isLoadingData: {
type: Boolean,
value: false,
},
apiLoaded: {
type: Boolean,
value: false,
},
isLoading: {
type: Boolean,
computed: 'computeIsLoading(isLoadingData, apiLoaded)',
},
groupedStateHistory: {
type: Object,
computed: 'computeGroupedStateHistory(isLoading, stateHistory)',
},
isSingleDevice: {
type: Boolean,
computed: 'computeIsSingleDevice(stateHistory)',
},
},
computeIsSingleDevice: function (stateHistory) {
return stateHistory && stateHistory.size === 1;
},
computeGroupedStateHistory: function (isLoading, stateHistory) {
var lineChartDevices = {};
var timelineDevices = [];
var unitStates;
if (isLoading || !stateHistory) {
return { line: [], timeline: [] };
}
stateHistory.forEach(function (stateInfo) {
var stateWithUnit;
var unit;
if (!stateInfo || stateInfo.size === 0) {
return;
}
stateWithUnit = stateInfo.find(
(state) => 'unit_of_measurement' in state.attributes);
unit = stateWithUnit ?
stateWithUnit.attributes.unit_of_measurement : false;
if (!unit) {
timelineDevices.push(stateInfo.toArray());
} else if (unit in lineChartDevices) {
lineChartDevices[unit].push(stateInfo.toArray());
} else {
lineChartDevices[unit] = [stateInfo.toArray()];
}
});
timelineDevices = timelineDevices.length > 0 && timelineDevices;
unitStates = Object.keys(lineChartDevices).map(
function (unit) {
return { unit: unit, data: lineChartDevices[unit] };
});
return { line: unitStates, timeline: timelineDevices };
},
googleApiLoaded: function () {
window.google.load('visualization', '1', {
packages: ['timeline', 'corechart'],
callback: function () {
this.apiLoaded = true;
}.bind(this),
});
},
computeContentClasses: function (isLoading) {
return isLoading ? 'loading' : '';
},
computeIsLoading: function (isLoadingData, apiLoaded) {
return isLoadingData || !apiLoaded;
},
computeIsEmpty: function (stateHistory) {
return stateHistory && stateHistory.size === 0;
},
});
</script>

View File

@@ -1,106 +0,0 @@
import Polymer from '../polymer';
import './state-history-chart-timeline';
import './state-history-chart-line';
export default new Polymer({
is: 'state-history-charts',
properties: {
stateHistory: {
type: Object,
},
isLoadingData: {
type: Boolean,
value: false,
},
apiLoaded: {
type: Boolean,
value: false,
},
isLoading: {
type: Boolean,
computed: 'computeIsLoading(isLoadingData, apiLoaded)',
},
groupedStateHistory: {
type: Object,
computed: 'computeGroupedStateHistory(isLoading, stateHistory)',
},
isSingleDevice: {
type: Boolean,
computed: 'computeIsSingleDevice(stateHistory)',
},
},
computeIsSingleDevice(stateHistory) {
return stateHistory && stateHistory.size === 1;
},
computeGroupedStateHistory(isLoading, stateHistory) {
if (isLoading || !stateHistory) {
return { line: [], timeline: [] };
}
const lineChartDevices = {};
let timelineDevices = [];
stateHistory.forEach((stateInfo) => {
if (!stateInfo || stateInfo.size === 0) {
return;
}
const stateWithUnit = stateInfo.find(
(state) => 'unit_of_measurement' in state.attributes);
const unit = stateWithUnit ?
stateWithUnit.attributes.unit_of_measurement : false;
if (!unit) {
timelineDevices.push(stateInfo.toArray());
} else if (unit in lineChartDevices) {
lineChartDevices[unit].push(stateInfo.toArray());
} else {
lineChartDevices[unit] = [stateInfo.toArray()];
}
});
timelineDevices = timelineDevices.length > 0 && timelineDevices;
const unitStates = Object.keys(lineChartDevices).map(
(unit) => [unit, lineChartDevices[unit]]);
return { line: unitStates, timeline: timelineDevices };
},
googleApiLoaded() {
window.google.load('visualization', '1', {
packages: ['timeline', 'corechart'],
callback: () => { this.apiLoaded = true; },
});
},
computeContentClasses(isLoading) {
return isLoading ? 'loading' : '';
},
computeIsLoading(isLoadingData, apiLoaded) {
return isLoadingData || !apiLoaded;
},
computeIsEmpty(stateHistory) {
return stateHistory && stateHistory.size === 0;
},
extractUnit(arr) {
return arr[0];
},
extractData(arr) {
return arr[1];
},
});