diff --git a/css/dashboard.css b/css/dashboard.css index 9a26383..0f1421e 100644 --- a/css/dashboard.css +++ b/css/dashboard.css @@ -497,6 +497,7 @@ input[type=range]::-moz-range-thumb { .icon.menu_down:before { content: "\F035D"; } .icon.menu_up:before { content: "\F0360"; } .icon.message:before { content: "\F0361"; } +.icon.microscope:before { content: "\F0654"; } .icon.moon_waning_crescent:before { content: "\F0F65"; } .icon.network_strength_4:before { content: "\F08FA"; } .icon.network_strength_off:before { content: "\F08FC"; } @@ -542,6 +543,7 @@ input[type=range]::-moz-range-thumb { .icon.thermometer:before { content: "\F050F"; } .icon.thermostat:before { content: "\F0393"; } .icon.thumb_up:before { content: "\F0513"; } +.icon.trash_can:before { content: "\F0A79"; } .icon.tune:before { content: "\F062E"; } .icon.twitter:before { content: "\F0544"; } .icon.undo:before { content: "\F054C"; } diff --git a/js/component/card/manage_thermostats.js b/js/component/card/manage_thermostats.js new file mode 100644 index 0000000..de9b512 --- /dev/null +++ b/js/component/card/manage_thermostats.js @@ -0,0 +1,122 @@ +/** + * Setting + */ +beestat.component.card.manage_thermostats = function() { + beestat.component.card.apply(this, arguments); +}; +beestat.extend(beestat.component.card.manage_thermostats, beestat.component.card); + +/** + * Decorate contents. + * + * @param {rocket.Elements} parent Parent + */ +beestat.component.card.manage_thermostats.prototype.decorate_contents_ = function(parent) { + var p = document.createElement('p'); + p.innerText = 'Thermostats directly connected to your ecobee account are automatically added and synced. In some cases, shared thermostats cannot be automatically detected. Add them here.'; + parent.appendChild(p); + + // Existing + (new beestat.component.title('Existing Thermostats')).render(parent); + + var sorted_thermostats = $.values(beestat.cache.thermostat) + .sort(function(a, b) { + return a.name > b.name; + }); + + const table = document.createElement('table'); + sorted_thermostats.forEach(function(thermostat) { + const ecobee_thermostat = beestat.cache.ecobee_thermostat[thermostat.ecobee_thermostat_id]; + + const tr = document.createElement('tr'); + + const td_name = document.createElement('td'); + const td_identifier = document.createElement('td'); + const td_delete = document.createElement('td'); + + td_name.innerText = thermostat.name; + td_identifier.innerText = ecobee_thermostat.identifier; + + const tile_delete = new beestat.component.tile() + .set_icon('trash_can') + .set_shadow(false) + .set_text_color(beestat.style.color.red.base) + .render($(td_delete)); + + tile_delete.addEventListener('click', function() { + console.info('delete'); + }) + + tr.appendChild(td_name); + tr.appendChild(td_identifier); + tr.appendChild(td_delete); + + table.appendChild(tr); + }); + + parent.appendChild(table); + + // New + (new beestat.component.title('Add Thermostat')).render(parent); + + const container = document.createElement('div'); + parent.appendChild(container); + + Object.assign(container.style, { + 'display': 'flex', + 'flex-direction': 'row', + 'grid-gap': `${beestat.style.size.gutter}px`, + }); + + const input_container = document.createElement('div'); + container.appendChild(input_container); + + new_identifier = new beestat.component.input.text() + .set_width(150) + .set_maxlength(12) + .set_placeholder('Serial #') + .render($(input_container)); + + const button_container = document.createElement('div'); + container.appendChild(button_container); + + const tile_add = new beestat.component.tile() + .set_background_color(beestat.style.color.green.base) + .set_background_hover_color(beestat.style.color.green.light) + .set_text_color('#fff') + .set_text('Add Thermostat') + .render($(button_container)); + + // TODO: Add thermostat button needs to make an API call. That call should + // look for an existing inactive thermostat on the account and add it back. + // If it doesn't exist, it should do an API call to ecobee to "sync" that + // thermostat which should immediately grab all of that data and create the + // rows for me using my existing code. Throw a loading spinner over the + // manage thermostats card while this happens, then call get thermostats when + // that's done to update beestat's cache. +}; + +/** + * Get the title of the card. + * + * @return {string} The title. + */ +beestat.component.card.manage_thermostats.prototype.get_title_ = function() { + return 'Manage Thermostats'; +}; + +/** + * Decorate the menu + * + * @param {rocket.Elements} parent + */ +beestat.component.card.manage_thermostats.prototype.decorate_top_right_ = function(parent) { + var menu = (new beestat.component.menu()).render(parent); + + menu.add_menu_item(new beestat.component.menu_item() + .set_text('Help') + .set_icon('help_circle') + .set_callback(function() { + window.open('TODO'); + })); +}; diff --git a/js/component/card/rookstack_survey_notification.js b/js/component/card/rookstack_survey_notification.js new file mode 100644 index 0000000..2fa957c --- /dev/null +++ b/js/component/card/rookstack_survey_notification.js @@ -0,0 +1,90 @@ +/** + * Blue banner asking people to check out a research opportunity. + */ +beestat.component.card.rookstack_survey_notification = function() { + var self = this; + + beestat.dispatcher.addEventListener([ + 'setting.display_2024_equipment_sizing_study_rookstack' + ], function() { + self.rerender(); + }); + + beestat.component.card.apply(this, arguments); +}; +beestat.extend(beestat.component.card.rookstack_survey_notification, beestat.component.card); + +beestat.component.card.rookstack_survey_notification.prototype.decorate_contents_ = function(parent) { + var self = this; + + // Don't render anything if the user is an active Patron. + if (beestat.component.card.rookstack_survey_notification.should_show() === false) { + window.setTimeout(function() { + self.dispose(); + }, 0); + return; + } + + parent.style('background', beestat.style.color.blue.base); + + + new beestat.component.tile() + .set_icon('microscope') + .set_size('large') + .set_text([ + 'I am interested in participating', + 'Learn more' + ]) + .set_background_color(beestat.style.color.blue.dark) + .set_background_hover_color(beestat.style.color.blue.light) + .addEventListener('click', function() { + beestat.setting('clicked_2024_equipment_sizing_study_rookstack', moment().utc().format('YYYY-MM-DD HH:mm:ss')); + window.open('https://docs.google.com/presentation/d/1OY8RR6hMeL86ODH5LdxfrZ_es7nnRDq3cG-1qIfS7XI/present#slide=id.p', '_blank'); + }) + .render(parent); +}; + +/** + * Get the title of the card. + * + * @return {string} The title. + */ +beestat.component.card.rookstack_survey_notification.prototype.get_title_ = function() { + return 'Research Opportunity'; +}; + +/** + * Get the subtitle of the card. + * + * @return {string} The subtitle. + */ +beestat.component.card.rookstack_survey_notification.prototype.get_subtitle_ = function() { + return 'Purdue University is looking for participants in a U.S. Department of Energy funded study that aims to develop and Artificial Intelligence solution to residential heating and cooling equipment sizing.'; +}; + +/** + * Decorate the close button. + * + * @param {rocket.Elements} parent + */ +beestat.component.card.rookstack_survey_notification.prototype.decorate_top_right_ = function(parent) { + new beestat.component.tile() + .set_type('pill') + .set_shadow(false) + .set_icon('close') + .set_text_color('#fff') + .set_background_hover_color(beestat.style.color.blue.light) + .addEventListener('click', function() { + beestat.setting('display_2024_equipment_sizing_study_rookstack', false); + }) + .render(parent); +}; + +/** + * Determine whether or not this card should be shown. + * + * @return {boolean} Whether or not to show the card. + */ +beestat.component.card.rookstack_survey_notification.should_show = function() { + return beestat.setting('display_2024_equipment_sizing_study_rookstack') === true; +}; diff --git a/js/js.php b/js/js.php index 0312ee5..bfe39fc 100755 --- a/js/js.php +++ b/js/js.php @@ -88,6 +88,7 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd echo '' . PHP_EOL; echo '' . PHP_EOL; echo '' . PHP_EOL; + echo '' . PHP_EOL; echo '' . PHP_EOL; echo '' . PHP_EOL; echo '' . PHP_EOL; @@ -102,6 +103,7 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd echo '' . PHP_EOL; echo '' . PHP_EOL; echo '' . PHP_EOL; + echo '' . PHP_EOL; echo '' . PHP_EOL; echo '' . PHP_EOL; echo '' . PHP_EOL; diff --git a/js/layer/detail.js b/js/layer/detail.js index 2340d14..74695b2 100644 --- a/js/layer/detail.js +++ b/js/layer/detail.js @@ -33,6 +33,15 @@ beestat.layer.detail.prototype.decorate_ = function(parent) { ]); } + // Manage Thermostats + cards.push([ + { + // 'card': new beestat.component.card.manage_thermostats(), + 'card': new beestat.component.card.rookstack_survey_notification(), + 'size': 12 + } + ]); + cards.push([ { 'card': new beestat.component.card.system(thermostat.thermostat_id), diff --git a/js/layer/settings.js b/js/layer/settings.js index 37d5ade..85cee1e 100644 --- a/js/layer/settings.js +++ b/js/layer/settings.js @@ -39,6 +39,14 @@ beestat.layer.settings.prototype.decorate_ = function(parent) { } ]); + // Manage Thermostats + // cards.push([ + // { + // 'card': new beestat.component.card.manage_thermostats(), + // 'size': 12 + // } + // ]); + // Footer cards.push([ {