diff --git a/css/dashboard.css b/css/dashboard.css index 52e938a..d1bc108 100644 --- a/css/dashboard.css +++ b/css/dashboard.css @@ -440,6 +440,8 @@ input[type=radio] { .icon.chart_bar_stacked:before { content: "\F076A"; } .icon.chart_line:before { content: "\F012A"; } .icon.check:before { content: "\F012C"; } +.icon.chevron_down:before { content: "\F0140"; } +.icon.chevron_up:before { content: "\F0143"; } .icon.clock_outline:before { content: "\F0150"; } .icon.close:before { content: "\F0156"; } .icon.close_network:before { content: "\F015B"; } @@ -467,6 +469,7 @@ input[type=radio] { .icon.home:before { content: "\F02DC"; } .icon.home_floor_a:before { content: "\F0D83"; } .icon.home_search:before { content: "\F13B0"; } +.icon.home_switch:before { content: "\F1794"; } .icon.information:before { content: "\F02FC"; } .icon.key:before { content: "\F0306"; } .icon.label:before { content: "\F0315"; } diff --git a/js/beestat/floor_plan.js b/js/beestat/floor_plan.js index 9338e84..c6a9fc0 100644 --- a/js/beestat/floor_plan.js +++ b/js/beestat/floor_plan.js @@ -58,6 +58,13 @@ beestat.floor_plan.get_area_room = function(room, round = true) { return area; }; +/** + * Get the bounding box for an entire floor plan. + * + * @param {number} floor_plan_id + * + * @return {object} + */ beestat.floor_plan.get_bounding_box = function(floor_plan_id) { const floor_plan = beestat.cache.floor_plan[floor_plan_id]; @@ -87,6 +94,13 @@ beestat.floor_plan.get_bounding_box = function(floor_plan_id) { }; }; +/** + * Get the bounding box for one group of a floor plan. + * + * @param {object} group + * + * @return {object} + */ beestat.floor_plan.get_bounding_box_group = function(group) { let min_x = Infinity; let max_x = -Infinity; @@ -114,6 +128,13 @@ beestat.floor_plan.get_bounding_box_group = function(group) { }; }; +/** + * Get the bounding box for one room of a floor plan. + * + * @param {object} room + * + * @return {object} + */ beestat.floor_plan.get_bounding_box_room = function(room) { let min_x = Infinity; let max_x = -Infinity; @@ -138,3 +159,25 @@ beestat.floor_plan.get_bounding_box_room = function(room) { 'y': min_y }; }; + +/** + * Get an object of all the sensor_ids included in the current floor plan. Key + * is sensor_id, value is true. + * + * @param {number} floor_plan_id + * + * @return {object} + */ +beestat.floor_plan.get_sensor_ids_map = function(floor_plan_id) { + const floor_plan = beestat.cache.floor_plan[floor_plan_id]; + const sensor_ids_map = {}; + floor_plan.data.groups.forEach(function(group) { + group.rooms.forEach(function(room) { + if (room.sensor_id !== undefined) { + sensor_ids_map[room.sensor_id] = true; + } + }); + }); + + return sensor_ids_map; +}; diff --git a/js/beestat/setting.js b/js/beestat/setting.js index e9fd467..345d69a 100644 --- a/js/beestat/setting.js +++ b/js/beestat/setting.js @@ -76,13 +76,12 @@ beestat.setting = function(argument_1, opt_value, opt_callback) { .format('MM/DD/YYYY'), 'visualize.range_static.end': moment() .format('MM/DD/YYYY'), - 'visualize.floor_plan_id': null, 'visualize.heat_map_type': 'relative', 'visualize.heat_map_absolute.temperature.min': 70, 'visualize.heat_map_absolute.temperature.max': 80, 'visualize.heat_map_absolute.occupancy.min': 0, - 'visualize.heat_map_absolute.occupancy.max': 100 - + 'visualize.heat_map_absolute.occupancy.max': 100, + 'visualize.hide_affiliate': false }; // Figure out what we're trying to do. diff --git a/js/component.js b/js/component.js index 597a367..5e6bc8f 100644 --- a/js/component.js +++ b/js/component.js @@ -1,5 +1,5 @@ beestat.component = function() { - var self = this; + const self = this; this.rendered_ = false; diff --git a/js/component/card/floor_plan_editor.js b/js/component/card/floor_plan_editor.js index fd12c22..53a5a36 100644 --- a/js/component/card/floor_plan_editor.js +++ b/js/component/card/floor_plan_editor.js @@ -8,7 +8,12 @@ beestat.component.card.floor_plan_editor = function(thermostat_id) { this.thermostat_id_ = thermostat_id; - const change_function = beestat.debounce(function() { + // Whether or not to show the editor when loading. + this.show_editor_ = beestat.floor_plan.get_bounding_box( + beestat.setting('visualize.floor_plan_id') + ).x === Infinity; + +/* const change_function = beestat.debounce(function() { // todo replace these with (if entity set active false?) delete self.state_.active_group; @@ -23,7 +28,7 @@ beestat.component.card.floor_plan_editor = function(thermostat_id) { beestat.dispatcher.addEventListener( 'setting.visualize.floor_plan_id', change_function - ); + );*/ beestat.component.card.apply(this, arguments); @@ -50,63 +55,60 @@ beestat.extend(beestat.component.card.floor_plan_editor, beestat.component.card) beestat.component.card.floor_plan_editor.prototype.decorate_contents_ = function(parent) { const self = this; - if (Object.keys(beestat.cache.floor_plan).length === 0) { - const center_container = $.createElement('div').style('text-align', 'center'); - parent.appendChild(center_container); + const floor_plan = beestat.cache.floor_plan[beestat.setting('visualize.floor_plan_id')]; - const get_started_button = new beestat.component.tile() - .set_icon('plus') - .set_text('Create my first floor plan') - .set_size('large') - .set_background_color(beestat.style.color.green.dark) - .set_background_hover_color(beestat.style.color.green.light) - .render(center_container) - .addEventListener('click', function() { - new beestat.component.modal.create_floor_plan( - self.thermostat_id_ - ).render(); - }); - center_container.appendChild(get_started_button); - } else { - const floor_plan = beestat.cache.floor_plan[beestat.setting('visualize.floor_plan_id')]; + // Set group ids if they are not set. + floor_plan.data.groups.forEach(function(group) { + if (group.group_id === undefined) { + group.group_id = window.crypto.randomUUID(); + } + }); - // Set group ids if they are not set. + /** + * If there is an active_group_id, override whatever the current active + * group is. Used for undo/redo. + */ + if (this.state_.active_group_id !== undefined) { + for (let i = 0; i < floor_plan.data.groups.length; i++) { + if (floor_plan.data.groups[i].group_id === this.state_.active_group_id) { + this.state_.active_group = floor_plan.data.groups[i]; + delete this.state_.active_group_id; + break; + } + } + } + + // If there is no active group, set it to best guess of ground floor. + if (this.state_.active_group === undefined) { + let closest_distance = Infinity; + let closest_group; floor_plan.data.groups.forEach(function(group) { - if (group.group_id === undefined) { - group.group_id = window.crypto.randomUUID(); + if (Math.abs(group.elevation) < closest_distance) { + closest_group = group; + closest_distance = Math.abs(group.elevation); } }); + this.state_.active_group = closest_group; + } - /** - * If there is an active_group_id, override whatever the current active - * group is. Used for undo/redo. - */ - if (this.state_.active_group_id !== undefined) { - for (let i = 0; i < floor_plan.data.groups.length; i++) { - if (floor_plan.data.groups[i].group_id === this.state_.active_group_id) { - this.state_.active_group = floor_plan.data.groups[i]; - delete this.state_.active_group_id; - break; - } - } - } + this.floor_plan_tile_ = new beestat.component.tile.floor_plan( + beestat.setting('visualize.floor_plan_id') + ) + .set_background_color(beestat.style.color.lightblue.base) + .set_background_hover_color(beestat.style.color.lightblue.base) + .set_text_color('#fff') + .set_display('block') + .addEventListener('click', function() { + self.show_editor_ = !self.show_editor_; + self.rerender(); + }) + .render(parent); - // If there is no active group, set it to best guess of ground floor. - if (this.state_.active_group === undefined) { - let closest_distance = Infinity; - let closest_group; - floor_plan.data.groups.forEach(function(group) { - if (Math.abs(group.elevation) < closest_distance) { - closest_group = group; - closest_distance = Math.abs(group.elevation); - } - }); - this.state_.active_group = closest_group; - } - - // Decorate everything. + // Decorate everything. + if (this.show_editor_ === true) { const drawing_pane_container = $.createElement('div'); drawing_pane_container.style({ + 'margin-top': beestat.style.size.gutter, 'position': 'relative', 'overflow-x': 'hidden' }); @@ -118,6 +120,26 @@ beestat.component.card.floor_plan_editor.prototype.decorate_contents_ = function parent.appendChild(this.info_pane_container_); this.decorate_info_pane_(this.info_pane_container_); } + + const expand_container = document.createElement('div'); + Object.assign(expand_container.style, { + 'position': 'absolute', + 'right': '28px', + 'top': '70px' + }); + parent.appendChild(expand_container); + + new beestat.component.tile() + .set_icon(this.show_editor_ === true ? 'chevron_up' : 'chevron_down') + .set_size('small') + .set_shadow(false) + .set_background_hover_color(beestat.style.color.lightblue.base) + .set_text_color('#fff') + .addEventListener('click', function() { + self.show_editor_ = !self.show_editor_; + self.rerender(); + }) + .render($(expand_container)); }; /** @@ -197,6 +219,7 @@ beestat.component.card.floor_plan_editor.prototype.decorate_drawing_pane_ = func room_entity.addEventListener('update', function() { self.floor_plan_.update_infobox(); self.update_info_pane_(); + self.update_floor_plan_tile_(); self.update_floor_plan_(); }); @@ -205,6 +228,7 @@ beestat.component.card.floor_plan_editor.prototype.decorate_drawing_pane_ = func self.floor_plan_.update_infobox(); self.floor_plan_.update_toolbar(); self.update_info_pane_(); + self.update_floor_plan_tile_(); }); // Update GUI when a room is deselected. @@ -212,6 +236,7 @@ beestat.component.card.floor_plan_editor.prototype.decorate_drawing_pane_ = func self.floor_plan_.update_infobox(); self.floor_plan_.update_toolbar(); self.update_info_pane_(); + self.update_floor_plan_tile_(); }); /** @@ -495,11 +520,25 @@ beestat.component.card.floor_plan_editor.prototype.decorate_info_pane_room_ = fu } sensor_input.addEventListener('change', function() { + const old_sensor_ids = Object.keys(beestat.floor_plan.get_sensor_ids_map( + beestat.setting('visualize.floor_plan_id') + )); + if (sensor_input.get_value() === '') { delete self.state_.active_room_entity.get_room().sensor_id; } else { self.state_.active_room_entity.get_room().sensor_id = Number(sensor_input.get_value()); } + + const new_sensor_ids = Object.keys(beestat.floor_plan.get_sensor_ids_map( + beestat.setting('visualize.floor_plan_id') + )); + + // Delete data if the overall sensor set changes so it's re-fetched. + if (old_sensor_ids.sort().join(' ') !== new_sensor_ids.sort().join(' ')) { + beestat.cache.delete('data.three_d__runtime_sensor'); + } + self.update_floor_plan_(); }); }; @@ -518,6 +557,15 @@ beestat.component.card.floor_plan_editor.prototype.update_info_pane_ = function( old_parent.parentNode().replaceChild(this.info_pane_container_, old_parent); }; +/** + * Rerender just the top floor pane tile to avoid rerendering the entire SVG + * for resizes, drags, etc. This isn't super ideal but without making the info + * pane a separate component this is the way. + */ +beestat.component.card.floor_plan_editor.prototype.update_floor_plan_tile_ = function() { + this.floor_plan_tile_.rerender(); +}; + /** * Get the title of the card. * @@ -577,6 +625,15 @@ beestat.component.card.floor_plan_editor.prototype.decorate_top_right_ = functio const menu = (new beestat.component.menu()).render(parent); if (window.is_demo === false) { + if (Object.keys(beestat.cache.floor_plan).length > 1) { + menu.add_menu_item(new beestat.component.menu_item() + .set_text('Switch') + .set_icon('home_switch') + .set_callback(function() { + (new beestat.component.modal.change_floor_plan()).render(); + })); + } + menu.add_menu_item(new beestat.component.menu_item() .set_text('Add New') .set_icon('plus') @@ -609,11 +666,11 @@ beestat.component.card.floor_plan_editor.prototype.decorate_top_right_ = functio } } - menu.add_menu_item(new beestat.component.menu_item() +/* menu.add_menu_item(new beestat.component.menu_item() .set_text('Help') .set_icon('help_circle') .set_callback(function() { // TODO // window.open('https://doc.beestat.io/???'); - })); + }));*/ }; diff --git a/js/component/card/three_d.js b/js/component/card/three_d.js index 46c09fb..b280e8f 100644 --- a/js/component/card/three_d.js +++ b/js/component/card/three_d.js @@ -108,20 +108,33 @@ beestat.component.card.three_d.prototype.decorate_contents_ = function(parent) { let required_begin; let required_end; if (beestat.setting('visualize.range_type') === 'dynamic') { - required_begin = moment() - .subtract( - beestat.setting('visualize.range_dynamic'), - 'day' - ) - .hour(0) - .minute(0) - .second(0); + if ( + beestat.setting('visualize.range_dynamic') === 0 || + beestat.setting('visualize.range_dynamic') === 1 + ) { + // Rig "today" and "yesterday" to behave differently. + required_begin = moment() + .subtract( + beestat.setting('visualize.range_dynamic'), + 'day' + ) + .hour(0) + .minute(0) + .second(0); - required_end = required_begin - .clone() - .hour(23) - .minute(59) - .second(59); + required_end = required_begin + .clone() + .hour(23) + .minute(59) + .second(59); + } else { + required_begin = moment() + .subtract( + beestat.setting('visualize.range_dynamic'), + 'day' + ); + required_end = moment(); + } } else { required_begin = moment( beestat.setting('visualize.range_static_begin') + ' 00:00:00' @@ -150,7 +163,7 @@ beestat.component.card.three_d.prototype.decorate_contents_ = function(parent) { */ // TODO somewhat problematic because I need to check if data is synced from multiple thermostats now // if (beestat.thermostat.data_synced(this.thermostat_id_, required_begin, required_end) === true) { - const sensor_ids = Object.keys(this.get_sensor_ids_map_()); + const sensor_ids = Object.keys(beestat.floor_plan.get_sensor_ids_map(this.floor_plan_id_)); if (sensor_ids.length > 0) { if (true) { if (beestat.cache.data.three_d__runtime_sensor === undefined) { @@ -163,7 +176,7 @@ beestat.component.card.three_d.prototype.decorate_contents_ = function(parent) { ]; const operator = 'between'; - const sensor_ids = Object.keys(this.get_sensor_ids_map_()); + const sensor_ids = Object.keys(beestat.floor_plan.get_sensor_ids_map(this.floor_plan_id_)); // if (sensor_ids.length > 0) { const api_call = new beestat.api(); sensor_ids.forEach(function(sensor_id) { @@ -252,30 +265,27 @@ beestat.component.card.three_d.prototype.decorate_drawing_pane_ = function(paren ); // Set the initial date. - if (this.has_data_() === true) { - this.update_scene_(); - this.scene_.render($(parent)); + // if (this.has_data_() === true) { + this.update_scene_(); + this.scene_.render($(parent)); - if (beestat.setting('visualize.range_type') === 'dynamic') { - this.date_m_ = moment() - .subtract( - beestat.setting('visualize.range_dynamic'), - 'day' - ) - .hour(0) - .minute(0) - .second(0); - } else { - this.date_m_ = moment( - beestat.setting('visualize.range_static_begin') + ' 00:00:00' - ); - } - - this.scene_.set_date(this.date_m_); + if (beestat.setting('visualize.range_type') === 'dynamic') { + this.date_m_ = moment() + .subtract( + beestat.setting('visualize.range_dynamic'), + 'day' + ) + .hour(0) + .minute(0) + .second(0); } else { - this.scene_.render($(parent)); + this.date_m_ = moment( + beestat.setting('visualize.range_static_begin') + ' 00:00:00' + ); } + this.scene_.set_date(this.date_m_); + // Manage width of the scene. setTimeout(function() { if (parent.getBoundingClientRect().width > 0) { @@ -386,7 +396,7 @@ beestat.component.card.three_d.prototype.decorate_controls_ = function(parent) { beestat.component.card.three_d.prototype.get_data_ = function(force) { const self = this; if (this.data_ === undefined || force === true) { - const sensor_ids_map = this.get_sensor_ids_map_(); + const sensor_ids_map = beestat.floor_plan.get_sensor_ids_map(this.floor_plan_id_); this.data_ = { 'metadata': { @@ -460,7 +470,6 @@ beestat.component.card.three_d.prototype.get_data_ = function(force) { } } } - // console.log(this.data_); return this.data_; }; @@ -482,32 +491,6 @@ beestat.component.card.three_d.prototype.has_data_ = function() { return false; }; -/** - * Get the title of the card. - * - * @return {string} The title. - */ -beestat.component.card.three_d.prototype.get_title_ = function() { - return '3D View'; -}; - -/** - * Decorate the menu. - * - * @param {rocket.Elements} parent - */ -beestat.component.card.three_d.prototype.decorate_top_right_ = function(parent) { - const 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() { - // TODO - // window.open('https://doc.beestat.io/???'); - })); -}; - /** * Update the scene with current settings. Anything that doesn't require * re-rendering can go here. @@ -559,23 +542,3 @@ beestat.component.card.three_d.prototype.set_floor_plan_id = function(floor_plan return this; }; - -/** - * Get an object of all the sensor_ids included in the current floor plan. Key - * is sensor_id, value is true. - * - * @return {object} - */ -beestat.component.card.three_d.prototype.get_sensor_ids_map_ = function() { - const floor_plan = beestat.cache.floor_plan[this.floor_plan_id_]; - const sensor_ids_map = []; - floor_plan.data.groups.forEach(function(group) { - group.rooms.forEach(function(room) { - if (room.sensor_id !== undefined) { - sensor_ids_map[room.sensor_id] = true; - } - }); - }); - - return sensor_ids_map; -}; diff --git a/js/component/card/visualize_affiliate.js b/js/component/card/visualize_affiliate.js new file mode 100644 index 0000000..c82bb79 --- /dev/null +++ b/js/component/card/visualize_affiliate.js @@ -0,0 +1,63 @@ +/** + * Visualize intro. + * + * @param {number} thermostat_id + */ +beestat.component.card.visualize_affiliate = function(thermostat_id) { + this.thermostat_id_ = thermostat_id; + + beestat.component.card.apply(this, arguments); +}; +beestat.extend(beestat.component.card.visualize_affiliate, beestat.component.card); + +/** + * Decorate. + * + * @param {rocket.Elements} parent + */ +beestat.component.card.visualize_affiliate.prototype.decorate_contents_ = function(parent) { + const tile_group = new beestat.component.tile_group(); + + tile_group.add_tile(new beestat.component.tile() + .set_icon('open_in_new') + .set_text([ + 'SmartSensor 2 Pack', + 'Amazon Affiliate' + ]) + .set_size('large') + .set_background_color(beestat.style.color.green.dark) + .set_background_hover_color(beestat.style.color.green.light) + .addEventListener('click', function() { + window.open('https://amzn.to/3SprUVB'); + }) + ); + + tile_group.render(parent); +}; + +/** + * Decorate the close button. + * + * @param {rocket.Elements} parent + */ +beestat.component.card.visualize_affiliate.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.green.light) + .addEventListener('click', function() { + beestat.setting('visualize.hide_affiliate', true); + }) + .render(parent); +}; + +/** + * Get the title of the card. + * + * @return {string} The title. + */ +beestat.component.card.visualize_affiliate.prototype.get_title_ = function() { + return 'Need more sensors?'; +}; diff --git a/js/component/card/visualize_intro.js b/js/component/card/visualize_intro.js new file mode 100644 index 0000000..53fbddf --- /dev/null +++ b/js/component/card/visualize_intro.js @@ -0,0 +1,54 @@ +/** + * Visualize intro. + * + * @param {number} thermostat_id + */ +beestat.component.card.visualize_intro = function(thermostat_id) { + this.thermostat_id_ = thermostat_id; + + beestat.component.card.apply(this, arguments); +}; +beestat.extend(beestat.component.card.visualize_intro, beestat.component.card); + +/** + * Decorate. + * + * @param {rocket.Elements} parent + */ +beestat.component.card.visualize_intro.prototype.decorate_contents_ = function(parent) { + const self = this; + + const p1 = document.createElement('p'); + p1.innerText = 'You now have early access to the new Visualize features. This is a work-in-progress, but you should find it to be mostly stable. More features and improvements are in the works, as well as documentation and videos to help explain the new capabilities.'; + parent.appendChild(p1); + + const p2 = document.createElement('p'); + p2.innerText = 'Please reach out on Discord or email contact@beestat.io with feedback. Thank you for your support!'; + parent.appendChild(p2); + + const center_container = document.createElement('div'); + center_container.style.textAlign = 'center'; + parent.appendChild(center_container); + + new beestat.component.tile() + .set_icon('plus') + .set_text('Create a floor plan') + .set_size('large') + .set_background_color(beestat.style.color.green.dark) + .set_background_hover_color(beestat.style.color.green.light) + .render($(center_container)) + .addEventListener('click', function() { + new beestat.component.modal.create_floor_plan( + self.thermostat_id_ + ).render(); + }); +}; + +/** + * Get the title of the card. + * + * @return {string} The title. + */ +beestat.component.card.visualize_intro.prototype.get_title_ = function() { + return 'Visualize'; +}; diff --git a/js/component/card/visualize_settings.js b/js/component/card/visualize_settings.js index 00490a5..4adde6c 100644 --- a/js/component/card/visualize_settings.js +++ b/js/component/card/visualize_settings.js @@ -45,10 +45,6 @@ beestat.component.card.visualize_settings.prototype.decorate_contents_ = functio const heat_map_type_container = document.createElement('div'); this.decorate_heat_map_type_(heat_map_type_container); grid_2.appendChild(heat_map_type_container); - - const floor_plan_container = document.createElement('div'); - this.decorate_floor_plan_(floor_plan_container); - grid_2.appendChild(floor_plan_container); }; /** @@ -317,7 +313,7 @@ beestat.component.card.visualize_settings.prototype.decorate_time_period_ = func .set_background_hover_color(color) .set_text_color('#fff') .set_icon('calendar_week') - .set_text('Last 7 Days'); + .set_text('7 Day Average'); if ( beestat.setting('visualize.range_type') === 'dynamic' && @@ -361,45 +357,6 @@ beestat.component.card.visualize_settings.prototype.decorate_time_period_ = func tile_group.render($(parent)); }; -/** - * Decorate the floor plan options. - * - * @param {HTMLDivElement} parent - */ -beestat.component.card.visualize_settings.prototype.decorate_floor_plan_ = function(parent) { - const self = this; - - (new beestat.component.title('Floor Plan')).render($(parent)); - - var sorted_floor_plans = $.values(beestat.cache.floor_plan) - .sort(function(a, b) { - return a.name > b.name; - }); - - const tile_group = new beestat.component.tile_group(); - sorted_floor_plans.forEach(function(floor_plan) { - const tile = new beestat.component.tile.floor_plan(floor_plan.floor_plan_id) - .set_text_color('#fff') - .set_display('block'); - - if (floor_plan.floor_plan_id === beestat.setting('visualize.floor_plan_id')) { - tile.set_background_color(beestat.style.color.lightblue.base); - } else { - tile - .set_background_color(beestat.style.color.bluegray.light) - .set_background_hover_color(beestat.style.color.lightblue.base) - .addEventListener('click', function() { - beestat.setting('visualize.floor_plan_id', floor_plan.floor_plan_id); - self.rerender(); - }); - } - - tile_group.add_tile(tile); - }); - - tile_group.render($(parent)); -}; - /** * Get the title of the card. * @@ -414,7 +371,7 @@ beestat.component.card.visualize_settings.prototype.get_title_ = function() { * * @param {rocket.Elements} parent */ -beestat.component.card.visualize_settings.prototype.decorate_top_right_ = function(parent) { +/*beestat.component.card.visualize_settings.prototype.decorate_top_right_ = function(parent) { var menu = (new beestat.component.menu()).render(parent); menu.add_menu_item(new beestat.component.menu_item() @@ -425,3 +382,4 @@ beestat.component.card.visualize_settings.prototype.decorate_top_right_ = functi // window.open('https://doc.beestat.io/596040eadd014928830b4d1d54692761'); })); }; +*/ diff --git a/js/component/floor_plan.js b/js/component/floor_plan.js index d9fa56b..ef2bd2a 100644 --- a/js/component/floor_plan.js +++ b/js/component/floor_plan.js @@ -748,6 +748,10 @@ beestat.component.floor_plan.prototype.add_room_ = function(room) { beestat.component.floor_plan.prototype.remove_room_ = function() { this.save_buffer(); + const old_sensor_ids = Object.keys(beestat.floor_plan.get_sensor_ids_map( + beestat.setting('visualize.floor_plan_id') + )); + const self = this; const index = this.state_.active_group.rooms.findIndex(function(room) { @@ -765,6 +769,16 @@ beestat.component.floor_plan.prototype.remove_room_ = function() { } this.state_.active_group.rooms.splice(index, 1); + + const new_sensor_ids = Object.keys(beestat.floor_plan.get_sensor_ids_map( + beestat.setting('visualize.floor_plan_id') + )); + + // Delete data if the overall sensor set changes so it's re-fetched. + if (old_sensor_ids.sort().join(' ') !== new_sensor_ids.sort().join(' ')) { + beestat.cache.delete('data.three_d__runtime_sensor'); + } + this.dispatchEvent('remove_room'); }; @@ -954,31 +968,13 @@ beestat.component.floor_plan.prototype.get_group_below = function(group) { * Center the view box on the content. Sets zoom and pan. */ beestat.component.floor_plan.prototype.center_content = function() { - // const floor_plan = beestat.cache.floor_plan[this.floor_plan_id_]; - - // let min_x = Infinity; - // let max_x = -Infinity; - // let min_y = Infinity; - // let max_y = -Infinity; - - // let has_content = false; - // floor_plan.data.groups.forEach(function(group) { - // group.rooms.forEach(function(room) { - // room.points.forEach(function(point) { - // has_content = true; - // min_x = Math.min(room.x + point.x, min_x); - // max_x = Math.max(room.x + point.x, max_x); - // min_y = Math.min(room.y + point.y, min_y); - // max_y = Math.max(room.y + point.y, max_y); - // }); - // }); - // }); - const bounding_box = beestat.floor_plan.get_bounding_box(this.floor_plan_id_); this.reset_view_box_(); - // TODO ADD THIS BACK IN - // if (has_content === true) { + if ( + bounding_box.x !== Infinity && + bounding_box.y !== Infinity + ) { const width = (bounding_box.width) + 50; const height = (bounding_box.height) + 50; while ( @@ -998,7 +994,7 @@ beestat.component.floor_plan.prototype.center_content = function() { this.view_box_.y = center_y - (this.view_box_.height / 2); this.update_view_box_(); - // } + } }; /** @@ -1048,6 +1044,10 @@ beestat.component.floor_plan.prototype.save_buffer = function(clear = true) { */ beestat.component.floor_plan.prototype.undo_ = function() { if (this.can_undo_() === true) { + const old_sensor_ids = Object.keys(beestat.floor_plan.get_sensor_ids_map( + beestat.setting('visualize.floor_plan_id') + )); + /** * When undoing, first save the buffer if the pointer is at the end to * capture the current state then shift the buffer pointer back an extra. @@ -1072,6 +1072,15 @@ beestat.component.floor_plan.prototype.undo_ = function() { this.state_.active_group_id = this.state_.buffer[this.state_.buffer_pointer].active_group_id; + // Delete data if the overall sensor set changes so it's re-fetched. + const new_sensor_ids = Object.keys(beestat.floor_plan.get_sensor_ids_map( + beestat.setting('visualize.floor_plan_id') + )); + + if (old_sensor_ids.sort().join(' ') !== new_sensor_ids.sort().join(' ')) { + beestat.cache.delete('data.three_d__runtime_sensor'); + } + this.update_toolbar(); this.dispatchEvent('undo'); } @@ -1091,6 +1100,10 @@ beestat.component.floor_plan.prototype.can_undo_ = function() { */ beestat.component.floor_plan.prototype.redo_ = function() { if (this.can_redo_() === true) { + const old_sensor_ids = Object.keys(beestat.floor_plan.get_sensor_ids_map( + beestat.setting('visualize.floor_plan_id') + )); + this.state_.buffer_pointer++; // Restore the floor plan. beestat.cache.floor_plan[this.floor_plan_id_] = @@ -1104,6 +1117,15 @@ beestat.component.floor_plan.prototype.redo_ = function() { this.state_.active_group_id = this.state_.buffer[this.state_.buffer_pointer].active_group_id; + // Delete data if the overall sensor set changes so it's re-fetched. + const new_sensor_ids = Object.keys(beestat.floor_plan.get_sensor_ids_map( + beestat.setting('visualize.floor_plan_id') + )); + + if (old_sensor_ids.sort().join(' ') !== new_sensor_ids.sort().join(' ')) { + beestat.cache.delete('data.three_d__runtime_sensor'); + } + this.update_toolbar(); this.dispatchEvent('redo'); } diff --git a/js/component/header.js b/js/component/header.js index b9a6892..4daa4b0 100644 --- a/js/component/header.js +++ b/js/component/header.js @@ -26,28 +26,58 @@ beestat.component.header.prototype.decorate_ = function(parent) { var pages; - pages = [ - { - 'layer': 'detail', - 'text': 'Detail', - 'icon': 'eye_circle' - }, - { - 'layer': 'analyze', - 'text': 'Analyze', - 'icon': 'home_search' - }, - { - 'layer': 'compare', - 'text': 'Compare', - 'icon': 'earth' - }, - { - 'layer': 'air_quality', - 'text': 'Air Quality', - 'icon': 'weather_windy' - } - ]; + if (beestat.user.has_early_access() === true) { + pages = [ + { + 'layer': 'detail', + 'text': 'Detail', + 'icon': 'eye_circle' + }, + { + 'layer': 'analyze', + 'text': 'Analyze', + 'icon': 'home_search' + }, + // { + // 'layer': 'visualize', + // 'text': 'Visualize', + // 'icon': 'floor_plan' + // }, + { + 'layer': 'compare', + 'text': 'Compare', + 'icon': 'earth' + }, + { + 'layer': 'air_quality', + 'text': 'Air Quality', + 'icon': 'weather_windy' + } + ]; + } else { + pages = [ + { + 'layer': 'detail', + 'text': 'Detail', + 'icon': 'eye_circle' + }, + { + 'layer': 'analyze', + 'text': 'Analyze', + 'icon': 'home_search' + }, + { + 'layer': 'compare', + 'text': 'Compare', + 'icon': 'earth' + }, + { + 'layer': 'air_quality', + 'text': 'Air Quality', + 'icon': 'weather_windy' + } + ]; + } pages.push(); diff --git a/js/component/modal/change_floor_plan.js b/js/component/modal/change_floor_plan.js new file mode 100644 index 0000000..26f5efc --- /dev/null +++ b/js/component/modal/change_floor_plan.js @@ -0,0 +1,66 @@ +/** + * Change floor plan + */ +beestat.component.modal.change_floor_plan = function() { + beestat.component.modal.apply(this, arguments); +}; +beestat.extend(beestat.component.modal.change_floor_plan, beestat.component.modal); + +/** + * Decorate + * + * @param {rocket.Elements} parent + */ +beestat.component.modal.change_floor_plan.prototype.decorate_contents_ = function(parent) { + const self = this; + + const p = document.createElement('p'); + p.innerText = 'You have multiple floor plans; which one would you like to view?'; + parent.appendChild(p); + + const grid = document.createElement('div'); + grid.style.display = 'grid'; + grid.style.gridTemplateColumns = 'repeat(auto-fit, minmax(150px, 1fr))'; + grid.style.columnGap = beestat.style.size.gutter + 'px'; + grid.style.rowGap = beestat.style.size.gutter + 'px'; + parent.appendChild(grid); + + var sorted_floor_plans = $.values(beestat.cache.floor_plan) + .sort(function(a, b) { + return a.name > b.name; + }); + + let div; + sorted_floor_plans.forEach(function(floor_plan) { + div = document.createElement('div'); + grid.appendChild(div); + + const tile = new beestat.component.tile.floor_plan(floor_plan.floor_plan_id) + .set_text_color('#fff') + .set_display('block'); + + if (floor_plan.floor_plan_id === beestat.setting('visualize.floor_plan_id')) { + tile.set_background_color(beestat.style.color.lightblue.base); + } else { + tile + .set_background_color(beestat.style.color.bluegray.base) + .set_background_hover_color(beestat.style.color.lightblue.base) + .addEventListener('click', function() { + beestat.setting('visualize.floor_plan_id', floor_plan.floor_plan_id); + self.dispose(); + }); + } + + tile.render($(div)); + }); +}; + +/** + * Get title. + * + * @return {string} Title. + */ +beestat.component.modal.change_floor_plan.prototype.get_title_ = function() { + return 'Change Floor Plan'; +}; + diff --git a/js/component/modal/create_floor_plan.js b/js/component/modal/create_floor_plan.js index 9a35b60..9dd3122 100644 --- a/js/component/modal/create_floor_plan.js +++ b/js/component/modal/create_floor_plan.js @@ -232,7 +232,6 @@ beestat.component.modal.create_floor_plan.prototype.get_buttons_ = function() { elevation += (self.state_.height * 12); } - self.dispose(); new beestat.api() .add_call( 'floor_plan', @@ -249,8 +248,8 @@ beestat.component.modal.create_floor_plan.prototype.get_buttons_ = function() { 'floor_plan' ) .set_callback(function(response) { - beestat.setting('visualize.floor_plan_id', response.new_floor_plan.floor_plan_id); beestat.cache.set('floor_plan', response.floor_plan); + beestat.setting('visualize.floor_plan_id', response.new_floor_plan.floor_plan_id); }) .send(); }); diff --git a/js/component/modal/delete_floor_plan.js b/js/component/modal/delete_floor_plan.js index 9fb4625..86eb539 100644 --- a/js/component/modal/delete_floor_plan.js +++ b/js/component/modal/delete_floor_plan.js @@ -59,7 +59,6 @@ beestat.component.modal.delete_floor_plan.prototype.get_buttons_ = function() { .set_text_color('#fff') .set_text('Delete Floor Plan') .addEventListener('click', function() { - self.dispose(); new beestat.api() .add_call( 'floor_plan', @@ -76,13 +75,14 @@ beestat.component.modal.delete_floor_plan.prototype.get_buttons_ = function() { 'floor_plan' ) .set_callback(function(response) { - console.log('deleted fp'); - console.log(response); + self.dispose(); + if (Object.keys(response.floor_plan).length > 0) { beestat.setting('visualize.floor_plan_id', Object.values(response.floor_plan)[0].floor_plan_id); } else { beestat.setting('visualize.floor_plan_id', null); } + beestat.cache.set('floor_plan', response.floor_plan); }) .send(); diff --git a/js/component/scene.js b/js/component/scene.js index d0e9f3c..2e41138 100644 --- a/js/component/scene.js +++ b/js/component/scene.js @@ -12,24 +12,35 @@ beestat.component.scene = function(floor_plan_id, data) { }; beestat.extend(beestat.component.scene, beestat.component); -beestat.component.scene.sun_light_intensity = 1; -beestat.component.scene.moon_light_intensity = 0.3; +// beestat.component.scene.sun_light_intensity = 1; +// beestat.component.scene.moon_light_intensity = 0.3; -beestat.component.scene.ambient_light_intensity_base = 1.5; -beestat.component.scene.ambient_light_intensity_sky = 0.4; -beestat.component.scene.moon_opacity = 0.9; +/** + * Brightness of the top-down light. This gives definition to the sides of + * meshes by lighting the tops. Increase this for more edge definition. + */ +beestat.component.scene.directional_light_top_intensity = 0.25; -beestat.component.scene.turbidity = 10; -beestat.component.scene.rayleigh = 0.5; -beestat.component.scene.mie_coefficient = 0.001; -beestat.component.scene.mie_directional_g = 0.95; +/** + * Brightness of the ambient light. Works with the top light to provide a base + * level of light to the scene. + */ +beestat.component.scene.ambient_light_intensity = 0.3; + +// beestat.component.scene.ambient_light_intensity_sky = 0.4; +// beestat.component.scene.moon_opacity = 0.9; + +// beestat.component.scene.turbidity = 10; +// beestat.component.scene.rayleigh = 0.5; +// beestat.component.scene.mie_coefficient = 0.001; +// beestat.component.scene.mie_directional_g = 0.95; // beestat.component.scene.turbidity = 14; // beestat.component.scene.rayleigh = 0.7; // beestat.component.scene.mie_coefficient = 0.008; // beestat.component.scene.mie_directional_g = 0.9; -beestat.component.scene.shadow_map_size = 4096; +// beestat.component.scene.shadow_map_size = 4096; /** * Rerender the scene by removing the primary group, then re-adding it and the @@ -65,10 +76,11 @@ beestat.component.scene.prototype.decorate_ = function(parent) { const self = this; this.debug_ = { - 'axes': false, - 'moon_light_helper': false, - 'sun_light_helper': false, - 'grid': false, + 'axes': true, + // 'directional_light_moon_helper': false, + // 'directional_light_sun_helper': false, + 'directional_light_top_helper': false, + // 'grid': false, 'watcher': false }; @@ -82,9 +94,10 @@ beestat.component.scene.prototype.decorate_ = function(parent) { this.add_controls_(parent); // this.add_sky_(); // this.add_moon_(); - // this.add_moon_light_(); - this.add_sun_light_(); + // this.add_directional_light_moon_(); + // this.add_directional_light_sun_(); this.add_ambient_light_(); + this.add_directional_light_top_(); // this.add_ground_(); // this.add_ground_limited_(); @@ -163,17 +176,17 @@ beestat.component.scene.prototype.add_renderer_ = function(parent) { this.renderer_ = new THREE.WebGLRenderer({ 'antialias': true }); - this.renderer_.setSize(window.innerWidth /1.1, window.innerHeight / 1.1); - this.renderer_.shadowMap.enabled = true; - this.renderer_.shadowMap.autoUpdate = false; + // this.renderer_.setSize(window.innerWidth, window.innerHeight); + // this.renderer_.shadowMap.enabled = true; + // this.renderer_.shadowMap.autoUpdate = false; /* * Added these to make the sky not look like crap. * https://threejs.org/examples/webgl_shaders_sky.html */ - this.renderer_.toneMapping = THREE.ACESFilmicToneMapping; + // this.renderer_.toneMapping = THREE.ACESFilmicToneMapping; // this.renderer_.toneMappingExposure = 0.5; - this.renderer_.toneMappingExposure = 0.2; + // this.renderer_.toneMappingExposure = 0.2; parent[0].appendChild(this.renderer_.domElement); }; @@ -221,7 +234,7 @@ beestat.component.scene.prototype.add_controls_ = function(parent) { * The sky material uniforms are configured to make the sky look generally * nice. They are tweaked for the eclipse simulation to darken the sky. */ -beestat.component.scene.prototype.add_sky_ = function() { +/*beestat.component.scene.prototype.add_sky_ = function() { this.sky_ = new THREE.Sky(); // Makes the sky box really big. @@ -240,13 +253,13 @@ beestat.component.scene.prototype.add_sky_ = function() { beestat.component.scene.mie_directional_g; this.scene_.add(this.sky_); -}; +};*/ /** * Adds a moon sprite to the scene. The scale is set arbitrarily to make it * roughly the size of the sun. */ -beestat.component.scene.prototype.add_moon_ = function() { +/*beestat.component.scene.prototype.add_moon_ = function() { const map = new THREE.TextureLoader().load('img/moon.png'); const material = new THREE.SpriteMaterial({'map': map}); const scale = 700; @@ -254,12 +267,12 @@ beestat.component.scene.prototype.add_moon_ = function() { this.moon_ = new THREE.Sprite(material); this.moon_.scale.set(scale, scale, scale); // this.scene_.add(this.moon_); -}; +};*/ /** * Adds a faint moon light so the moon can cast shadows at night. */ -beestat.component.scene.prototype.add_moon_light_ = function() { +/*beestat.component.scene.prototype.add_directional_light_moon_ = function() { this.directional_light_moon_ = new THREE.DirectionalLight( 0xfffbab, 0.2 @@ -274,7 +287,7 @@ beestat.component.scene.prototype.add_moon_light_ = function() { this.directional_light_moon_.shadow.camera.far = 10000; // this.scene_.add(this.directional_light_moon_); - if (this.debug_.moon_light_helper === true) { + if (this.debug_.directional_light_moon_helper === true) { this.directional_light_moon_helper_ = new THREE.DirectionalLightHelper( this.directional_light_moon_ ); @@ -285,12 +298,12 @@ beestat.component.scene.prototype.add_moon_light_ = function() { ); this.scene_.add(this.directional_light_moon_camera_helper_); } -}; +};*/ /** * Add a strong sun light to the scene. */ -beestat.component.scene.prototype.add_sun_light_ = function() { +/*beestat.component.scene.prototype.add_directional_light_sun_ = function() { // Directional light to cast shadows. this.directional_light_sun_ = new THREE.DirectionalLight( 0xffffff, @@ -308,7 +321,7 @@ beestat.component.scene.prototype.add_sun_light_ = function() { this.directional_light_sun_.shadow.camera.far = 10000; this.scene_.add(this.directional_light_sun_); - if (this.debug_.sun_light_helper === true) { + if (this.debug_.directional_light_sun_helper === true) { this.directional_light_sun_helper_ = new THREE.DirectionalLightHelper( this.directional_light_sun_ ); @@ -319,10 +332,31 @@ beestat.component.scene.prototype.add_sun_light_ = function() { ); this.scene_.add(this.directional_light_sun_camera_helper_); } +};*/ + +/** + * Consistent directional light that provides definition to the edge of meshes + * by lighting the top. + */ +beestat.component.scene.prototype.add_directional_light_top_ = function() { + this.directional_light_top_ = new THREE.DirectionalLight( + 0xffffff, + beestat.component.scene.directional_light_top_intensity + ); + this.directional_light_top_.position.set(0, 1000, 0); + this.scene_.add(this.directional_light_top_); + + if (this.debug_.directional_light_top_helper === true) { + this.directional_light_top_helper_ = new THREE.DirectionalLightHelper( + this.directional_light_top_, + 500 + ); + this.scene_.add(this.directional_light_top_helper_); + } }; /** - * Add ambient lighting so everything is always somewhat visible. + * Ambient lighting so nothing is shrouded in darkness. */ beestat.component.scene.prototype.add_ambient_light_ = function() { /** @@ -331,18 +365,8 @@ beestat.component.scene.prototype.add_ambient_light_ = function() { */ this.scene_.add(new THREE.AmbientLight( 0xffffff, - beestat.component.scene.ambient_light_intensity_base + beestat.component.scene.ambient_light_intensity )); - - /** - * Ambient light from the sun/moon. Ths intensity of this light changes - * based on the time of day. - */ - this.ambient_light_sky_ = new THREE.AmbientLight( - 0xffffff, - beestat.component.scene.ambient_light_intensity_sky - ); - this.scene_.add(this.ambient_light_sky_); }; /** @@ -423,7 +447,7 @@ beestat.component.scene.prototype.update_ = function() { // TODO TEMP TO KEEP LIGHTING CONSISTENT // const date = new Date('2022-08-16 12:00:00'); // const date = this.date_.toDate(); - const date = moment() + /*const date = moment() .hour(12) .minute(0) .second(0) @@ -477,7 +501,7 @@ beestat.component.scene.prototype.update_ = function() { const eclipse_percentage = Math.max( 0, (1 - (sun_moon_distance / eclipse_begins_distance)) - ); + );*/ /* * this.ambient_light_sky_.intensity = @@ -490,10 +514,10 @@ beestat.component.scene.prototype.update_ = function() { */ // Set light intensities by altitude and eclipse percentage. - this.ambient_light_sky_.intensity = Math.max( +/* this.ambient_light_sky_.intensity = Math.max( 0, beestat.component.scene.ambient_light_intensity_sky * Math.sin(sun_position.altitude) * (1 - eclipse_percentage) - ); + );*/ // this.moon_.material.opacity = 0.2; @@ -502,7 +526,7 @@ beestat.component.scene.prototype.update_ = function() { */ // Turn down to 0 - if (this.sky_ !== undefined) { + /*if (this.sky_ !== undefined) { this.sky_.material.uniforms.rayleigh.value = beestat.component.scene.rayleigh * (1 - eclipse_percentage); @@ -521,7 +545,7 @@ beestat.component.scene.prototype.update_ = function() { ); this.sky_.material.uniforms.sunPosition.value.copy(sun_object_vector); - } + }*/ /* * this.renderer_.toneMappingExposure = Math.max( @@ -531,11 +555,10 @@ beestat.component.scene.prototype.update_ = function() { */ // Set the brightness of the sun - if (this.directional_light_sun_ !== undefined) { + /*if (this.directional_light_sun_ !== undefined) { this.directional_light_sun_.intensity = beestat.component.scene.sun_light_intensity * Math.sin(sun_position.altitude) * (1 - eclipse_percentage); this.directional_light_sun_.position.copy(sun_light_vector); - } // Set the brightness of the moon @@ -547,7 +570,7 @@ beestat.component.scene.prototype.update_ = function() { if (this.moon_ !== undefined) { this.moon_.position.copy(moon_object_vector); - } + }*/ // TODO size of moon based on distance? Might not be worth it haha. @@ -562,23 +585,26 @@ beestat.component.scene.prototype.update_ = function() { // this.sky2_.material.uniforms.sunPosition.value.copy(moon_object_vector); // Update shadows - this.renderer_.shadowMap.needsUpdate = true; + /*this.renderer_.shadowMap.needsUpdate = true; - if (this.debug_.moon_light_helper === true) { + if (this.debug_.directional_light_moon_helper === true) { this.directional_light_moon_helper_.update(); this.directional_light_moon_camera_helper_.update(); } - if (this.debug_.sun_light_helper === true) { + if (this.debug_.directional_light_sun_helper === true) { this.directional_light_sun_helper_.update(); this.directional_light_sun_camera_helper_.update(); + }*/ + + if (this.debug_.directional_light_top_helper === true) { + this.directional_light_top_helper_.update(); + // this.directional_light_top_camera_helper_.update(); } - - // Update debug watcher if (this.debug_.watcher === true) { - this.debug_info_.date = date; + // this.debug_info_.date = date; this.update_debug_(); } }; @@ -586,7 +612,7 @@ beestat.component.scene.prototype.update_ = function() { /** * Add some type of ground for the house to sit on. */ -beestat.component.scene.prototype.add_ground_ = function() { +/*beestat.component.scene.prototype.add_ground_ = function() { const size = 40000; const texture = new THREE.TextureLoader().load('img/grass.jpg'); @@ -620,7 +646,8 @@ beestat.component.scene.prototype.add_ground_ = function() { this.scene_.add(grid_helper); } }; -beestat.component.scene.prototype.add_ground_limited_ = function() { +*/ +/*beestat.component.scene.prototype.add_ground_limited_ = function() { const height = 24; const bounding_box = beestat.floor_plan.get_bounding_box(this.floor_plan_id_); @@ -658,7 +685,7 @@ beestat.component.scene.prototype.add_ground_limited_ = function() { ); this.scene_.add(grid_helper); } -}; +};*/ @@ -685,7 +712,7 @@ beestat.component.scene.prototype.add_background_ = function() { * @param {object} room The room to add. */ beestat.component.scene.prototype.add_room_ = function(group, room) { - const color = beestat.style.color.gray.base; + const color = beestat.style.color.gray.dark; var clipper_offset = new ClipperLib.ClipperOffset(); @@ -695,7 +722,7 @@ beestat.component.scene.prototype.add_room_ = function(group, room) { ClipperLib.EndType.etClosedPolygon ); var clipper_hole = new ClipperLib.Path(); - clipper_offset.Execute(clipper_hole, -3); + clipper_offset.Execute(clipper_hole, -1.5); // Full height // const extrude_height = (room.height || group.height) - 3; @@ -717,11 +744,11 @@ beestat.component.scene.prototype.add_room_ = function(group, room) { // Extrude the shape and create the mesh. const extrude_settings = { 'depth': extrude_height, - 'bevelEnabled': true, - 'bevelThickness': 1, - 'bevelSize': 1, - 'bevelOffset': 1, - 'bevelSegments': 5 + 'bevelEnabled': false, + // 'bevelThickness': 1, + // 'bevelSize': 1, + // 'bevelOffset': 1, + // 'bevelSegments': 5 }; const geometry = new THREE.ExtrudeGeometry( diff --git a/js/component/tile.js b/js/component/tile.js index 34ad239..3b48195 100644 --- a/js/component/tile.js +++ b/js/component/tile.js @@ -14,6 +14,19 @@ beestat.extend(beestat.component.tile, beestat.component); beestat.component.tile.prototype.decorate_ = function(parent) { const self = this; + let size_constant; + switch (this.get_size_()) { + case 'large': + size_constant = 48; + break; + case 'small': + size_constant = 24; + break; + case 'medium': + default: + size_constant = 32; + } + const background_color = this.background_color_ || 'none'; const text_color = this.text_color_ || '#fff'; const tabbable = this.tabbable_ || false; @@ -21,7 +34,7 @@ beestat.component.tile.prototype.decorate_ = function(parent) { const display = this.display_ === 'block' ? 'flex' : 'inline-flex'; let border_radius; if (this.type_ === 'pill') { - border_radius = (this.get_size_() === 'large' ? 48 : 36); + border_radius = size_constant; } else { border_radius = beestat.style.size.border_radius; } @@ -31,7 +44,7 @@ beestat.component.tile.prototype.decorate_ = function(parent) { Object.assign(this.container_.style, { 'background': background_color, 'border-radius': `${border_radius}px`, - 'height': `${(this.get_size_() === 'large' ? 48 : 36)}px`, + 'height': `${size_constant}px`, 'display': display, 'align-items': 'center', 'color': text_color, @@ -52,7 +65,7 @@ beestat.component.tile.prototype.decorate_ = function(parent) { // Padding. Basically for icon only make it a nice square button. if (this.get_text_() === undefined) { Object.assign(this.container_.style, { - 'width': `${(this.get_size_() === 'large' ? 48 : 36)}px`, + 'width': `${size_constant}px`, 'justify-content': 'center' }); } else { @@ -200,9 +213,9 @@ beestat.component.tile.prototype.set_icon = function(icon) { }; /** - * Set the size. Default is small. + * Set the size. Default is medium. * - * @param {string} size large|small + * @param {string} size large|medium|small * * @return {beestat.component.tile} This. */ diff --git a/js/js.php b/js/js.php index 9ccc191..247ad02 100755 --- a/js/js.php +++ b/js/js.php @@ -80,6 +80,8 @@ 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; echo '' . PHP_EOL; @@ -119,6 +121,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/visualize.js b/js/layer/visualize.js index 6b2e5aa..56f0e0c 100644 --- a/js/layer/visualize.js +++ b/js/layer/visualize.js @@ -17,6 +17,13 @@ beestat.layer.visualize.prototype.decorate_ = function(parent) { 'padding': '0 ' + beestat.style.size.gutter + 'px' }); + beestat.dispatcher.addEventListener([ + 'setting.visualize.floor_plan_id', + 'setting.visualize.hide_affiliate' + ], function() { + (new beestat.layer.visualize()).render(); + }); + (new beestat.component.header('visualize')).render(parent); // All the cards @@ -31,35 +38,52 @@ beestat.layer.visualize.prototype.decorate_ = function(parent) { ]); } - cards.push([ - { - 'card': new beestat.component.card.visualize_settings(), - 'size': 12 + if ( + beestat.setting('visualize.floor_plan_id') !== null && + beestat.setting('visualize.floor_plan_id') !== undefined + ) { + cards.push([ + { + 'card': new beestat.component.card.floor_plan_editor( + beestat.setting('thermostat_id') + ), + 'size': 12 + } + ]); + + cards.push([ + { + 'card': new beestat.component.card.visualize_settings(), + 'size': 12 + } + ]); + + if (beestat.setting('visualize.hide_affiliate') === false) { + cards.push([ + { + 'card': new beestat.component.card.visualize_affiliate(), + 'size': 12 + } + ]); } - ]); - const three_d = new beestat.component.card.three_d() - .set_floor_plan_id(beestat.setting('visualize.floor_plan_id')); - - beestat.dispatcher.addEventListener('setting.visualize.floor_plan_id', function() { - three_d.set_floor_plan_id(beestat.setting('visualize.floor_plan_id')); - }); - - cards.push([ - { - 'card': three_d, - 'size': 12 - } - ]); - - cards.push([ - { - 'card': new beestat.component.card.floor_plan_editor( - beestat.setting('thermostat_id') - ), - 'size': 12 - } - ]); + cards.push([ + { + 'card': new beestat.component.card.three_d() + .set_floor_plan_id(beestat.setting('visualize.floor_plan_id')), + 'size': 12 + } + ]); + } else { + cards.push([ + { + 'card': new beestat.component.card.visualize_intro( + beestat.setting('thermostat_id') + ), + 'size': 12 + } + ]); + } // Footer cards.push([