From 7b4cbfee1d5c3660f67bb624f2e3f51958348058 Mon Sep 17 00:00:00 2001 From: Jon Ziebell Date: Sun, 19 Jun 2022 22:06:33 -0400 Subject: [PATCH] Added ability to customize profile start date --- api/profile.php | 22 ++++++-- js/beestat/api.js | 12 ++++- js/component/card/settings.js | 99 ++++++++++++++++++++++++++++++++++- js/component/input/text.js | 4 ++ 4 files changed, 132 insertions(+), 5 deletions(-) diff --git a/api/profile.php b/api/profile.php index 87180a2..c96c425 100644 --- a/api/profile.php +++ b/api/profile.php @@ -10,8 +10,8 @@ class profile extends cora\api { public static $exposed = [ - 'private' => [], - 'public' => ['generate'] + 'private' => ['generate'], + 'public' => [] ]; public static $cache = []; @@ -126,6 +126,14 @@ class profile extends cora\api { 'get_setting', 'thermostat.' . $thermostat_id . '.profile.ignore_solar_gain' ); + /** + * Allow a custom start date. + */ + $custom_range_begin = $this->api( + 'user', + 'get_setting', + 'thermostat.' . $thermostat_id . '.profile.range_begin' + ); if($thermostat['system_type']['reported']['heat']['equipment'] !== null) { $system_type_heat = $thermostat['system_type']['reported']['heat']['equipment']; @@ -152,7 +160,15 @@ class profile extends cora\api { // Figure out all the starting and ending times. Round begin/end to the // nearest 5 minutes to help with the looping later on. $end_timestamp = time(); - $begin_timestamp = strtotime('-1 year', $end_timestamp); + + if($custom_range_begin !== null) { + $begin_timestamp = max( + strtotime($custom_range_begin), + strtotime('-1 year', $end_timestamp) + ); + } else { + $begin_timestamp = strtotime('-1 year', $end_timestamp); + } // Round to 5 minute intervals. $begin_timestamp = floor($begin_timestamp / 300) * 300; diff --git a/js/beestat/api.js b/js/beestat/api.js index 45388e6..86cbd5c 100644 --- a/js/beestat/api.js +++ b/js/beestat/api.js @@ -116,10 +116,20 @@ beestat.api.prototype.send = function(opt_api_call) { * @param {string=} opt_alias Optional alias (required for batch API calls). * @param {boolean=} opt_bypass_cache_read Optional bypass of cache read. * @param {boolean=} opt_bypass_cache_write Optional bypass of cache write. + * @param {boolean=} opt_clear_cache Optional flag to just clear the cache for + * an API call. * * @return {beestat.api} This. */ -beestat.api.prototype.add_call = function(resource, method, opt_args, opt_alias, opt_bypass_cache_read, opt_bypass_cache_write, opt_clear_cache) { +beestat.api.prototype.add_call = function( + resource, + method, + opt_args, + opt_alias, + opt_bypass_cache_read, + opt_bypass_cache_write, + opt_clear_cache +) { var api_call = { 'resource': resource, 'method': method, diff --git a/js/component/card/settings.js b/js/component/card/settings.js index 3369fdf..b4f79fa 100644 --- a/js/component/card/settings.js +++ b/js/component/card/settings.js @@ -60,7 +60,10 @@ beestat.component.card.settings.prototype.decorate_contents_ = function(parent) parent.appendChild( $.createElement('p') - .style('font-weight', '400') + .style({ + 'font-weight': '400', + 'margin-top': (beestat.style.size.gutter * 2) + 'px' + }) .innerText('Temperature Profiles') ); const ignore_solar_gain = new beestat.component.input.checkbox(); @@ -76,6 +79,10 @@ beestat.component.card.settings.prototype.decorate_contents_ = function(parent) ignore_solar_gain_key, ignore_solar_gain.get_value(), function() { + /** + * Clear the API call cache and delete the profile so it regenerates + * next time you go to the page. + */ new beestat.api() .add_call( 'thermostat', @@ -117,6 +124,96 @@ beestat.component.card.settings.prototype.decorate_contents_ = function(parent) } ); }); + + // Temperature profile begin/end + const temperature_profiles_range_begin_key = 'thermostat.' + thermostat.thermostat_id + '.profile.range_begin'; + + parent.appendChild( + $.createElement('p') + .innerText('Custom Start Date') + ); + + var temperature_profiles_range_begin = new beestat.component.input.text() + .set_style({ + 'width': 110, + 'text-align': 'center', + 'border-bottom': '2px solid ' + beestat.style.color.lightblue.base + }) + .set_attribute({ + 'maxlength': 10 + }) + .set_icon('calendar'); + + var temperature_profiles_range_begin_m = + moment(beestat.setting(temperature_profiles_range_begin_key)); + + if (temperature_profiles_range_begin_m.isValid() === true) { + temperature_profiles_range_begin.set_value( + temperature_profiles_range_begin_m.format('M/D/YYYY') + ); + } + + temperature_profiles_range_begin.addEventListener('change', function() { + var m = moment(this.get_value()); + var temperature_profiles_range_begin_value; + if (m.isValid() === true) { + this.set_value(m.format('M/D/YYYY')); + temperature_profiles_range_begin_value = m.format('YYYY-MM-DD'); + } else { + this.set_value(''); + temperature_profiles_range_begin_value = null; + } + + beestat.setting( + temperature_profiles_range_begin_key, + temperature_profiles_range_begin_value, + function() { + /** + * Clear the API call cache and delete the profile so it regenerates + * next time you go to the page. + */ + new beestat.api() + .add_call( + 'thermostat', + 'generate_profile', + { + 'thermostat_id': thermostat.thermostat_id + }, + undefined, + undefined, + undefined, + // Clear cache + true + ) + .add_call( + 'thermostat', + 'update', + { + 'attributes': { + 'thermostat_id': thermostat.thermostat_id, + 'profile': null + } + } + ) + .add_call( + 'thermostat', + 'read_id', + { + 'attributes': { + 'inactive': 0 + } + }, + 'thermostat' + ) + .set_callback(function(response) { + beestat.cache.set('thermostat', response.thermostat); + }) + .send(); + } + ); + }); + + temperature_profiles_range_begin.render(parent); }; /** diff --git a/js/component/input/text.js b/js/component/input/text.js index b79f0b8..b44339e 100644 --- a/js/component/input/text.js +++ b/js/component/input/text.js @@ -20,6 +20,10 @@ beestat.component.input.text = function() { }); }); + this.input_.addEventListener('change', function() { + self.dispatchEvent('change'); + }); + beestat.component.input.apply(this, arguments); }; beestat.extend(beestat.component.input.text, beestat.component.input);