1
0
mirror of https://github.com/beestat/app.git synced 2025-07-09 03:04:07 -04:00

Lots of bug fixes and improvements to overall visualize flow

This commit is contained in:
Jon Ziebell 2022-08-24 18:11:12 -04:00
parent 1176c327ed
commit bec632172e
18 changed files with 657 additions and 333 deletions

View File

@ -440,6 +440,8 @@ input[type=radio] {
.icon.chart_bar_stacked:before { content: "\F076A"; } .icon.chart_bar_stacked:before { content: "\F076A"; }
.icon.chart_line:before { content: "\F012A"; } .icon.chart_line:before { content: "\F012A"; }
.icon.check:before { content: "\F012C"; } .icon.check:before { content: "\F012C"; }
.icon.chevron_down:before { content: "\F0140"; }
.icon.chevron_up:before { content: "\F0143"; }
.icon.clock_outline:before { content: "\F0150"; } .icon.clock_outline:before { content: "\F0150"; }
.icon.close:before { content: "\F0156"; } .icon.close:before { content: "\F0156"; }
.icon.close_network:before { content: "\F015B"; } .icon.close_network:before { content: "\F015B"; }
@ -467,6 +469,7 @@ input[type=radio] {
.icon.home:before { content: "\F02DC"; } .icon.home:before { content: "\F02DC"; }
.icon.home_floor_a:before { content: "\F0D83"; } .icon.home_floor_a:before { content: "\F0D83"; }
.icon.home_search:before { content: "\F13B0"; } .icon.home_search:before { content: "\F13B0"; }
.icon.home_switch:before { content: "\F1794"; }
.icon.information:before { content: "\F02FC"; } .icon.information:before { content: "\F02FC"; }
.icon.key:before { content: "\F0306"; } .icon.key:before { content: "\F0306"; }
.icon.label:before { content: "\F0315"; } .icon.label:before { content: "\F0315"; }

View File

@ -58,6 +58,13 @@ beestat.floor_plan.get_area_room = function(room, round = true) {
return area; 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) { beestat.floor_plan.get_bounding_box = function(floor_plan_id) {
const floor_plan = beestat.cache.floor_plan[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) { beestat.floor_plan.get_bounding_box_group = function(group) {
let min_x = Infinity; let min_x = Infinity;
let max_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) { beestat.floor_plan.get_bounding_box_room = function(room) {
let min_x = Infinity; let min_x = Infinity;
let max_x = -Infinity; let max_x = -Infinity;
@ -138,3 +159,25 @@ beestat.floor_plan.get_bounding_box_room = function(room) {
'y': min_y '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;
};

View File

@ -76,13 +76,12 @@ beestat.setting = function(argument_1, opt_value, opt_callback) {
.format('MM/DD/YYYY'), .format('MM/DD/YYYY'),
'visualize.range_static.end': moment() 'visualize.range_static.end': moment()
.format('MM/DD/YYYY'), .format('MM/DD/YYYY'),
'visualize.floor_plan_id': null,
'visualize.heat_map_type': 'relative', 'visualize.heat_map_type': 'relative',
'visualize.heat_map_absolute.temperature.min': 70, 'visualize.heat_map_absolute.temperature.min': 70,
'visualize.heat_map_absolute.temperature.max': 80, 'visualize.heat_map_absolute.temperature.max': 80,
'visualize.heat_map_absolute.occupancy.min': 0, '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. // Figure out what we're trying to do.

View File

@ -1,5 +1,5 @@
beestat.component = function() { beestat.component = function() {
var self = this; const self = this;
this.rendered_ = false; this.rendered_ = false;

View File

@ -8,7 +8,12 @@ beestat.component.card.floor_plan_editor = function(thermostat_id) {
this.thermostat_id_ = 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?) // todo replace these with (if entity set active false?)
delete self.state_.active_group; delete self.state_.active_group;
@ -23,7 +28,7 @@ beestat.component.card.floor_plan_editor = function(thermostat_id) {
beestat.dispatcher.addEventListener( beestat.dispatcher.addEventListener(
'setting.visualize.floor_plan_id', 'setting.visualize.floor_plan_id',
change_function change_function
); );*/
beestat.component.card.apply(this, arguments); 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) { beestat.component.card.floor_plan_editor.prototype.decorate_contents_ = function(parent) {
const self = this; const self = this;
if (Object.keys(beestat.cache.floor_plan).length === 0) { const floor_plan = beestat.cache.floor_plan[beestat.setting('visualize.floor_plan_id')];
const center_container = $.createElement('div').style('text-align', 'center');
parent.appendChild(center_container);
const get_started_button = new beestat.component.tile() // Set group ids if they are not set.
.set_icon('plus') floor_plan.data.groups.forEach(function(group) {
.set_text('Create my first floor plan') if (group.group_id === undefined) {
.set_size('large') group.group_id = window.crypto.randomUUID();
.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. /**
* 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) { floor_plan.data.groups.forEach(function(group) {
if (group.group_id === undefined) { if (Math.abs(group.elevation) < closest_distance) {
group.group_id = window.crypto.randomUUID(); closest_group = group;
closest_distance = Math.abs(group.elevation);
} }
}); });
this.state_.active_group = closest_group;
}
/** this.floor_plan_tile_ = new beestat.component.tile.floor_plan(
* If there is an active_group_id, override whatever the current active beestat.setting('visualize.floor_plan_id')
* group is. Used for undo/redo. )
*/ .set_background_color(beestat.style.color.lightblue.base)
if (this.state_.active_group_id !== undefined) { .set_background_hover_color(beestat.style.color.lightblue.base)
for (let i = 0; i < floor_plan.data.groups.length; i++) { .set_text_color('#fff')
if (floor_plan.data.groups[i].group_id === this.state_.active_group_id) { .set_display('block')
this.state_.active_group = floor_plan.data.groups[i]; .addEventListener('click', function() {
delete this.state_.active_group_id; self.show_editor_ = !self.show_editor_;
break; self.rerender();
} })
} .render(parent);
}
// If there is no active group, set it to best guess of ground floor. // Decorate everything.
if (this.state_.active_group === undefined) { if (this.show_editor_ === true) {
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.
const drawing_pane_container = $.createElement('div'); const drawing_pane_container = $.createElement('div');
drawing_pane_container.style({ drawing_pane_container.style({
'margin-top': beestat.style.size.gutter,
'position': 'relative', 'position': 'relative',
'overflow-x': 'hidden' 'overflow-x': 'hidden'
}); });
@ -118,6 +120,26 @@ beestat.component.card.floor_plan_editor.prototype.decorate_contents_ = function
parent.appendChild(this.info_pane_container_); parent.appendChild(this.info_pane_container_);
this.decorate_info_pane_(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() { room_entity.addEventListener('update', function() {
self.floor_plan_.update_infobox(); self.floor_plan_.update_infobox();
self.update_info_pane_(); self.update_info_pane_();
self.update_floor_plan_tile_();
self.update_floor_plan_(); 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_infobox();
self.floor_plan_.update_toolbar(); self.floor_plan_.update_toolbar();
self.update_info_pane_(); self.update_info_pane_();
self.update_floor_plan_tile_();
}); });
// Update GUI when a room is deselected. // 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_infobox();
self.floor_plan_.update_toolbar(); self.floor_plan_.update_toolbar();
self.update_info_pane_(); 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() { 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() === '') { if (sensor_input.get_value() === '') {
delete self.state_.active_room_entity.get_room().sensor_id; delete self.state_.active_room_entity.get_room().sensor_id;
} else { } else {
self.state_.active_room_entity.get_room().sensor_id = Number(sensor_input.get_value()); 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_(); 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); 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. * 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); const menu = (new beestat.component.menu()).render(parent);
if (window.is_demo === false) { 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() menu.add_menu_item(new beestat.component.menu_item()
.set_text('Add New') .set_text('Add New')
.set_icon('plus') .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_text('Help')
.set_icon('help_circle') .set_icon('help_circle')
.set_callback(function() { .set_callback(function() {
// TODO // TODO
// window.open('https://doc.beestat.io/???'); // window.open('https://doc.beestat.io/???');
})); }));*/
}; };

View File

@ -108,20 +108,33 @@ beestat.component.card.three_d.prototype.decorate_contents_ = function(parent) {
let required_begin; let required_begin;
let required_end; let required_end;
if (beestat.setting('visualize.range_type') === 'dynamic') { if (beestat.setting('visualize.range_type') === 'dynamic') {
required_begin = moment() if (
.subtract( beestat.setting('visualize.range_dynamic') === 0 ||
beestat.setting('visualize.range_dynamic'), beestat.setting('visualize.range_dynamic') === 1
'day' ) {
) // Rig "today" and "yesterday" to behave differently.
.hour(0) required_begin = moment()
.minute(0) .subtract(
.second(0); beestat.setting('visualize.range_dynamic'),
'day'
)
.hour(0)
.minute(0)
.second(0);
required_end = required_begin required_end = required_begin
.clone() .clone()
.hour(23) .hour(23)
.minute(59) .minute(59)
.second(59); .second(59);
} else {
required_begin = moment()
.subtract(
beestat.setting('visualize.range_dynamic'),
'day'
);
required_end = moment();
}
} else { } else {
required_begin = moment( required_begin = moment(
beestat.setting('visualize.range_static_begin') + ' 00:00:00' 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 // 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) { // 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 (sensor_ids.length > 0) {
if (true) { if (true) {
if (beestat.cache.data.three_d__runtime_sensor === undefined) { 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 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) { // if (sensor_ids.length > 0) {
const api_call = new beestat.api(); const api_call = new beestat.api();
sensor_ids.forEach(function(sensor_id) { 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. // Set the initial date.
if (this.has_data_() === true) { // if (this.has_data_() === true) {
this.update_scene_(); this.update_scene_();
this.scene_.render($(parent)); this.scene_.render($(parent));
if (beestat.setting('visualize.range_type') === 'dynamic') { if (beestat.setting('visualize.range_type') === 'dynamic') {
this.date_m_ = moment() this.date_m_ = moment()
.subtract( .subtract(
beestat.setting('visualize.range_dynamic'), beestat.setting('visualize.range_dynamic'),
'day' 'day'
) )
.hour(0) .hour(0)
.minute(0) .minute(0)
.second(0); .second(0);
} else {
this.date_m_ = moment(
beestat.setting('visualize.range_static_begin') + ' 00:00:00'
);
}
this.scene_.set_date(this.date_m_);
} else { } 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. // Manage width of the scene.
setTimeout(function() { setTimeout(function() {
if (parent.getBoundingClientRect().width > 0) { 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) { beestat.component.card.three_d.prototype.get_data_ = function(force) {
const self = this; const self = this;
if (this.data_ === undefined || force === true) { 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_ = { this.data_ = {
'metadata': { 'metadata': {
@ -460,7 +470,6 @@ beestat.component.card.three_d.prototype.get_data_ = function(force) {
} }
} }
} }
// console.log(this.data_);
return this.data_; return this.data_;
}; };
@ -482,32 +491,6 @@ beestat.component.card.three_d.prototype.has_data_ = function() {
return false; 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 * Update the scene with current settings. Anything that doesn't require
* re-rendering can go here. * re-rendering can go here.
@ -559,23 +542,3 @@ beestat.component.card.three_d.prototype.set_floor_plan_id = function(floor_plan
return this; 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;
};

View File

@ -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?';
};

View File

@ -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';
};

View File

@ -45,10 +45,6 @@ beestat.component.card.visualize_settings.prototype.decorate_contents_ = functio
const heat_map_type_container = document.createElement('div'); const heat_map_type_container = document.createElement('div');
this.decorate_heat_map_type_(heat_map_type_container); this.decorate_heat_map_type_(heat_map_type_container);
grid_2.appendChild(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_background_hover_color(color)
.set_text_color('#fff') .set_text_color('#fff')
.set_icon('calendar_week') .set_icon('calendar_week')
.set_text('Last 7 Days'); .set_text('7 Day Average');
if ( if (
beestat.setting('visualize.range_type') === 'dynamic' && beestat.setting('visualize.range_type') === 'dynamic' &&
@ -361,45 +357,6 @@ beestat.component.card.visualize_settings.prototype.decorate_time_period_ = func
tile_group.render($(parent)); 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. * Get the title of the card.
* *
@ -414,7 +371,7 @@ beestat.component.card.visualize_settings.prototype.get_title_ = function() {
* *
* @param {rocket.Elements} parent * @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); var menu = (new beestat.component.menu()).render(parent);
menu.add_menu_item(new beestat.component.menu_item() 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'); // window.open('https://doc.beestat.io/596040eadd014928830b4d1d54692761');
})); }));
}; };
*/

View File

@ -748,6 +748,10 @@ beestat.component.floor_plan.prototype.add_room_ = function(room) {
beestat.component.floor_plan.prototype.remove_room_ = function() { beestat.component.floor_plan.prototype.remove_room_ = function() {
this.save_buffer(); 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 self = this;
const index = this.state_.active_group.rooms.findIndex(function(room) { 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); 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'); 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. * Center the view box on the content. Sets zoom and pan.
*/ */
beestat.component.floor_plan.prototype.center_content = function() { 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_); const bounding_box = beestat.floor_plan.get_bounding_box(this.floor_plan_id_);
this.reset_view_box_(); this.reset_view_box_();
// TODO ADD THIS BACK IN if (
// if (has_content === true) { bounding_box.x !== Infinity &&
bounding_box.y !== Infinity
) {
const width = (bounding_box.width) + 50; const width = (bounding_box.width) + 50;
const height = (bounding_box.height) + 50; const height = (bounding_box.height) + 50;
while ( 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.view_box_.y = center_y - (this.view_box_.height / 2);
this.update_view_box_(); 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() { beestat.component.floor_plan.prototype.undo_ = function() {
if (this.can_undo_() === true) { 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 * 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. * 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_.active_group_id =
this.state_.buffer[this.state_.buffer_pointer].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.update_toolbar();
this.dispatchEvent('undo'); this.dispatchEvent('undo');
} }
@ -1091,6 +1100,10 @@ beestat.component.floor_plan.prototype.can_undo_ = function() {
*/ */
beestat.component.floor_plan.prototype.redo_ = function() { beestat.component.floor_plan.prototype.redo_ = function() {
if (this.can_redo_() === true) { 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++; this.state_.buffer_pointer++;
// Restore the floor plan. // Restore the floor plan.
beestat.cache.floor_plan[this.floor_plan_id_] = 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_.active_group_id =
this.state_.buffer[this.state_.buffer_pointer].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.update_toolbar();
this.dispatchEvent('redo'); this.dispatchEvent('redo');
} }

View File

@ -26,28 +26,58 @@ beestat.component.header.prototype.decorate_ = function(parent) {
var pages; var pages;
pages = [ if (beestat.user.has_early_access() === true) {
{ pages = [
'layer': 'detail', {
'text': 'Detail', 'layer': 'detail',
'icon': 'eye_circle' 'text': 'Detail',
}, 'icon': 'eye_circle'
{ },
'layer': 'analyze', {
'text': 'Analyze', 'layer': 'analyze',
'icon': 'home_search' 'text': 'Analyze',
}, 'icon': 'home_search'
{ },
'layer': 'compare', // {
'text': 'Compare', // 'layer': 'visualize',
'icon': 'earth' // 'text': 'Visualize',
}, // 'icon': 'floor_plan'
{ // },
'layer': 'air_quality', {
'text': 'Air Quality', 'layer': 'compare',
'icon': 'weather_windy' '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(); pages.push();

View File

@ -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';
};

View File

@ -232,7 +232,6 @@ beestat.component.modal.create_floor_plan.prototype.get_buttons_ = function() {
elevation += (self.state_.height * 12); elevation += (self.state_.height * 12);
} }
self.dispose();
new beestat.api() new beestat.api()
.add_call( .add_call(
'floor_plan', 'floor_plan',
@ -249,8 +248,8 @@ beestat.component.modal.create_floor_plan.prototype.get_buttons_ = function() {
'floor_plan' 'floor_plan'
) )
.set_callback(function(response) { .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.cache.set('floor_plan', response.floor_plan);
beestat.setting('visualize.floor_plan_id', response.new_floor_plan.floor_plan_id);
}) })
.send(); .send();
}); });

View File

@ -59,7 +59,6 @@ beestat.component.modal.delete_floor_plan.prototype.get_buttons_ = function() {
.set_text_color('#fff') .set_text_color('#fff')
.set_text('Delete Floor Plan') .set_text('Delete Floor Plan')
.addEventListener('click', function() { .addEventListener('click', function() {
self.dispose();
new beestat.api() new beestat.api()
.add_call( .add_call(
'floor_plan', 'floor_plan',
@ -76,13 +75,14 @@ beestat.component.modal.delete_floor_plan.prototype.get_buttons_ = function() {
'floor_plan' 'floor_plan'
) )
.set_callback(function(response) { .set_callback(function(response) {
console.log('deleted fp'); self.dispose();
console.log(response);
if (Object.keys(response.floor_plan).length > 0) { if (Object.keys(response.floor_plan).length > 0) {
beestat.setting('visualize.floor_plan_id', Object.values(response.floor_plan)[0].floor_plan_id); beestat.setting('visualize.floor_plan_id', Object.values(response.floor_plan)[0].floor_plan_id);
} else { } else {
beestat.setting('visualize.floor_plan_id', null); beestat.setting('visualize.floor_plan_id', null);
} }
beestat.cache.set('floor_plan', response.floor_plan); beestat.cache.set('floor_plan', response.floor_plan);
}) })
.send(); .send();

View File

@ -12,24 +12,35 @@ beestat.component.scene = function(floor_plan_id, data) {
}; };
beestat.extend(beestat.component.scene, beestat.component); beestat.extend(beestat.component.scene, beestat.component);
beestat.component.scene.sun_light_intensity = 1; // beestat.component.scene.sun_light_intensity = 1;
beestat.component.scene.moon_light_intensity = 0.3; // 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; * Brightness of the top-down light. This gives definition to the sides of
beestat.component.scene.moon_opacity = 0.9; * 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; * Brightness of the ambient light. Works with the top light to provide a base
beestat.component.scene.mie_coefficient = 0.001; * level of light to the scene.
beestat.component.scene.mie_directional_g = 0.95; */
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.turbidity = 14;
// beestat.component.scene.rayleigh = 0.7; // beestat.component.scene.rayleigh = 0.7;
// beestat.component.scene.mie_coefficient = 0.008; // beestat.component.scene.mie_coefficient = 0.008;
// beestat.component.scene.mie_directional_g = 0.9; // 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 * 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; const self = this;
this.debug_ = { this.debug_ = {
'axes': false, 'axes': true,
'moon_light_helper': false, // 'directional_light_moon_helper': false,
'sun_light_helper': false, // 'directional_light_sun_helper': false,
'grid': false, 'directional_light_top_helper': false,
// 'grid': false,
'watcher': false 'watcher': false
}; };
@ -82,9 +94,10 @@ beestat.component.scene.prototype.decorate_ = function(parent) {
this.add_controls_(parent); this.add_controls_(parent);
// this.add_sky_(); // this.add_sky_();
// this.add_moon_(); // this.add_moon_();
// this.add_moon_light_(); // this.add_directional_light_moon_();
this.add_sun_light_(); // this.add_directional_light_sun_();
this.add_ambient_light_(); this.add_ambient_light_();
this.add_directional_light_top_();
// this.add_ground_(); // this.add_ground_();
// this.add_ground_limited_(); // this.add_ground_limited_();
@ -163,17 +176,17 @@ beestat.component.scene.prototype.add_renderer_ = function(parent) {
this.renderer_ = new THREE.WebGLRenderer({ this.renderer_ = new THREE.WebGLRenderer({
'antialias': true 'antialias': true
}); });
this.renderer_.setSize(window.innerWidth /1.1, window.innerHeight / 1.1); // this.renderer_.setSize(window.innerWidth, window.innerHeight);
this.renderer_.shadowMap.enabled = true; // this.renderer_.shadowMap.enabled = true;
this.renderer_.shadowMap.autoUpdate = false; // this.renderer_.shadowMap.autoUpdate = false;
/* /*
* Added these to make the sky not look like crap. * Added these to make the sky not look like crap.
* https://threejs.org/examples/webgl_shaders_sky.html * 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.5;
this.renderer_.toneMappingExposure = 0.2; // this.renderer_.toneMappingExposure = 0.2;
parent[0].appendChild(this.renderer_.domElement); 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 * The sky material uniforms are configured to make the sky look generally
* nice. They are tweaked for the eclipse simulation to darken the sky. * 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(); this.sky_ = new THREE.Sky();
// Makes the sky box really big. // Makes the sky box really big.
@ -240,13 +253,13 @@ beestat.component.scene.prototype.add_sky_ = function() {
beestat.component.scene.mie_directional_g; beestat.component.scene.mie_directional_g;
this.scene_.add(this.sky_); this.scene_.add(this.sky_);
}; };*/
/** /**
* Adds a moon sprite to the scene. The scale is set arbitrarily to make it * Adds a moon sprite to the scene. The scale is set arbitrarily to make it
* roughly the size of the sun. * 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 map = new THREE.TextureLoader().load('img/moon.png');
const material = new THREE.SpriteMaterial({'map': map}); const material = new THREE.SpriteMaterial({'map': map});
const scale = 700; const scale = 700;
@ -254,12 +267,12 @@ beestat.component.scene.prototype.add_moon_ = function() {
this.moon_ = new THREE.Sprite(material); this.moon_ = new THREE.Sprite(material);
this.moon_.scale.set(scale, scale, scale); this.moon_.scale.set(scale, scale, scale);
// this.scene_.add(this.moon_); // this.scene_.add(this.moon_);
}; };*/
/** /**
* Adds a faint moon light so the moon can cast shadows at night. * 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( this.directional_light_moon_ = new THREE.DirectionalLight(
0xfffbab, 0xfffbab,
0.2 0.2
@ -274,7 +287,7 @@ beestat.component.scene.prototype.add_moon_light_ = function() {
this.directional_light_moon_.shadow.camera.far = 10000; this.directional_light_moon_.shadow.camera.far = 10000;
// this.scene_.add(this.directional_light_moon_); // 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_helper_ = new THREE.DirectionalLightHelper(
this.directional_light_moon_ 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_); this.scene_.add(this.directional_light_moon_camera_helper_);
} }
}; };*/
/** /**
* Add a strong sun light to the scene. * 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. // Directional light to cast shadows.
this.directional_light_sun_ = new THREE.DirectionalLight( this.directional_light_sun_ = new THREE.DirectionalLight(
0xffffff, 0xffffff,
@ -308,7 +321,7 @@ beestat.component.scene.prototype.add_sun_light_ = function() {
this.directional_light_sun_.shadow.camera.far = 10000; this.directional_light_sun_.shadow.camera.far = 10000;
this.scene_.add(this.directional_light_sun_); 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_helper_ = new THREE.DirectionalLightHelper(
this.directional_light_sun_ 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_); 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() { 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( this.scene_.add(new THREE.AmbientLight(
0xffffff, 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 // TODO TEMP TO KEEP LIGHTING CONSISTENT
// const date = new Date('2022-08-16 12:00:00'); // const date = new Date('2022-08-16 12:00:00');
// const date = this.date_.toDate(); // const date = this.date_.toDate();
const date = moment() /*const date = moment()
.hour(12) .hour(12)
.minute(0) .minute(0)
.second(0) .second(0)
@ -477,7 +501,7 @@ beestat.component.scene.prototype.update_ = function() {
const eclipse_percentage = Math.max( const eclipse_percentage = Math.max(
0, 0,
(1 - (sun_moon_distance / eclipse_begins_distance)) (1 - (sun_moon_distance / eclipse_begins_distance))
); );*/
/* /*
* this.ambient_light_sky_.intensity = * this.ambient_light_sky_.intensity =
@ -490,10 +514,10 @@ beestat.component.scene.prototype.update_ = function() {
*/ */
// Set light intensities by altitude and eclipse percentage. // Set light intensities by altitude and eclipse percentage.
this.ambient_light_sky_.intensity = Math.max( /* this.ambient_light_sky_.intensity = Math.max(
0, 0,
beestat.component.scene.ambient_light_intensity_sky * Math.sin(sun_position.altitude) * (1 - eclipse_percentage) beestat.component.scene.ambient_light_intensity_sky * Math.sin(sun_position.altitude) * (1 - eclipse_percentage)
); );*/
// this.moon_.material.opacity = 0.2; // this.moon_.material.opacity = 0.2;
@ -502,7 +526,7 @@ beestat.component.scene.prototype.update_ = function() {
*/ */
// Turn down to 0 // Turn down to 0
if (this.sky_ !== undefined) { /*if (this.sky_ !== undefined) {
this.sky_.material.uniforms.rayleigh.value = this.sky_.material.uniforms.rayleigh.value =
beestat.component.scene.rayleigh * (1 - eclipse_percentage); 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.sky_.material.uniforms.sunPosition.value.copy(sun_object_vector);
} }*/
/* /*
* this.renderer_.toneMappingExposure = Math.max( * this.renderer_.toneMappingExposure = Math.max(
@ -531,11 +555,10 @@ beestat.component.scene.prototype.update_ = function() {
*/ */
// Set the brightness of the sun // Set the brightness of the sun
if (this.directional_light_sun_ !== undefined) { /*if (this.directional_light_sun_ !== undefined) {
this.directional_light_sun_.intensity = this.directional_light_sun_.intensity =
beestat.component.scene.sun_light_intensity * Math.sin(sun_position.altitude) * (1 - eclipse_percentage); beestat.component.scene.sun_light_intensity * Math.sin(sun_position.altitude) * (1 - eclipse_percentage);
this.directional_light_sun_.position.copy(sun_light_vector); this.directional_light_sun_.position.copy(sun_light_vector);
} }
// Set the brightness of the moon // Set the brightness of the moon
@ -547,7 +570,7 @@ beestat.component.scene.prototype.update_ = function() {
if (this.moon_ !== undefined) { if (this.moon_ !== undefined) {
this.moon_.position.copy(moon_object_vector); this.moon_.position.copy(moon_object_vector);
} }*/
// TODO size of moon based on distance? Might not be worth it haha. // 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); // this.sky2_.material.uniforms.sunPosition.value.copy(moon_object_vector);
// Update shadows // 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_helper_.update();
this.directional_light_moon_camera_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_helper_.update();
this.directional_light_sun_camera_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 // Update debug watcher
if (this.debug_.watcher === true) { if (this.debug_.watcher === true) {
this.debug_info_.date = date; // this.debug_info_.date = date;
this.update_debug_(); this.update_debug_();
} }
}; };
@ -586,7 +612,7 @@ beestat.component.scene.prototype.update_ = function() {
/** /**
* Add some type of ground for the house to sit on. * 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 size = 40000;
const texture = new THREE.TextureLoader().load('img/grass.jpg'); 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); 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 height = 24;
const bounding_box = beestat.floor_plan.get_bounding_box(this.floor_plan_id_); 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); this.scene_.add(grid_helper);
} }
}; };*/
@ -685,7 +712,7 @@ beestat.component.scene.prototype.add_background_ = function() {
* @param {object} room The room to add. * @param {object} room The room to add.
*/ */
beestat.component.scene.prototype.add_room_ = function(group, room) { 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(); var clipper_offset = new ClipperLib.ClipperOffset();
@ -695,7 +722,7 @@ beestat.component.scene.prototype.add_room_ = function(group, room) {
ClipperLib.EndType.etClosedPolygon ClipperLib.EndType.etClosedPolygon
); );
var clipper_hole = new ClipperLib.Path(); var clipper_hole = new ClipperLib.Path();
clipper_offset.Execute(clipper_hole, -3); clipper_offset.Execute(clipper_hole, -1.5);
// Full height // Full height
// const extrude_height = (room.height || group.height) - 3; // 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. // Extrude the shape and create the mesh.
const extrude_settings = { const extrude_settings = {
'depth': extrude_height, 'depth': extrude_height,
'bevelEnabled': true, 'bevelEnabled': false,
'bevelThickness': 1, // 'bevelThickness': 1,
'bevelSize': 1, // 'bevelSize': 1,
'bevelOffset': 1, // 'bevelOffset': 1,
'bevelSegments': 5 // 'bevelSegments': 5
}; };
const geometry = new THREE.ExtrudeGeometry( const geometry = new THREE.ExtrudeGeometry(

View File

@ -14,6 +14,19 @@ beestat.extend(beestat.component.tile, beestat.component);
beestat.component.tile.prototype.decorate_ = function(parent) { beestat.component.tile.prototype.decorate_ = function(parent) {
const self = this; 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 background_color = this.background_color_ || 'none';
const text_color = this.text_color_ || '#fff'; const text_color = this.text_color_ || '#fff';
const tabbable = this.tabbable_ || false; const tabbable = this.tabbable_ || false;
@ -21,7 +34,7 @@ beestat.component.tile.prototype.decorate_ = function(parent) {
const display = this.display_ === 'block' ? 'flex' : 'inline-flex'; const display = this.display_ === 'block' ? 'flex' : 'inline-flex';
let border_radius; let border_radius;
if (this.type_ === 'pill') { if (this.type_ === 'pill') {
border_radius = (this.get_size_() === 'large' ? 48 : 36); border_radius = size_constant;
} else { } else {
border_radius = beestat.style.size.border_radius; border_radius = beestat.style.size.border_radius;
} }
@ -31,7 +44,7 @@ beestat.component.tile.prototype.decorate_ = function(parent) {
Object.assign(this.container_.style, { Object.assign(this.container_.style, {
'background': background_color, 'background': background_color,
'border-radius': `${border_radius}px`, 'border-radius': `${border_radius}px`,
'height': `${(this.get_size_() === 'large' ? 48 : 36)}px`, 'height': `${size_constant}px`,
'display': display, 'display': display,
'align-items': 'center', 'align-items': 'center',
'color': text_color, '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. // Padding. Basically for icon only make it a nice square button.
if (this.get_text_() === undefined) { if (this.get_text_() === undefined) {
Object.assign(this.container_.style, { Object.assign(this.container_.style, {
'width': `${(this.get_size_() === 'large' ? 48 : 36)}px`, 'width': `${size_constant}px`,
'justify-content': 'center' 'justify-content': 'center'
}); });
} else { } 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. * @return {beestat.component.tile} This.
*/ */

View File

@ -80,6 +80,8 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
echo '<script src="/js/component/card/visualize_settings.js"></script>' . PHP_EOL; echo '<script src="/js/component/card/visualize_settings.js"></script>' . PHP_EOL;
echo '<script src="/js/component/card/air_quality_not_supported.js"></script>' . PHP_EOL; echo '<script src="/js/component/card/air_quality_not_supported.js"></script>' . PHP_EOL;
echo '<script src="/js/component/card/floor_plan_editor.js"></script>' . PHP_EOL; echo '<script src="/js/component/card/floor_plan_editor.js"></script>' . PHP_EOL;
echo '<script src="/js/component/card/visualize_intro.js"></script>' . PHP_EOL;
echo '<script src="/js/component/card/visualize_affiliate.js"></script>' . PHP_EOL;
echo '<script src="/js/component/chart.js"></script>' . PHP_EOL; echo '<script src="/js/component/chart.js"></script>' . PHP_EOL;
echo '<script src="/js/component/chart/runtime_thermostat_summary.js"></script>' . PHP_EOL; echo '<script src="/js/component/chart/runtime_thermostat_summary.js"></script>' . PHP_EOL;
echo '<script src="/js/component/chart/temperature_profiles.js"></script>' . PHP_EOL; echo '<script src="/js/component/chart/temperature_profiles.js"></script>' . PHP_EOL;
@ -119,6 +121,7 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
echo '<script src="/js/component/modal/create_floor_plan.js"></script>' . PHP_EOL; echo '<script src="/js/component/modal/create_floor_plan.js"></script>' . PHP_EOL;
echo '<script src="/js/component/modal/update_floor_plan.js"></script>' . PHP_EOL; echo '<script src="/js/component/modal/update_floor_plan.js"></script>' . PHP_EOL;
echo '<script src="/js/component/modal/delete_floor_plan.js"></script>' . PHP_EOL; echo '<script src="/js/component/modal/delete_floor_plan.js"></script>' . PHP_EOL;
echo '<script src="/js/component/modal/change_floor_plan.js"></script>' . PHP_EOL;
echo '<script src="/js/component/input.js"></script>' . PHP_EOL; echo '<script src="/js/component/input.js"></script>' . PHP_EOL;
echo '<script src="/js/component/input/text.js"></script>' . PHP_EOL; echo '<script src="/js/component/input/text.js"></script>' . PHP_EOL;
echo '<script src="/js/component/input/checkbox.js"></script>' . PHP_EOL; echo '<script src="/js/component/input/checkbox.js"></script>' . PHP_EOL;

View File

@ -17,6 +17,13 @@ beestat.layer.visualize.prototype.decorate_ = function(parent) {
'padding': '0 ' + beestat.style.size.gutter + 'px' '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); (new beestat.component.header('visualize')).render(parent);
// All the cards // All the cards
@ -31,35 +38,52 @@ beestat.layer.visualize.prototype.decorate_ = function(parent) {
]); ]);
} }
cards.push([ if (
{ beestat.setting('visualize.floor_plan_id') !== null &&
'card': new beestat.component.card.visualize_settings(), beestat.setting('visualize.floor_plan_id') !== undefined
'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.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() cards.push([
.set_floor_plan_id(beestat.setting('visualize.floor_plan_id')); {
'card': new beestat.component.card.three_d()
beestat.dispatcher.addEventListener('setting.visualize.floor_plan_id', function() { .set_floor_plan_id(beestat.setting('visualize.floor_plan_id')),
three_d.set_floor_plan_id(beestat.setting('visualize.floor_plan_id')); 'size': 12
}); }
]);
cards.push([ } else {
{ cards.push([
'card': three_d, {
'size': 12 'card': new beestat.component.card.visualize_intro(
} beestat.setting('thermostat_id')
]); ),
'size': 12
cards.push([ }
{ ]);
'card': new beestat.component.card.floor_plan_editor( }
beestat.setting('thermostat_id')
),
'size': 12
}
]);
// Footer // Footer
cards.push([ cards.push([