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_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"; }

View File

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

View File

@ -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.

View File

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

View File

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

View File

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

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');
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');
}));
};
*/

View File

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

View File

@ -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();

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);
}
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();
});

View File

@ -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();

View File

@ -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(

View File

@ -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.
*/

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/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/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/runtime_thermostat_summary.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/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/change_floor_plan.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/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'
});
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([