mirror of
https://github.com/beestat/app.git
synced 2025-05-24 02:14:03 -04:00
449 lines
13 KiB
JavaScript
449 lines
13 KiB
JavaScript
/**
|
|
* Single alert.
|
|
*/
|
|
beestat.component.alert = function(alert) {
|
|
this.alert_ = alert;
|
|
beestat.component.apply(this, arguments);
|
|
};
|
|
beestat.extend(beestat.component.alert, beestat.component);
|
|
|
|
beestat.component.alert.prototype.decorate_ = function(parent) {
|
|
this.decorate_main_(parent);
|
|
this.decorate_detail_(parent);
|
|
};
|
|
|
|
/**
|
|
* Decorate the main alert icon and text.
|
|
*
|
|
* @param {rocket.Elements} parent
|
|
*/
|
|
beestat.component.alert.prototype.decorate_main_ = function(parent) {
|
|
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
|
|
|
|
this.alert_main_ = $.createElement('div')
|
|
.style({
|
|
'display': 'flex',
|
|
'cursor': 'pointer',
|
|
'transition': 'all 200ms ease',
|
|
'margin': '0 -' + beestat.style.size.gutter + 'px',
|
|
'padding-left': beestat.style.size.gutter,
|
|
'padding-right': beestat.style.size.gutter,
|
|
'overflow': 'hidden'
|
|
});
|
|
parent.appendChild(this.alert_main_);
|
|
|
|
if (this.should_show() === true) {
|
|
this.show();
|
|
} else {
|
|
/*
|
|
* This causes flicker but ensures that everything actually gets a height.
|
|
* Not perfect but trying it for now.
|
|
*/
|
|
this.hide();
|
|
}
|
|
|
|
this.add_event_listeners_();
|
|
|
|
var icon_name;
|
|
switch (this.alert_.code) {
|
|
case 100000:
|
|
case 100001:
|
|
icon_name = 'tune';
|
|
break;
|
|
case 611: // Invalid registration password
|
|
icon_name = 'key';
|
|
break;
|
|
case 1000: // Cold temp alert
|
|
case 1006: // Problem with cooling
|
|
case 1013: // Sensor activated disabling AC
|
|
icon_name = 'snowflake';
|
|
break;
|
|
case 1001: // Hot temp alert
|
|
case 1003: // Problem with furnace/boiler heating
|
|
case 1004: // Problem with heatpump heating
|
|
case 1005: // Problem with heatpump heating
|
|
case 1009: // Problem with aux heat, running too much
|
|
case 1010: // Aux heat used with high outdoor temp
|
|
case 1018: // Sensor activated shutting down aux heat
|
|
case 1022: // Sensor activated shutting down heat
|
|
icon_name = 'fire';
|
|
break;
|
|
case 1007: // Communication to EI failed
|
|
case 1028: // Remote sensor not communicating
|
|
icon_name = 'wifi_strength_1_alert';
|
|
break;
|
|
case 6301: // Network join failed
|
|
icon_name = 'close_network';
|
|
break;
|
|
case 1002: // Sensor activated shutting down compressor
|
|
case 1011: // Sensor activated switching to occupied
|
|
icon_name = 'eye';
|
|
break;
|
|
case 1012: // Sensor activated switching to unoccupied
|
|
icon_name = 'eye_off';
|
|
break;
|
|
case 1017: // Sensor activated turning on fan
|
|
icon_name = 'fan';
|
|
break;
|
|
case 1020: // Low humidity alert
|
|
case 1021: // High humidity alert
|
|
case 1024: // Sensor activated humidifier
|
|
case 1032: // Faulty humidity sensor
|
|
case 1033: // Faulty humidity sensor
|
|
case 1025: // Sensor activated dehumidifier
|
|
icon_name = 'water_percent';
|
|
break;
|
|
case 1026: // Low battery
|
|
icon_name = 'battery_10';
|
|
break;
|
|
case 1029: // Remote sensor re-established
|
|
case 6300: // Network join successful
|
|
icon_name = 'wifi_strength_4';
|
|
break;
|
|
case 3130: // Furnace maintenance reminder
|
|
case 3131: // Humidifier maintenance reminder
|
|
case 3132: // Ventilator maintenance reminder
|
|
case 3133: // Dehumidifier maintenance reminder
|
|
case 3134: // Economizer maintenance reminder
|
|
case 3135: // UV maintenance reminder
|
|
case 3136: // AC maintenance reminder
|
|
case 3137: // Air filter reminder (ClimateMaster only)
|
|
case 3138: // Air cleaner reminder (ClimateMaster only)
|
|
case 3140: // Hvac maintenance reminder
|
|
icon_name = 'calendar_alert';
|
|
break;
|
|
case 6200: // Monthly cost exceeded
|
|
case 6201: // Monthly projected cost exceeded
|
|
icon_name = 'cash';
|
|
break;
|
|
case 1034: // Incorrect Zigbee module installed
|
|
icon_name = 'zigbee';
|
|
break;
|
|
case 7002: // Web initiated messages - such as Utility welcome message or similar
|
|
icon_name = 'message';
|
|
break;
|
|
default:
|
|
|
|
/*
|
|
* 1014 Sensor activated setting temp up/down
|
|
* 1015 Sensor activated
|
|
* 1016 Sensor activated opening/closing relay
|
|
* 1019 Sensor activated shutting down heating/cooling
|
|
* 1027 Remote sensor detected
|
|
* 1030 Invalid current temp reading
|
|
* 1031 Current temp reading restored
|
|
* 4000 ClimateTalk
|
|
* 6000 DR voluntary alert
|
|
* 6001 DR voluntary utility message
|
|
* 6100 DR mandatory alert
|
|
* 6101 DR mandatory message
|
|
* 6102 DR mandatory alert
|
|
* 7000 Registration confirmation
|
|
* 7001 Registration Remind me alert
|
|
* 9000 ClimateMaster fault
|
|
* 9255 ClimateMaster fault max
|
|
* 9500 ClimateMaster disconnected
|
|
* 9755 ClimateMaster disconnected max
|
|
* 8300 - 8599 ClimateMaster Heatpump/hardware Unit Alerts
|
|
* 4100 - 4199 ClimateTalk device alert major/minor fault codes
|
|
* 4200 - 4299 ClimateTalk device lost communications
|
|
* 4300 - 4399 ClimateTalk system message from device
|
|
* 6002 - 6005 DR voluntary alerts
|
|
* 8000 - 8299 Daikin Indoor/Outdoor Unit Alerts
|
|
*/
|
|
icon_name = 'bell';
|
|
break;
|
|
}
|
|
|
|
(new beestat.component.icon(icon_name)).render(this.alert_main_);
|
|
|
|
/*
|
|
* Since all other temperature conversions are done client-side, do this one
|
|
* here too...
|
|
*/
|
|
if (thermostat.temperature_unit === '°C') {
|
|
if (this.alert_.code === 100000 || this.alert_.code === 100001) {
|
|
this.alert_.text = this.alert_.text.replace('0.5°F', '0.3°C');
|
|
this.alert_.text = this.alert_.text.replace('1.0°F', '0.8°C');
|
|
}
|
|
}
|
|
|
|
var text = $.createElement('div')
|
|
.style({
|
|
'padding-left': (beestat.style.size.gutter / 2)
|
|
})
|
|
.innerHTML(this.alert_.text);
|
|
this.alert_main_.appendChild(text);
|
|
};
|
|
|
|
/**
|
|
* Decorate the detail that appears when you click on an alert.
|
|
*
|
|
* @param {rocket.Elements} parent
|
|
*/
|
|
beestat.component.alert.prototype.decorate_detail_ = function(parent) {
|
|
var self = this;
|
|
|
|
// Detail
|
|
this.alert_detail_ = $.createElement('div')
|
|
.style({
|
|
'max-height': '0',
|
|
'overflow': 'hidden'
|
|
});
|
|
parent.appendChild(this.alert_detail_);
|
|
|
|
var row;
|
|
|
|
row = $.createElement('div').style({
|
|
'display': 'flex',
|
|
'margin-top': (beestat.style.size.gutter / 2),
|
|
'margin-bottom': (beestat.style.size.gutter / 2)
|
|
});
|
|
this.alert_detail_.appendChild(row);
|
|
|
|
var source = $.createElement('div').style('width', '50%');
|
|
row.appendChild(source);
|
|
source.appendChild($.createElement('div')
|
|
.innerHTML('Source')
|
|
.style('font-weight', beestat.style.font_weight.bold));
|
|
source.appendChild($.createElement('div').innerHTML(this.alert_.source));
|
|
|
|
var date = $.createElement('div').style('width', '50%');
|
|
row.appendChild(date);
|
|
date.appendChild($.createElement('div')
|
|
.innerHTML('Date')
|
|
.style('font-weight', beestat.style.font_weight.bold));
|
|
var timestamp = moment(this.alert_.timestamp);
|
|
date.appendChild($.createElement('div').innerHTML(timestamp.format('MMM M')));
|
|
// date.appendChild($.createElement('div').innerHTML(timestamp.format('MMM M @ h:mm a')));
|
|
|
|
var details = $.createElement('div');
|
|
this.alert_detail_.appendChild(details);
|
|
details.appendChild($.createElement('div')
|
|
.innerHTML('Details')
|
|
.style('font-weight', beestat.style.font_weight.bold));
|
|
details.appendChild(
|
|
$.createElement('div')
|
|
.style('margin-bottom', beestat.style.size.gutter)
|
|
.innerText(this.alert_.details)
|
|
);
|
|
|
|
// Actions
|
|
var button_container = $.createElement('div')
|
|
.style({
|
|
'text-align': 'center'
|
|
});
|
|
details.appendChild(button_container);
|
|
|
|
// Dismiss
|
|
var dismiss_container = $.createElement('div')
|
|
.style({
|
|
'display': 'inline-block'
|
|
});
|
|
button_container.appendChild(dismiss_container);
|
|
|
|
(new beestat.component.button())
|
|
.set_icon('bell_off')
|
|
.set_text('Dismiss')
|
|
.set_background_color(beestat.style.color.red.dark)
|
|
.set_background_hover_color(beestat.style.color.red.light)
|
|
.render(dismiss_container)
|
|
.addEventListener('click', function() {
|
|
new beestat.api()
|
|
.add_call(
|
|
'thermostat',
|
|
'dismiss_alert',
|
|
{
|
|
'thermostat_id': beestat.setting('thermostat_id'),
|
|
'guid': self.alert_.guid
|
|
}
|
|
)
|
|
.send();
|
|
|
|
beestat.cache.thermostat[beestat.setting('thermostat_id')].alerts.forEach(function(alert) {
|
|
if (alert.guid === self.alert_.guid) {
|
|
alert.dismissed = true;
|
|
}
|
|
});
|
|
|
|
restore_container.style('display', 'inline-block');
|
|
dismiss_container.style('display', 'none');
|
|
|
|
self.dispatchEvent('dismiss');
|
|
});
|
|
|
|
// Restore
|
|
var restore_container = $.createElement('div')
|
|
.style({
|
|
'display': 'inline-block'
|
|
});
|
|
button_container.appendChild(restore_container);
|
|
|
|
(new beestat.component.button())
|
|
.set_icon('bell')
|
|
.set_text('Restore')
|
|
.set_background_color(beestat.style.color.red.dark)
|
|
.set_background_hover_color(beestat.style.color.red.light)
|
|
.render(restore_container)
|
|
.addEventListener('click', function() {
|
|
new beestat.api()
|
|
.add_call(
|
|
'thermostat',
|
|
'restore_alert',
|
|
{
|
|
'thermostat_id': beestat.setting('thermostat_id'),
|
|
'guid': self.alert_.guid
|
|
}
|
|
)
|
|
.send();
|
|
|
|
beestat.cache.thermostat[beestat.setting('thermostat_id')].alerts.forEach(function(alert) {
|
|
if (alert.guid === self.alert_.guid) {
|
|
alert.dismissed = false;
|
|
}
|
|
});
|
|
|
|
restore_container.style('display', 'none');
|
|
dismiss_container.style('display', 'inline-block');
|
|
|
|
self.dispatchEvent('restore');
|
|
});
|
|
|
|
if (this.alert_.dismissed === true) {
|
|
dismiss_container.style('display', 'none');
|
|
} else {
|
|
restore_container.style('display', 'none');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Add the appropriate event listeners.
|
|
*/
|
|
beestat.component.alert.prototype.add_event_listeners_ = function() {
|
|
var self = this;
|
|
|
|
this.alert_main_.addEventListener('mouseover', function() {
|
|
self.alert_main_.style({
|
|
'background': beestat.style.color.red.dark
|
|
});
|
|
});
|
|
|
|
this.alert_main_.addEventListener('mouseout', function() {
|
|
self.alert_main_.style({
|
|
'background': ''
|
|
});
|
|
});
|
|
|
|
this.alert_main_.addEventListener('click', function() {
|
|
self.dispatchEvent('click');
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Show the alert. After the transition runs to restore the original height,
|
|
* the height gets set to auto to fix any problems. For example, if you
|
|
* collapse all the elements, then shrink your browser, then go back,
|
|
* everything will get restored to the original (now wrong) heights.
|
|
*/
|
|
beestat.component.alert.prototype.show = function() {
|
|
var self = this;
|
|
|
|
if (
|
|
this.should_show() === true
|
|
) {
|
|
this.alert_main_.style({
|
|
'height': this.height_,
|
|
'padding-top': (beestat.style.size.gutter / 2),
|
|
'padding-bottom': (beestat.style.size.gutter / 2)
|
|
});
|
|
|
|
window.setTimeout(function() {
|
|
self.alert_main_.style('height', 'auto');
|
|
}, 200);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Whether or not this alert is marked as dismissed.
|
|
*
|
|
* @return {boolean}
|
|
*/
|
|
/*
|
|
* beestat.component.alert.prototype.is_dismissed = function() {
|
|
* return this.alert_.dismissed;
|
|
* };
|
|
*/
|
|
|
|
/**
|
|
* Whether or not the alert should be shown based on it's properties and the
|
|
* current settings.
|
|
*
|
|
* @return {boolean}
|
|
*/
|
|
beestat.component.alert.prototype.should_show = function() {
|
|
return (
|
|
this.alert_.dismissed === false ||
|
|
beestat.setting('show_dismissed_alerts') === true
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Hide the alert. This gets the element's current height, sets that height,
|
|
* then changes the height to 0. This is because you can't run a transition on
|
|
* a height of auto and I don't have a fixed height for this element.
|
|
*/
|
|
beestat.component.alert.prototype.hide = function() {
|
|
var self = this;
|
|
|
|
this.height_ = this.alert_main_.getBoundingClientRect().height;
|
|
this.alert_main_.style('height', this.height_);
|
|
|
|
window.setTimeout(function() {
|
|
self.alert_main_.style({
|
|
'height': '0',
|
|
'padding-top': '0',
|
|
'padding-bottom': '0'
|
|
});
|
|
}, 0);
|
|
};
|
|
|
|
/**
|
|
* Expand the alert; removes event listeners basically so it's static. Also
|
|
* changes the transition speed on alert detail. When pinning something want
|
|
* the expand to go slower to help prevent a jumpy resize of the parent.
|
|
*/
|
|
beestat.component.alert.prototype.expand = function() {
|
|
this.alert_main_
|
|
.style({
|
|
'background': beestat.style.color.red.dark,
|
|
'cursor': 'default'
|
|
})
|
|
.removeEventListener('mouseover')
|
|
.removeEventListener('mouseout')
|
|
.removeEventListener('click');
|
|
|
|
this.alert_detail_.style({
|
|
'transition': 'all 400ms ease',
|
|
'max-height': '250px'
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Collapse the alert; re-adds the event listeners. Also changes the
|
|
* transition speed on alert detail. When unpinning something want the
|
|
* collapse to go faster to help prevent a jumpy resize of the parent.
|
|
*/
|
|
beestat.component.alert.prototype.collapse = function() {
|
|
this.alert_main_
|
|
.style({
|
|
'background': '',
|
|
'cursor': 'pointer'
|
|
});
|
|
this.add_event_listeners_();
|
|
|
|
this.alert_detail_.style({
|
|
'transition': 'all 100ms ease',
|
|
'max-height': '0'
|
|
});
|
|
};
|