mirror of
https://github.com/beestat/app.git
synced 2025-05-24 02:14:03 -04:00
More floor plan enhancements and fixes
This commit is contained in:
parent
5678b952a5
commit
0572527d6f
@ -415,6 +415,9 @@ input[type=radio] {
|
||||
.icon.air_filter:before { content: "\F0D43"; }
|
||||
.icon.air_purifier:before { content: "\F0D44"; }
|
||||
.icon.alarm_snooze:before { content: "\F068E"; }
|
||||
.icon.alpha_b:before { content: "\F0AEF"; }
|
||||
.icon.alpha_b_box:before { content: "\F0B09"; }
|
||||
.icon.arrow_expand_vertical:before { content: "\F084F"; }
|
||||
.icon.arrow_left:before { content: "\F004D"; }
|
||||
.icon.basket_fill:before { content: "\F0077"; }
|
||||
.icon.basket_unfill:before { content: "\F0078"; }
|
||||
@ -461,21 +464,40 @@ input[type=radio] {
|
||||
.icon.home_search:before { content: "\F13B0"; }
|
||||
.icon.information:before { content: "\F02FC"; }
|
||||
.icon.key:before { content: "\F0306"; }
|
||||
.icon.label:before { content: "\F0315"; }
|
||||
.icon.layers:before { content: "\F0328"; }
|
||||
.icon.layers_plus:before { content: "\F0E4D"; }
|
||||
.icon.magnify_close:before { content: "\F0980"; }
|
||||
.icon.magnify_plus_outline:before { content: "\F06ED"; }
|
||||
.icon.magnify_minus_outline:before { content: "\F06EC"; }
|
||||
.icon.magnify_plus_outline:before { content: "\F06ED"; }
|
||||
.icon.map_marker:before { content: "\F05F8"; }
|
||||
.icon.menu_down:before { content: "\F035D"; }
|
||||
.icon.menu_up:before { content: "\F0360"; }
|
||||
.icon.message:before { content: "\F0361"; }
|
||||
.icon.network_strength_4:before { content: "\F08FA"; }
|
||||
.icon.network_strength_off:before { content: "\F08FC"; }
|
||||
/*.icon.numeric_1_box:before { content: "\F03A4"; }
|
||||
.icon.numeric_0:before { content: "\F0B39"; }
|
||||
.icon.numeric_0_box:before { content: "\F03A1"; }
|
||||
.icon.numeric_10:before { content: "\F0FE9"; }
|
||||
.icon.numeric_10_box:before { content: "\F0F7D"; }
|
||||
.icon.numeric_1:before { content: "\F0B3A"; }
|
||||
.icon.numeric_1_box:before { content: "\F03A4"; }
|
||||
.icon.numeric_2:before { content: "\F0B3B"; }
|
||||
.icon.numeric_2_box:before { content: "\F03A7"; }
|
||||
.icon.numeric_3:before { content: "\F0B3C"; }
|
||||
.icon.numeric_3_box:before { content: "\F03AA"; }
|
||||
.icon.numeric_4:before { content: "\F0B3D"; }
|
||||
.icon.numeric_4_box:before { content: "\F03AD"; }
|
||||
.icon.numeric_7_box:before { content: "\F03B6"; }*/
|
||||
.icon.numeric_5:before { content: "\F0B3E"; }
|
||||
.icon.numeric_5_box:before { content: "\F03B1"; }
|
||||
.icon.numeric_6:before { content: "\F0B3F"; }
|
||||
.icon.numeric_6_box:before { content: "\F03B3"; }
|
||||
.icon.numeric_7:before { content: "\F0B40"; }
|
||||
.icon.numeric_7_box:before { content: "\F03B6"; }
|
||||
.icon.numeric_8:before { content: "\F0B41"; }
|
||||
.icon.numeric_8_box:before { content: "\F03B9"; }
|
||||
.icon.numeric_9:before { content: "\F0B42"; }
|
||||
.icon.numeric_9_box:before { content: "\F03BC"; }
|
||||
.icon.open_in_new:before { content: "\F03CC"; }
|
||||
.icon.patreon:before { content: "\F0882"; }
|
||||
.icon.pound:before { content: "\F0423"; }
|
||||
@ -508,88 +530,9 @@ input[type=radio] {
|
||||
.icon.wifi_strength_1_alert:before { content: "\F0920"; }
|
||||
.icon.wifi_strength_4:before { content: "\F0928"; }
|
||||
.icon.zigbee:before { content: "\F0D41"; }
|
||||
.icon.home_plus:before { content: "\F0975"; }
|
||||
.icon.home_switch:before { content: "\F1794"; }
|
||||
.icon.home_remove:before { content: "\F1247"; }
|
||||
.icon.arrow_expand_vertical:before { content: "\F084F"; }
|
||||
.icon.label:before { content: "\F0315"; }
|
||||
|
||||
.icon.numeric_0:before { content: "\F0B39"; }
|
||||
.icon.numeric_0_box:before { content: "\F03A1"; }
|
||||
.icon.numeric_1:before { content: "\F0B3A"; }
|
||||
.icon.numeric_1_box:before { content: "\F03A4"; }
|
||||
.icon.numeric_10:before { content: "\F0FE9"; }
|
||||
.icon.numeric_10_box:before { content: "\F0F7D"; }
|
||||
.icon.numeric_2:before { content: "\F0B3B"; }
|
||||
.icon.numeric_2_box:before { content: "\F03A7"; }
|
||||
.icon.numeric_3:before { content: "\F0B3C"; }
|
||||
.icon.numeric_3_box:before { content: "\F03AA"; }
|
||||
.icon.numeric_4:before { content: "\F0B3D"; }
|
||||
.icon.numeric_4_box:before { content: "\F03AD"; }
|
||||
.icon.numeric_5:before { content: "\F0B3E"; }
|
||||
.icon.numeric_5_box:before { content: "\F03B1"; }
|
||||
.icon.numeric_6:before { content: "\F0B3F"; }
|
||||
.icon.numeric_6_box:before { content: "\F03B3"; }
|
||||
.icon.numeric_7:before { content: "\F0B40"; }
|
||||
.icon.numeric_7_box:before { content: "\F03B6"; }
|
||||
.icon.numeric_8:before { content: "\F0B41"; }
|
||||
.icon.numeric_8_box:before { content: "\F03B9"; }
|
||||
.icon.numeric_9:before { content: "\F0B42"; }
|
||||
.icon.numeric_9_box:before { content: "\F03BC"; }
|
||||
.icon.alpha_a:before { content: "\F0AEE"; }
|
||||
.icon.alpha_a_box:before { content: "\F0B08"; }
|
||||
.icon.alpha_b:before { content: "\F0AEF"; }
|
||||
.icon.alpha_b_box:before { content: "\F0B09"; }
|
||||
.icon.alpha_c:before { content: "\F0AF0"; }
|
||||
.icon.alpha_c_box:before { content: "\F0B0A"; }
|
||||
.icon.alpha_d:before { content: "\F0AF1"; }
|
||||
.icon.alpha_d_box:before { content: "\F0B0B"; }
|
||||
.icon.alpha_e:before { content: "\F0AF2"; }
|
||||
.icon.alpha_e_box:before { content: "\F0B0C"; }
|
||||
.icon.alpha_f:before { content: "\F0AF3"; }
|
||||
.icon.alpha_f_box:before { content: "\F0B0D"; }
|
||||
.icon.alpha_g:before { content: "\F0AF4"; }
|
||||
.icon.alpha_g_box:before { content: "\F0B0E"; }
|
||||
.icon.alpha_h:before { content: "\F0AF5"; }
|
||||
.icon.alpha_h_box:before { content: "\F0B0F"; }
|
||||
.icon.alpha_i:before { content: "\F0AF6"; }
|
||||
.icon.alpha_i_box:before { content: "\F0B10"; }
|
||||
.icon.alpha_j:before { content: "\F0AF7"; }
|
||||
.icon.alpha_j_box:before { content: "\F0B11"; }
|
||||
.icon.alpha_k:before { content: "\F0AF8"; }
|
||||
.icon.alpha_k_box:before { content: "\F0B12"; }
|
||||
.icon.alpha_l:before { content: "\F0AF9"; }
|
||||
.icon.alpha_l_box:before { content: "\F0B13"; }
|
||||
.icon.alpha_m:before { content: "\F0AFA"; }
|
||||
.icon.alpha_m_box:before { content: "\F0B14"; }
|
||||
.icon.alpha_n:before { content: "\F0AFB"; }
|
||||
.icon.alpha_n_box:before { content: "\F0B15"; }
|
||||
.icon.alpha_o:before { content: "\F0AFC"; }
|
||||
.icon.alpha_o_box:before { content: "\F0B16"; }
|
||||
.icon.alpha_p:before { content: "\F0AFD"; }
|
||||
.icon.alpha_p_box:before { content: "\F0B17"; }
|
||||
.icon.alpha_q:before { content: "\F0AFE"; }
|
||||
.icon.alpha_q_box:before { content: "\F0B18"; }
|
||||
.icon.alpha_r:before { content: "\F0AFF"; }
|
||||
.icon.alpha_r_box:before { content: "\F0B19"; }
|
||||
.icon.alpha_s:before { content: "\F0B00"; }
|
||||
.icon.alpha_s_box:before { content: "\F0B1A"; }
|
||||
.icon.alpha_t:before { content: "\F0B01"; }
|
||||
.icon.alpha_t_box:before { content: "\F0B1B"; }
|
||||
.icon.alpha_u:before { content: "\F0B02"; }
|
||||
.icon.alpha_u_box:before { content: "\F0B1C"; }
|
||||
.icon.alpha_v:before { content: "\F0B03"; }
|
||||
.icon.alpha_v_box:before { content: "\F0B1D"; }
|
||||
.icon.alpha_w:before { content: "\F0B04"; }
|
||||
.icon.alpha_w_box:before { content: "\F0B1E"; }
|
||||
.icon.alpha_x:before { content: "\F0B05"; }
|
||||
.icon.alpha_x_box:before { content: "\F0B1F"; }
|
||||
.icon.alpha_y:before { content: "\F0B06"; }
|
||||
.icon.alpha_y_box:before { content: "\F0B20"; }
|
||||
.icon.alpha_z:before { content: "\F0B07"; }
|
||||
.icon.alpha_z_box:before { content: "\F0B21"; }
|
||||
|
||||
|
||||
.icon.pencil:before { content: "\F03EB"; }
|
||||
.icon.plus:before { content: "\F0415"; }
|
||||
.icon.delete:before { content: "\F01B4"; }
|
||||
|
||||
.icon.f16:before { font-size: 16px; }
|
||||
.icon.f24:before { font-size: 24px; }
|
||||
|
@ -14,7 +14,9 @@ beestat.component.card.floor_plan_editor = function(thermostat_id) {
|
||||
self.rerender();
|
||||
|
||||
// Center the content if the floor plan changed.
|
||||
self.floor_plan_.center_content();
|
||||
if (self.floor_plan_ !== undefined) {
|
||||
self.floor_plan_.center_content();
|
||||
}
|
||||
}, 10);
|
||||
|
||||
beestat.dispatcher.addEventListener(
|
||||
@ -33,10 +35,12 @@ beestat.component.card.floor_plan_editor = function(thermostat_id) {
|
||||
}
|
||||
|
||||
// The first time this component renders center the content.
|
||||
this.addEventListener('render', function() {
|
||||
self.floor_plan_.center_content();
|
||||
self.removeEventListener('render');
|
||||
});
|
||||
if (self.floor_plan_ !== undefined) {
|
||||
this.addEventListener('render', function() {
|
||||
self.floor_plan_.center_content();
|
||||
self.removeEventListener('render');
|
||||
});
|
||||
}
|
||||
};
|
||||
beestat.extend(beestat.component.card.floor_plan_editor, beestat.component.card);
|
||||
|
||||
@ -52,10 +56,10 @@ beestat.component.card.floor_plan_editor.prototype.decorate_contents_ = function
|
||||
const center_container = $.createElement('div').style('text-align', 'center');
|
||||
parent.appendChild(center_container);
|
||||
|
||||
center_container.appendChild($.createElement('p').innerText('You haven\'t created any floor plans yet.'));
|
||||
const get_started_button = new beestat.component.tile()
|
||||
.set_icon('home_plus')
|
||||
.set_text('Get Started')
|
||||
.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)
|
||||
@ -251,9 +255,9 @@ beestat.component.card.floor_plan_editor.prototype.decorate_info_pane_floor_ = f
|
||||
div = $.createElement('div');
|
||||
grid.appendChild(div);
|
||||
const elevation_input = new beestat.component.input.text()
|
||||
.set_label('Elevation (inches)')
|
||||
.set_placeholder(this.state_.active_group.elevation)
|
||||
.set_value(this.state_.active_group.elevation || '')
|
||||
.set_label('Elevation (feet)')
|
||||
.set_placeholder(this.state_.active_group.elevation / 12)
|
||||
.set_value(this.state_.active_group.elevation / 12 || '')
|
||||
.set_width('100%')
|
||||
.set_maxlength('5')
|
||||
.set_requirements({
|
||||
@ -262,12 +266,11 @@ beestat.component.card.floor_plan_editor.prototype.decorate_info_pane_floor_ = f
|
||||
})
|
||||
.render(div);
|
||||
|
||||
elevation_input.set_value(this.state_.active_group.elevation);
|
||||
|
||||
elevation_input.addEventListener('change', function() {
|
||||
if (elevation_input.meets_requirements() === true) {
|
||||
self.state_.active_group.elevation = elevation_input.get_value();
|
||||
self.state_.active_group.elevation = elevation_input.get_value() * 12;
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
} else {
|
||||
elevation_input.set_value(self.state_.active_group.elevation);
|
||||
}
|
||||
@ -277,9 +280,9 @@ beestat.component.card.floor_plan_editor.prototype.decorate_info_pane_floor_ = f
|
||||
div = $.createElement('div');
|
||||
grid.appendChild(div);
|
||||
const height_input = new beestat.component.input.text()
|
||||
.set_label('Ceiling Height (inches)')
|
||||
.set_placeholder(this.state_.active_group.height)
|
||||
.set_value(this.state_.active_group.height || '')
|
||||
.set_label('Ceiling Height (feet)')
|
||||
.set_placeholder(this.state_.active_group.height / 12)
|
||||
.set_value(this.state_.active_group.height / 12 || '')
|
||||
.set_width('100%')
|
||||
.set_maxlength('4')
|
||||
.set_requirements({
|
||||
@ -289,11 +292,9 @@ beestat.component.card.floor_plan_editor.prototype.decorate_info_pane_floor_ = f
|
||||
})
|
||||
.render(div);
|
||||
|
||||
height_input.set_value(this.state_.active_group.height);
|
||||
|
||||
height_input.addEventListener('change', function() {
|
||||
if (height_input.meets_requirements() === true) {
|
||||
self.state_.active_group.height = height_input.get_value();
|
||||
self.state_.active_group.height = height_input.get_value() * 12;
|
||||
self.update_floor_plan_();
|
||||
} else {
|
||||
height_input.set_value(self.state_.active_group.height);
|
||||
@ -353,9 +354,9 @@ beestat.component.card.floor_plan_editor.prototype.decorate_info_pane_room_ = fu
|
||||
div = $.createElement('div');
|
||||
grid.appendChild(div);
|
||||
const elevation_input = new beestat.component.input.text()
|
||||
.set_label('Elevation (inches)')
|
||||
.set_placeholder(this.state_.active_group.elevation)
|
||||
.set_value(this.state_.active_room.elevation || '')
|
||||
.set_label('Elevation (feet)')
|
||||
.set_placeholder(this.state_.active_group.elevation / 12)
|
||||
.set_value(this.state_.active_room.elevation / 12 || '')
|
||||
.set_width('100%')
|
||||
.set_maxlength('5')
|
||||
.set_requirements({
|
||||
@ -363,14 +364,11 @@ beestat.component.card.floor_plan_editor.prototype.decorate_info_pane_room_ = fu
|
||||
})
|
||||
.render(div);
|
||||
|
||||
if (this.state_.active_room.elevation !== undefined) {
|
||||
elevation_input.set_value(this.state_.active_room.elevation);
|
||||
}
|
||||
|
||||
elevation_input.addEventListener('change', function() {
|
||||
if (elevation_input.meets_requirements() === true) {
|
||||
self.state_.active_room.elevation = elevation_input.get_value();
|
||||
self.state_.active_room.elevation = elevation_input.get_value() * 12;
|
||||
self.update_floor_plan_();
|
||||
self.rerender();
|
||||
} else {
|
||||
elevation_input.set_value('');
|
||||
}
|
||||
@ -380,9 +378,9 @@ beestat.component.card.floor_plan_editor.prototype.decorate_info_pane_room_ = fu
|
||||
div = $.createElement('div');
|
||||
grid.appendChild(div);
|
||||
const height_input = new beestat.component.input.text()
|
||||
.set_label('Ceiling Height (inches)')
|
||||
.set_placeholder(this.state_.active_group.height)
|
||||
.set_value(this.state_.active_room.height || '')
|
||||
.set_label('Ceiling Height (feet)')
|
||||
.set_placeholder(this.state_.active_group.height / 12)
|
||||
.set_value(this.state_.active_room.height / 12 || '')
|
||||
.set_width('100%')
|
||||
.set_maxlength('4')
|
||||
.set_requirements({
|
||||
@ -391,13 +389,9 @@ beestat.component.card.floor_plan_editor.prototype.decorate_info_pane_room_ = fu
|
||||
})
|
||||
.render(div);
|
||||
|
||||
if (this.state_.active_room.height !== undefined) {
|
||||
height_input.set_value(this.state_.active_room.height);
|
||||
}
|
||||
|
||||
height_input.addEventListener('change', function() {
|
||||
if (height_input.meets_requirements() === true) {
|
||||
self.state_.active_room.height = height_input.get_value();
|
||||
self.state_.active_room.height = height_input.get_value() * 12;
|
||||
self.update_floor_plan_();
|
||||
} else {
|
||||
height_input.set_value('');
|
||||
@ -491,22 +485,26 @@ beestat.component.card.floor_plan_editor.prototype.get_subtitle_ = function() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the floor plan in the database.
|
||||
* Update the floor plan in the database. This is throttled so the update can
|
||||
* only run so fast.
|
||||
*/
|
||||
beestat.component.card.floor_plan_editor.prototype.update_floor_plan_ = function() {
|
||||
new beestat.api()
|
||||
.add_call(
|
||||
'floor_plan',
|
||||
'update',
|
||||
{
|
||||
'attributes': {
|
||||
'floor_plan_id': beestat.setting('floor_plan_id'),
|
||||
'data': beestat.cache.floor_plan[beestat.setting('floor_plan_id')].data
|
||||
}
|
||||
},
|
||||
'update_floor_plan'
|
||||
)
|
||||
.send();
|
||||
window.clearTimeout(this.update_timeout_);
|
||||
this.update_timeout_ = window.setTimeout(function() {
|
||||
new beestat.api()
|
||||
.add_call(
|
||||
'floor_plan',
|
||||
'update',
|
||||
{
|
||||
'attributes': {
|
||||
'floor_plan_id': beestat.setting('floor_plan_id'),
|
||||
'data': beestat.cache.floor_plan[beestat.setting('floor_plan_id')].data
|
||||
}
|
||||
},
|
||||
'update_floor_plan'
|
||||
)
|
||||
.send();
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -522,7 +520,7 @@ beestat.component.card.floor_plan_editor.prototype.decorate_top_right_ = functio
|
||||
if (window.is_demo === false) {
|
||||
menu.add_menu_item(new beestat.component.menu_item()
|
||||
.set_text('Add New')
|
||||
.set_icon('home_plus')
|
||||
.set_icon('plus')
|
||||
.set_callback(function() {
|
||||
new beestat.component.modal.create_floor_plan(
|
||||
self.thermostat_id_
|
||||
@ -532,22 +530,34 @@ beestat.component.card.floor_plan_editor.prototype.decorate_top_right_ = functio
|
||||
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_icon('swap_horizontal')
|
||||
.set_callback(function() {
|
||||
(new beestat.component.modal.change_floor_plan()).render();
|
||||
}));
|
||||
}
|
||||
|
||||
if (beestat.setting('floor_plan_id') !== null) {
|
||||
menu.add_menu_item(new beestat.component.menu_item()
|
||||
.set_text('Edit')
|
||||
.set_icon('pencil')
|
||||
.set_callback(function() {
|
||||
new beestat.component.modal.update_floor_plan(
|
||||
beestat.setting('floor_plan_id')
|
||||
).render();
|
||||
}));
|
||||
}
|
||||
|
||||
if (beestat.setting('floor_plan_id') !== null) {
|
||||
menu.add_menu_item(new beestat.component.menu_item()
|
||||
.set_text('Delete')
|
||||
.set_icon('home_remove')
|
||||
.set_icon('delete')
|
||||
.set_callback(function() {
|
||||
new beestat.component.modal.delete_floor_plan(
|
||||
beestat.setting('floor_plan_id')
|
||||
).render();
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
menu.add_menu_item(new beestat.component.menu_item()
|
||||
|
@ -18,9 +18,20 @@ beestat.component.card.my_home = function(thermostat_id) {
|
||||
beestat.extend(beestat.component.card.my_home, beestat.component.card);
|
||||
|
||||
beestat.component.card.my_home.prototype.decorate_contents_ = function(parent) {
|
||||
this.decorate_system_type_(parent);
|
||||
this.decorate_region_(parent);
|
||||
this.decorate_property_(parent);
|
||||
const system_container = document.createElement('div');
|
||||
system_container.style.marginBottom = `${beestat.style.size.gutter}px`;
|
||||
parent.appendChild(system_container);
|
||||
this.decorate_system_type_($(system_container));
|
||||
|
||||
const region_container = document.createElement('div');
|
||||
region_container.style.marginBottom = `${beestat.style.size.gutter}px`;
|
||||
parent.appendChild(region_container);
|
||||
this.decorate_region_($(region_container));
|
||||
|
||||
const property_container = document.createElement('div');
|
||||
property_container.style.marginBottom = `${beestat.style.size.gutter}px`;
|
||||
parent.appendChild(property_container);
|
||||
this.decorate_property_($(property_container));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -116,6 +116,53 @@ beestat.component.floor_plan.prototype.render = function(parent) {
|
||||
}
|
||||
} else if (e.key.toLowerCase() === 's') {
|
||||
self.toggle_snapping_();
|
||||
} else if (
|
||||
e.key.toLowerCase() === 'c' &&
|
||||
e.ctrlKey === true
|
||||
) {
|
||||
self.state_.copied_room = beestat.clone(self.state_.active_room);
|
||||
} else if (
|
||||
e.key.toLowerCase() === 'v' &&
|
||||
e.ctrlKey === true
|
||||
) {
|
||||
if (self.state_.copied_room !== undefined) {
|
||||
self.add_room_(self.state_.copied_room);
|
||||
}
|
||||
} else if (
|
||||
e.key.toLowerCase() === 'z' &&
|
||||
e.ctrlKey === true
|
||||
) {
|
||||
console.log('undo');
|
||||
} else if (
|
||||
e.key === 'ArrowLeft' ||
|
||||
e.key === 'ArrowRight' ||
|
||||
e.key === 'ArrowUp' ||
|
||||
e.key === 'ArrowDown'
|
||||
) {
|
||||
const entity =
|
||||
self.state_.active_point_entity ||
|
||||
self.state_.active_wall_entity ||
|
||||
self.state_.active_room_entity;
|
||||
|
||||
if (entity !== undefined) {
|
||||
const x = entity.get_x();
|
||||
const y = entity.get_y();
|
||||
|
||||
switch (e.key) {
|
||||
case 'ArrowLeft':
|
||||
entity.set_xy(x === null ? null : x - 1, y);
|
||||
break;
|
||||
case 'ArrowRight':
|
||||
entity.set_xy(x === null ? null : x + 1, y);
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
entity.set_xy(x, y === null ? null : y - 1);
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
entity.set_xy(x, y === null ? null : y + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -366,7 +413,9 @@ beestat.component.floor_plan.prototype.update_toolbar = function() {
|
||||
.set_text_color(beestat.style.color.gray.light)
|
||||
.set_background_color(beestat.style.color.bluegray.base)
|
||||
.set_background_hover_color(beestat.style.color.bluegray.light)
|
||||
.addEventListener('click', this.add_room_.bind(this))
|
||||
.addEventListener('click', function() {
|
||||
self.add_room_();
|
||||
})
|
||||
);
|
||||
|
||||
// Remove room
|
||||
@ -492,18 +541,32 @@ beestat.component.floor_plan.prototype.update_toolbar = function() {
|
||||
this.button_group_floors_ = new beestat.component.tile_group();
|
||||
|
||||
const floor_plan = beestat.cache.floor_plan[this.floor_plan_id_];
|
||||
floor_plan.data.groups.forEach(function(group) {
|
||||
|
||||
const sorted_groups = Object.values(floor_plan.data.groups)
|
||||
.sort(function(a, b) {
|
||||
return a.elevation > b.elevation;
|
||||
});
|
||||
|
||||
let icon_number = 1;
|
||||
sorted_groups.forEach(function(group) {
|
||||
const button = new beestat.component.tile()
|
||||
.set_title(group.name)
|
||||
.set_text_hover_color(beestat.style.color.lightblue.light)
|
||||
.set_text_color(beestat.style.color.lightblue.base);
|
||||
|
||||
let icon;
|
||||
if (group.elevation < 0) {
|
||||
icon = 'alpha_b';
|
||||
} else {
|
||||
icon = 'numeric_' + icon_number++;
|
||||
}
|
||||
|
||||
if (group === self.state_.active_group) {
|
||||
button
|
||||
.set_icon(group.icon + '_box');
|
||||
.set_icon(icon + '_box');
|
||||
} else {
|
||||
button
|
||||
.set_icon(group.icon)
|
||||
.set_icon(icon)
|
||||
.addEventListener('click', function() {
|
||||
if (self.state_.active_room_entity !== undefined) {
|
||||
self.state_.active_room_entity.set_active(false);
|
||||
@ -557,32 +620,57 @@ beestat.component.floor_plan.prototype.toggle_snapping_ = function() {
|
||||
|
||||
/**
|
||||
* Add a new room.
|
||||
*
|
||||
* @param {object} room Optional room to copy from.
|
||||
*/
|
||||
beestat.component.floor_plan.prototype.add_room_ = function() {
|
||||
const new_room_size = 120;
|
||||
beestat.component.floor_plan.prototype.add_room_ = function(room) {
|
||||
const svg_view_box = this.view_box_;
|
||||
const new_room = {
|
||||
'x': svg_view_box.x + (svg_view_box.width / 2) - (new_room_size / 2),
|
||||
'y': svg_view_box.y + (svg_view_box.height / 2) - (new_room_size / 2),
|
||||
'points': [
|
||||
{
|
||||
'x': 0,
|
||||
'y': 0
|
||||
},
|
||||
{
|
||||
'x': new_room_size,
|
||||
'y': 0
|
||||
},
|
||||
{
|
||||
'x': new_room_size,
|
||||
'y': new_room_size
|
||||
},
|
||||
{
|
||||
'x': 0,
|
||||
'y': new_room_size
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
let new_room;
|
||||
if (room === undefined) {
|
||||
const new_room_size = 120;
|
||||
new_room = {
|
||||
'x': svg_view_box.x + (svg_view_box.width / 2) - (new_room_size / 2),
|
||||
'y': svg_view_box.y + (svg_view_box.height / 2) - (new_room_size / 2),
|
||||
'points': [
|
||||
{
|
||||
'x': 0,
|
||||
'y': 0
|
||||
},
|
||||
{
|
||||
'x': new_room_size,
|
||||
'y': 0
|
||||
},
|
||||
{
|
||||
'x': new_room_size,
|
||||
'y': new_room_size
|
||||
},
|
||||
{
|
||||
'x': 0,
|
||||
'y': new_room_size
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
let min_x = Infinity;
|
||||
let max_x = -Infinity;
|
||||
let min_y = Infinity;
|
||||
let max_y = -Infinity;
|
||||
|
||||
room.points.forEach(function(point) {
|
||||
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);
|
||||
});
|
||||
|
||||
new_room = {
|
||||
'x': svg_view_box.x + (svg_view_box.width / 2) - ((max_x - min_x) / 2),
|
||||
'y': svg_view_box.y + (svg_view_box.height / 2) - ((max_y - min_y) / 2),
|
||||
'points': beestat.clone(room.points)
|
||||
};
|
||||
}
|
||||
|
||||
this.state_.active_group.rooms.push(new_room);
|
||||
this.state_.active_room = new_room;
|
||||
|
||||
|
@ -146,6 +146,8 @@ beestat.component.floor_plan_entity.point.prototype.set_xy = function(x, y) {
|
||||
|
||||
this.update_rect_();
|
||||
|
||||
this.dispatchEvent('update');
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -243,8 +245,6 @@ beestat.component.floor_plan_entity.point.prototype.after_mousemove_handler_ = f
|
||||
desired_x,
|
||||
desired_y
|
||||
);
|
||||
|
||||
this.dispatchEvent('update');
|
||||
};
|
||||
|
||||
/**
|
||||
@ -358,3 +358,21 @@ beestat.component.floor_plan_entity.point.prototype.set_active = function(active
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get X
|
||||
*
|
||||
* @return {number} x
|
||||
*/
|
||||
beestat.component.floor_plan_entity.point.prototype.get_x = function() {
|
||||
return this.point_.x;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get Y
|
||||
*
|
||||
* @return {number} y
|
||||
*/
|
||||
beestat.component.floor_plan_entity.point.prototype.get_y = function() {
|
||||
return this.point_.y;
|
||||
};
|
||||
|
@ -114,7 +114,7 @@ beestat.component.floor_plan_entity.prototype.decorate_points_ = function(parent
|
||||
point_entity.addEventListener('update', function() {
|
||||
self.update_polygon_();
|
||||
self.update_walls_();
|
||||
// self.dispatchEvent('update');
|
||||
self.dispatchEvent('update');
|
||||
});
|
||||
|
||||
// When a point is done moving normalize the points
|
||||
@ -178,6 +178,7 @@ beestat.component.floor_plan_entity.prototype.decorate_walls_ = function(parent)
|
||||
self.update_polygon_();
|
||||
self.update_points_();
|
||||
self.update_walls_();
|
||||
self.dispatchEvent('update');
|
||||
});
|
||||
|
||||
// Clear any active points on drag start.
|
||||
@ -381,6 +382,8 @@ beestat.component.floor_plan_entity.room.prototype.set_xy = function(x, y) {
|
||||
this.room_.x = Math.round(clamped_x);
|
||||
this.room_.y = Math.round(clamped_y);
|
||||
|
||||
this.dispatchEvent('update');
|
||||
|
||||
return beestat.component.floor_plan_entity.prototype.set_xy.apply(
|
||||
this,
|
||||
[
|
||||
|
@ -326,6 +326,8 @@ beestat.component.floor_plan_entity.wall.prototype.set_xy = function(x, y) {
|
||||
this.point_2_.y = Math.round(clamped_y - this.room_.get_y());
|
||||
}
|
||||
|
||||
this.dispatchEvent('update');
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -396,8 +398,6 @@ beestat.component.floor_plan_entity.wall.prototype.after_mousemove_handler_ = fu
|
||||
desired_y
|
||||
);
|
||||
}
|
||||
|
||||
this.dispatchEvent('update');
|
||||
};
|
||||
|
||||
/**
|
||||
@ -577,3 +577,21 @@ beestat.component.floor_plan_entity.wall.prototype.set_active = function(active)
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get X
|
||||
*
|
||||
* @return {number} x
|
||||
*/
|
||||
beestat.component.floor_plan_entity.wall.prototype.get_x = function() {
|
||||
return this.is_vertical_() === true ? this.point_1_.x : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get Y
|
||||
*
|
||||
* @return {number} y
|
||||
*/
|
||||
beestat.component.floor_plan_entity.wall.prototype.get_y = function() {
|
||||
return this.is_horizontal_() === true ? this.point_1_.y : null;
|
||||
};
|
||||
|
@ -21,7 +21,7 @@ beestat.component.modal.create_floor_plan.prototype.decorate_contents_ = functio
|
||||
const self = this;
|
||||
const thermostat = beestat.cache.thermostat[this.thermostat_id_];
|
||||
|
||||
parent.appendChild($.createElement('p').innerHTML('Describe your home to help create this floor plan. You can change these values later.'));
|
||||
parent.appendChild($.createElement('p').innerHTML('Describe your home to help create this floor plan.'));
|
||||
|
||||
// Name
|
||||
(new beestat.component.title('Give your floor plan a name')).render(parent);
|
||||
@ -46,7 +46,12 @@ beestat.component.modal.create_floor_plan.prototype.decorate_contents_ = functio
|
||||
}
|
||||
|
||||
// Floor count
|
||||
(new beestat.component.title('How many floors does your home have?')).render(parent);
|
||||
const floor_container = document.createElement('div');
|
||||
floor_container.style.marginBottom = `${beestat.style.size.gutter}px`;
|
||||
parent.appendChild(floor_container);
|
||||
|
||||
(new beestat.component.title('How many floors does your home have?'))
|
||||
.render($(floor_container));
|
||||
|
||||
const floor_count_input = new beestat.component.input.text()
|
||||
.set_icon('layers')
|
||||
@ -57,7 +62,7 @@ beestat.component.modal.create_floor_plan.prototype.decorate_contents_ = functio
|
||||
'type': 'integer',
|
||||
'required': true
|
||||
})
|
||||
.render(parent);
|
||||
.render($(floor_container));
|
||||
|
||||
floor_count_input.addEventListener('change', function() {
|
||||
self.state_.floor_count = floor_count_input.get_value();
|
||||
@ -76,7 +81,7 @@ beestat.component.modal.create_floor_plan.prototype.decorate_contents_ = functio
|
||||
// Basement
|
||||
const basement_checkbox = new beestat.component.input.checkbox()
|
||||
.set_label('One of these floors is a basement')
|
||||
.render(parent);
|
||||
.render($(floor_container));
|
||||
|
||||
basement_checkbox.addEventListener('change', function() {
|
||||
self.state_.basement = basement_checkbox.get_checked();
|
||||
@ -94,7 +99,6 @@ beestat.component.modal.create_floor_plan.prototype.decorate_contents_ = functio
|
||||
.set_maxlength(2)
|
||||
.set_requirements({
|
||||
'min_value': 1,
|
||||
'max_value': 24,
|
||||
'type': 'integer',
|
||||
'required': true
|
||||
})
|
||||
@ -108,7 +112,7 @@ beestat.component.modal.create_floor_plan.prototype.decorate_contents_ = functio
|
||||
if (self.state_.height !== undefined) {
|
||||
height_input.set_value(self.state_.height);
|
||||
} else if (self.state_.error.height !== true) {
|
||||
height_input.set_value(9);
|
||||
height_input.set_value(8);
|
||||
}
|
||||
|
||||
// Address
|
||||
@ -116,7 +120,7 @@ beestat.component.modal.create_floor_plan.prototype.decorate_contents_ = functio
|
||||
parent.appendChild($.createElement('p').innerHTML('Addresses are pulled directly from your ecobee data.'));
|
||||
|
||||
const radio_group = new beestat.component.radio_group();
|
||||
const addresses = $.values(beestat.cache.address);
|
||||
const addresses = Object.values(beestat.cache.address);
|
||||
addresses.forEach(function(address) {
|
||||
if (
|
||||
address.normalized !== null &&
|
||||
@ -234,7 +238,6 @@ beestat.component.modal.create_floor_plan.prototype.get_buttons_ = function() {
|
||||
];
|
||||
for (let i = 0; i < self.state_.floor_count; i++) {
|
||||
attributes.data.groups.push({
|
||||
'icon': floor === 0 ? 'alpha_b' : ('numeric_' + floor),
|
||||
'name': floor === 0 ? 'Basement' : (ordinals[floor - 1] + ' Floor'),
|
||||
'elevation': elevation,
|
||||
'height': self.state_.height * 12,
|
||||
|
@ -16,21 +16,14 @@ beestat.extend(beestat.component.modal.delete_floor_plan, beestat.component.moda
|
||||
* @param {rocket.Elements} parent
|
||||
*/
|
||||
beestat.component.modal.delete_floor_plan.prototype.decorate_contents_ = function(parent) {
|
||||
parent.appendChild(
|
||||
$.createElement('p').innerHTML(
|
||||
'Are you sure you want to delete this floor plan?'
|
||||
)
|
||||
);
|
||||
const p = document.createElement('p');
|
||||
p.innerText = 'Are you sure you want to delete this floor plan?';
|
||||
parent.appendChild(p);
|
||||
|
||||
const floor_plan = beestat.cache.floor_plan[this.floor_plan_id_];
|
||||
floor_plan.data.groups.forEach(function(group) {
|
||||
parent.appendChild(
|
||||
$.createElement('div')
|
||||
.innerHTML(
|
||||
group.name + ': ' + group.rooms.length + ' room' + (group.rooms.length === 1 ? '' : 's')
|
||||
)
|
||||
);
|
||||
});
|
||||
new beestat.component.tile.floor_plan(this.floor_plan_id_)
|
||||
.set_background_color(beestat.style.color.bluegray.base)
|
||||
.set_text_color('#fff')
|
||||
.render(parent);
|
||||
};
|
||||
|
||||
/**
|
||||
|
232
js/component/modal/update_floor_plan.js
Normal file
232
js/component/modal/update_floor_plan.js
Normal file
@ -0,0 +1,232 @@
|
||||
/**
|
||||
* Update a floor plan.
|
||||
*
|
||||
* @param {integer} floor_plan_id
|
||||
*/
|
||||
beestat.component.modal.update_floor_plan = function(floor_plan_id) {
|
||||
this.floor_plan_id_ = floor_plan_id;
|
||||
|
||||
beestat.component.modal.apply(this, arguments);
|
||||
|
||||
this.state_.error = {};
|
||||
};
|
||||
beestat.extend(beestat.component.modal.update_floor_plan, beestat.component.modal);
|
||||
|
||||
/**
|
||||
* Decorate
|
||||
*
|
||||
* @param {rocket.Elements} parent
|
||||
*/
|
||||
beestat.component.modal.update_floor_plan.prototype.decorate_contents_ = function(parent) {
|
||||
const self = this;
|
||||
|
||||
const floor_plan = beestat.cache.floor_plan[this.floor_plan_id_];
|
||||
|
||||
parent.appendChild($.createElement('p').innerHTML('Make changes to your floor plan below.'));
|
||||
|
||||
// Name
|
||||
(new beestat.component.title('Give your floor plan a name')).render(parent);
|
||||
|
||||
const name_input = new beestat.component.input.text()
|
||||
.set_icon('label')
|
||||
.set_maxlength(255)
|
||||
.set_requirements({
|
||||
'required': true
|
||||
})
|
||||
.render(parent);
|
||||
|
||||
name_input.addEventListener('change', function() {
|
||||
self.state_.name = name_input.get_value();
|
||||
self.state_.error.name = !name_input.meets_requirements();
|
||||
});
|
||||
|
||||
if (self.state_.name !== undefined) {
|
||||
name_input.set_value(self.state_.name);
|
||||
} else if (self.state_.error.name !== true) {
|
||||
name_input.set_value(floor_plan.name);
|
||||
}
|
||||
|
||||
// Floors
|
||||
(new beestat.component.title('Floors')).render(parent);
|
||||
parent.appendChild($.createElement('p').innerHTML('To add or remove floors, create a new floor plan. Change floor settings like name, elevation, and ceiling height on the editor.'));
|
||||
|
||||
const grid = document.createElement('div');
|
||||
|
||||
Object.assign(grid.style, {
|
||||
'display': 'grid',
|
||||
'grid-template-columns': 'repeat(auto-fit, minmax(150px, 1fr))',
|
||||
'column-gap': `${beestat.style.size.gutter}px`,
|
||||
'row-gap': `${beestat.style.size.gutter}px`,
|
||||
'margin-bottom': `${beestat.style.size.gutter}px`
|
||||
});
|
||||
|
||||
parent.appendChild(grid);
|
||||
|
||||
const sorted_groups = Object.values(floor_plan.data.groups)
|
||||
.sort(function(a, b) {
|
||||
return a.elevation > b.elevation;
|
||||
});
|
||||
|
||||
sorted_groups.forEach(function(group) {
|
||||
new beestat.component.tile.floor_plan_group(group)
|
||||
.set_background_color(beestat.style.color.bluegray.base)
|
||||
.set_text_color('#fff')
|
||||
.set_display('block')
|
||||
.render($(grid));
|
||||
});
|
||||
|
||||
// Address
|
||||
(new beestat.component.title('What is the address for this home?')).render(parent);
|
||||
parent.appendChild($.createElement('p').innerHTML('Addresses are pulled directly from your ecobee data.'));
|
||||
|
||||
const radio_group = new beestat.component.radio_group();
|
||||
const addresses = Object.values(beestat.cache.address);
|
||||
addresses.forEach(function(address) {
|
||||
if (
|
||||
address.normalized !== null &&
|
||||
address.normalized.metadata !== undefined &&
|
||||
address.normalized.metadata.latitude !== undefined &&
|
||||
address.normalized.metadata.latitude !== null &&
|
||||
address.normalized.metadata.longitude !== undefined &&
|
||||
address.normalized.metadata.longitude !== null
|
||||
) {
|
||||
const address_parts = [
|
||||
address.normalized.components.primary_number,
|
||||
address.normalized.components.street_predirection,
|
||||
address.normalized.components.street_name,
|
||||
address.normalized.components.street_suffix,
|
||||
address.normalized.components.city_name + ',',
|
||||
address.normalized.components.state_abbreviation,
|
||||
address.normalized.components.zipcode
|
||||
];
|
||||
|
||||
let radio = new beestat.component.input.radio()
|
||||
.set_label(address_parts.join(' '))
|
||||
.set_value(address.address_id);
|
||||
|
||||
if (address.address_id === floor_plan.address_id) {
|
||||
radio.set_checked(true);
|
||||
self.state_.address_id = Number(address.address_id);
|
||||
}
|
||||
|
||||
radio_group.add_radio(radio);
|
||||
}
|
||||
});
|
||||
|
||||
radio_group.add_radio(
|
||||
new beestat.component.input.radio()
|
||||
.set_label('Not Listed')
|
||||
.set_checked(floor_plan.address_id === null)
|
||||
);
|
||||
|
||||
radio_group.addEventListener('change', function() {
|
||||
if (radio_group.get_value() === undefined) {
|
||||
delete self.state_.address_id;
|
||||
} else {
|
||||
self.state_.address_id = Number(radio_group.get_value());
|
||||
}
|
||||
});
|
||||
|
||||
radio_group.render(parent);
|
||||
|
||||
this.decorate_error_(parent);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get title.
|
||||
*
|
||||
* @return {string} The title.
|
||||
*/
|
||||
beestat.component.modal.update_floor_plan.prototype.get_title_ = function() {
|
||||
return 'Edit Floor Plan';
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the buttons that go on the bottom of this modal.
|
||||
*
|
||||
* @return {[beestat.component.button]} The buttons.
|
||||
*/
|
||||
beestat.component.modal.update_floor_plan.prototype.get_buttons_ = function() {
|
||||
const self = this;
|
||||
|
||||
const cancel = new beestat.component.tile()
|
||||
.set_background_color('#fff')
|
||||
.set_text_color(beestat.style.color.gray.base)
|
||||
.set_text_hover_color(beestat.style.color.red.base)
|
||||
.set_text('Cancel')
|
||||
.addEventListener('click', function() {
|
||||
self.dispose();
|
||||
});
|
||||
|
||||
const save = new beestat.component.tile()
|
||||
.set_background_color(beestat.style.color.green.base)
|
||||
.set_background_hover_color(beestat.style.color.green.light)
|
||||
.set_text_color('#fff')
|
||||
.set_text('Update Floor Plan')
|
||||
.addEventListener('click', function() {
|
||||
// Fail if there are errors.
|
||||
if (
|
||||
self.state_.error.name === true
|
||||
) {
|
||||
self.rerender();
|
||||
return;
|
||||
}
|
||||
|
||||
const attributes = {
|
||||
'floor_plan_id': self.floor_plan_id_,
|
||||
'name': self.state_.name,
|
||||
'address_id': self.state_.address_id === undefined ? null : self.state_.address_id
|
||||
};
|
||||
|
||||
self.dispose();
|
||||
new beestat.api()
|
||||
.add_call(
|
||||
'floor_plan',
|
||||
'update',
|
||||
{
|
||||
'attributes': attributes
|
||||
},
|
||||
'update_floor_plan'
|
||||
)
|
||||
.add_call(
|
||||
'floor_plan',
|
||||
'read_id',
|
||||
{},
|
||||
'floor_plan'
|
||||
)
|
||||
.set_callback(function(response) {
|
||||
beestat.cache.set('floor_plan', response.floor_plan);
|
||||
})
|
||||
.send();
|
||||
});
|
||||
|
||||
return [
|
||||
cancel,
|
||||
save
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Decorate the error area.
|
||||
*
|
||||
* @param {rocket.Elements} parent
|
||||
*/
|
||||
beestat.component.modal.update_floor_plan.prototype.decorate_error_ = function(parent) {
|
||||
let has_error = false;
|
||||
|
||||
var div = $.createElement('div').style({
|
||||
'background': beestat.style.color.red.base,
|
||||
'color': '#fff',
|
||||
'border-radius': beestat.style.size.border_radius,
|
||||
'padding': beestat.style.size.gutter
|
||||
});
|
||||
|
||||
if (this.state_.error.name === true) {
|
||||
div.appendChild($.createElement('div').innerText('Name is required.'));
|
||||
has_error = true;
|
||||
}
|
||||
|
||||
if (has_error === true) {
|
||||
parent.appendChild(div);
|
||||
}
|
||||
};
|
419
js/component/tile.js
Normal file
419
js/component/tile.js
Normal file
@ -0,0 +1,419 @@
|
||||
/**
|
||||
* A block with an optional icon and up to two lines of text.
|
||||
*/
|
||||
beestat.component.tile = function() {
|
||||
beestat.component.apply(this, arguments);
|
||||
};
|
||||
beestat.extend(beestat.component.tile, beestat.component);
|
||||
|
||||
/**
|
||||
* Decorate
|
||||
*
|
||||
* @param {rocket.Elements} parent
|
||||
*/
|
||||
beestat.component.tile.prototype.decorate_ = function(parent) {
|
||||
const self = this;
|
||||
|
||||
const background_color = this.background_color_ || 'none';
|
||||
const text_color = this.text_color_ || '#fff';
|
||||
const tabbable = this.tabbable_ || false;
|
||||
const display = this.display_ === 'block' ? 'flex' : 'inline-flex';
|
||||
let border_radius;
|
||||
if (this.type_ === 'pill') {
|
||||
border_radius = (this.get_size_() === 'large' ? 48 : 32);
|
||||
} else {
|
||||
border_radius = beestat.style.size.border_radius;
|
||||
}
|
||||
|
||||
this.container_ = document.createElement('div');
|
||||
|
||||
Object.assign(this.container_.style, {
|
||||
'background': background_color,
|
||||
'border-radius': `${border_radius}px`,
|
||||
'height': `${(this.get_size_() === 'large' ? 48 : 32)}px`,
|
||||
'display': display,
|
||||
'align-items': 'center',
|
||||
'color': text_color,
|
||||
'user-select': 'none',
|
||||
'transition': 'color 200ms ease, background 200ms ease',
|
||||
'outline-offset': '1px',
|
||||
'text-align': 'left'
|
||||
});
|
||||
|
||||
parent.appendChild(this.container_);
|
||||
|
||||
// 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 : 32)}px`,
|
||||
'justify-content': 'center'
|
||||
});
|
||||
} else {
|
||||
Object.assign(this.container_.style, {
|
||||
'padding-left': `${(beestat.style.size.gutter / 2)}px`,
|
||||
'padding-right': `${(beestat.style.size.gutter / 2)}px`,
|
||||
});
|
||||
}
|
||||
|
||||
// Tabbable
|
||||
if (tabbable === true) {
|
||||
this.container_.setAttribute('tabIndex', '0');
|
||||
}
|
||||
|
||||
// Title
|
||||
if (this.title_ !== undefined) {
|
||||
this.container_.setAttribute('title', this.title_);
|
||||
}
|
||||
|
||||
// Hover
|
||||
if (
|
||||
this.text_hover_color_ !== undefined ||
|
||||
this.background_hover_color_ !== undefined
|
||||
) {
|
||||
this.container_.style.cursor = 'pointer';
|
||||
|
||||
const mouseenter_style = {};
|
||||
if (this.text_hover_color_ !== undefined) {
|
||||
mouseenter_style.color = this.text_hover_color_;
|
||||
}
|
||||
if (this.background_hover_color_ !== undefined) {
|
||||
mouseenter_style.background = this.background_hover_color_;
|
||||
}
|
||||
|
||||
const mouseleave_style = {};
|
||||
mouseleave_style.color =
|
||||
(this.text_color_ !== undefined) ? this.text_color_ : '';
|
||||
mouseleave_style.background =
|
||||
(this.background_color_ !== undefined) ? this.background_color_ : '';
|
||||
|
||||
this.container_.addEventListener('mouseenter', function() {
|
||||
Object.assign(self.container_.style, mouseenter_style);
|
||||
});
|
||||
this.container_.addEventListener('mouseleave', function() {
|
||||
Object.assign(self.container_.style, mouseleave_style);
|
||||
});
|
||||
}
|
||||
|
||||
// Focus
|
||||
if (tabbable === true) {
|
||||
this.container_.addEventListener('focus', function() {
|
||||
self.container_.style.outline = '2px solid #fff';
|
||||
});
|
||||
this.container_.addEventListener('blur', function() {
|
||||
self.container_.style.outline = 'none';
|
||||
});
|
||||
this.container_.addEventListener('keydown', function(e) {
|
||||
if (
|
||||
e.key === 'Enter' ||
|
||||
e.key === ' '
|
||||
) {
|
||||
self.dispatchEvent(new window.Event('click'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Left and right container
|
||||
const left_container = document.createElement('div');
|
||||
this.decorate_left_(left_container);
|
||||
this.container_.appendChild(left_container);
|
||||
|
||||
const right_container = document.createElement('div');
|
||||
this.decorate_right_(right_container);
|
||||
this.container_.appendChild(right_container);
|
||||
|
||||
// Events
|
||||
this.container_.addEventListener('click', function() {
|
||||
self.dispatchEvent('click');
|
||||
});
|
||||
|
||||
this.container_.addEventListener('mousedown', function() {
|
||||
self.dispatchEvent('mousedown');
|
||||
});
|
||||
};
|
||||
|
||||
beestat.component.tile.prototype.decorate_left_ = function(parent) {
|
||||
if (this.get_icon_() !== undefined) {
|
||||
const icon_container = document.createElement('div');
|
||||
if (this.get_text_() !== undefined) {
|
||||
icon_container.style.marginRight = (beestat.style.size.gutter / 2) + 'px';
|
||||
}
|
||||
parent.appendChild(icon_container);
|
||||
|
||||
new beestat.component.icon(this.get_icon_())
|
||||
.set_bubble_text(this.bubble_text_)
|
||||
.set_bubble_color(this.bubble_color_)
|
||||
.set_size(this.get_size_() === 'large' ? 32 : 24)
|
||||
.render($(icon_container));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Decorate the right side of the tile.
|
||||
*
|
||||
* @param {HTMLElement} parent
|
||||
*/
|
||||
beestat.component.tile.prototype.decorate_right_ = function(parent) {
|
||||
if (Array.isArray(this.get_text_()) === true) {
|
||||
const line_1_container = document.createElement('div');
|
||||
line_1_container.innerText = this.get_text_()[0];
|
||||
line_1_container.style.fontWeight = beestat.style.font_weight.bold;
|
||||
parent.appendChild(line_1_container);
|
||||
|
||||
const line_2_container = document.createElement('div');
|
||||
line_2_container.innerText = this.get_text_()[1];
|
||||
line_2_container.style.fontWeight = beestat.style.font_weight.light;
|
||||
parent.appendChild(line_2_container);
|
||||
} else if (this.get_text_() !== undefined) {
|
||||
const text_container = document.createElement('div');
|
||||
text_container.innerText = this.get_text_();
|
||||
text_container.style.fontWeight = beestat.style.font_weight.normal;
|
||||
parent.appendChild(text_container);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the icon.
|
||||
*
|
||||
* @param {string} icon
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.set_icon = function(icon) {
|
||||
this.icon_ = icon;
|
||||
|
||||
if (this.rendered_ === true) {
|
||||
this.rerender();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the size. Default is small.
|
||||
*
|
||||
* @param {string} size large|small
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.set_size = function(size) {
|
||||
this.size_ = size;
|
||||
|
||||
if (this.rendered_ === true) {
|
||||
this.rerender();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the size of this tile.
|
||||
*
|
||||
* @return {string} The size of this tile.
|
||||
*/
|
||||
beestat.component.tile.prototype.get_size_ = function() {
|
||||
return this.size_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the icon for this tile.
|
||||
*
|
||||
* @return {string} The icon.
|
||||
*/
|
||||
beestat.component.tile.prototype.get_icon_ = function() {
|
||||
return this.icon_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the text of the button.
|
||||
*
|
||||
* @param {string|array} text A single string or array of strings. If an array is passed multiple lines of text will be shown.
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.set_text = function(text) {
|
||||
this.text_ = text;
|
||||
|
||||
if (this.rendered_ === true) {
|
||||
this.rerender();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the text for this tile.
|
||||
*
|
||||
* @return {string} The text for this tile.
|
||||
*/
|
||||
beestat.component.tile.prototype.get_text_ = function() {
|
||||
return this.text_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the background color.
|
||||
*
|
||||
* @param {string} background_color
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.set_background_color = function(background_color) {
|
||||
this.background_color_ = background_color;
|
||||
if (this.rendered_ === true) {
|
||||
this.rerender();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the text color.
|
||||
*
|
||||
* @param {string} text_color
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.set_text_color = function(text_color) {
|
||||
this.text_color_ = text_color;
|
||||
if (this.rendered_ === true) {
|
||||
this.rerender();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the background hover color.
|
||||
*
|
||||
* @param {string} background_hover_color
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.set_background_hover_color = function(background_hover_color) {
|
||||
this.background_hover_color_ = background_hover_color;
|
||||
if (this.rendered_ === true) {
|
||||
this.rerender();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the text hover color.
|
||||
*
|
||||
* @param {string} text_hover_color
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.set_text_hover_color = function(text_hover_color) {
|
||||
this.text_hover_color_ = text_hover_color;
|
||||
if (this.rendered_ === true) {
|
||||
this.rerender();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the title for the tile.
|
||||
*
|
||||
* @param {string} title
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.set_title = function(title) {
|
||||
this.title_ = title;
|
||||
if (this.rendered_ === true) {
|
||||
this.rerender();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the container for this tile.
|
||||
*
|
||||
* @return {array} The container for this tile.
|
||||
*/
|
||||
beestat.component.tile.prototype.get_container = function() {
|
||||
return this.container_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set whether or not this is tabbable. Default false.
|
||||
*
|
||||
* @param {boolean} tabbable
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.set_tabbable = function(tabbable) {
|
||||
this.tabbable_ = tabbable;
|
||||
if (this.rendered_ === true) {
|
||||
this.rerender();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set display mode.
|
||||
*
|
||||
* @param {string} display inline|block; default inline.
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.set_display = function(display) {
|
||||
this.display_ = display;
|
||||
if (this.rendered_ === true) {
|
||||
this.rerender();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the type.
|
||||
*
|
||||
* @param {string} type Valid value is "pill" for now.
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.set_type = function(type) {
|
||||
this.type_ = type;
|
||||
if (this.rendered_ === true) {
|
||||
this.rerender();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Do the normal event listener stuff. Only exists for chaining purposes.
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.addEventListener = function() {
|
||||
rocket.EventTarget.prototype.addEventListener.apply(this, arguments);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the text of the bubble.
|
||||
*
|
||||
* @param {string} bubble_text
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.set_bubble_text = function(bubble_text) {
|
||||
this.bubble_text_ = bubble_text;
|
||||
if (this.rendered_ === true) {
|
||||
this.rerender();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the color of the bubble.
|
||||
*
|
||||
* @param {string} bubble_color
|
||||
*
|
||||
* @return {beestat.component.tile} This.
|
||||
*/
|
||||
beestat.component.tile.prototype.set_bubble_color = function(bubble_color) {
|
||||
this.bubble_color_ = bubble_color;
|
||||
if (this.rendered_ === true) {
|
||||
this.rerender();
|
||||
}
|
||||
return this;
|
||||
};
|
48
js/component/tile/floor_plan.js
Normal file
48
js/component/tile/floor_plan.js
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* A tile representing a floor plan.
|
||||
*
|
||||
* @param {integer} floor_plan_id
|
||||
*/
|
||||
beestat.component.tile.floor_plan = function(floor_plan_id) {
|
||||
this.floor_plan_id_ = floor_plan_id;
|
||||
|
||||
beestat.component.apply(this, arguments);
|
||||
};
|
||||
beestat.extend(beestat.component.tile.floor_plan, beestat.component.tile);
|
||||
|
||||
/**
|
||||
* Get the icon for this tile.
|
||||
*
|
||||
* @return {string} The icon.
|
||||
*/
|
||||
beestat.component.tile.floor_plan.prototype.get_icon_ = function() {
|
||||
return 'floor_plan';
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the text for this tile.
|
||||
*
|
||||
* @return {string} The first line of text.
|
||||
*/
|
||||
beestat.component.tile.floor_plan.prototype.get_text_ = function() {
|
||||
const floor_plan = beestat.cache.floor_plan[this.floor_plan_id_];
|
||||
|
||||
const line_2_parts = [];
|
||||
let floor_count = floor_plan.data.groups.length;
|
||||
line_2_parts.push(floor_count + (floor_count === 1 ? ' Floor' : ' Floors'));
|
||||
line_2_parts.push(beestat.floor_plan.get_area(this.floor_plan_id_).toLocaleString() + ' sqft');
|
||||
|
||||
return [
|
||||
floor_plan.name,
|
||||
line_2_parts.join(' • ')
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the size of this tile.
|
||||
*
|
||||
* @return {string} The size of this tile.
|
||||
*/
|
||||
beestat.component.tile.floor_plan.prototype.get_size_ = function() {
|
||||
return 'large';
|
||||
};
|
46
js/component/tile/floor_plan_group.js
Normal file
46
js/component/tile/floor_plan_group.js
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* A tile representing a floor plan group.
|
||||
*
|
||||
* @param {object} floor_plan_group
|
||||
*/
|
||||
beestat.component.tile.floor_plan_group = function(floor_plan_group) {
|
||||
this.floor_plan_group_ = floor_plan_group;
|
||||
|
||||
beestat.component.apply(this, arguments);
|
||||
};
|
||||
beestat.extend(beestat.component.tile.floor_plan_group, beestat.component.tile);
|
||||
|
||||
/**
|
||||
* Get the icon for this tile.
|
||||
*
|
||||
* @return {string} The icon.
|
||||
*/
|
||||
beestat.component.tile.floor_plan_group.prototype.get_icon_ = function() {
|
||||
return 'layers';
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the text for this tile.
|
||||
*
|
||||
* @return {string} The first line of text.
|
||||
*/
|
||||
beestat.component.tile.floor_plan_group.prototype.get_text_ = function() {
|
||||
const line_2_parts = [];
|
||||
let room_count = this.floor_plan_group_.rooms.length;
|
||||
line_2_parts.push(room_count + (room_count === 1 ? ' Room' : ' Rooms'));
|
||||
line_2_parts.push(beestat.floor_plan.get_area_group(this.floor_plan_group_).toLocaleString() + ' sqft');
|
||||
|
||||
return [
|
||||
this.floor_plan_group_.name,
|
||||
line_2_parts.join(' • ')
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the size of this tile.
|
||||
*
|
||||
* @return {string} The size of this tile.
|
||||
*/
|
||||
beestat.component.tile.floor_plan_group.prototype.get_size_ = function() {
|
||||
return 'large';
|
||||
};
|
49
js/component/tile/thermostat.js
Normal file
49
js/component/tile/thermostat.js
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* A tile representing a thermostat.
|
||||
*
|
||||
* @param {integer} thermostat_id
|
||||
*/
|
||||
beestat.component.tile.thermostat = function(thermostat_id) {
|
||||
this.thermostat_id_ = thermostat_id;
|
||||
|
||||
beestat.component.apply(this, arguments);
|
||||
};
|
||||
beestat.extend(beestat.component.tile.thermostat, beestat.component.tile);
|
||||
|
||||
/**
|
||||
* Get the icon for this tile.
|
||||
*
|
||||
* @return {string} The icon.
|
||||
*/
|
||||
beestat.component.tile.thermostat.prototype.get_icon_ = function() {
|
||||
return 'thermostat';
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the text for this tile.
|
||||
*
|
||||
* @return {string} The first line of text.
|
||||
*/
|
||||
beestat.component.tile.thermostat.prototype.get_text_ = function() {
|
||||
const thermostat = beestat.cache.thermostat[this.thermostat_id_];
|
||||
|
||||
const temperature = beestat.temperature({
|
||||
'temperature': thermostat.temperature,
|
||||
'round': 0,
|
||||
'units': true
|
||||
});
|
||||
|
||||
return [
|
||||
thermostat.name,
|
||||
temperature
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the size of this tile.
|
||||
*
|
||||
* @return {string} The size of this tile.
|
||||
*/
|
||||
beestat.component.tile.thermostat.prototype.get_size_ = function() {
|
||||
return 'large';
|
||||
};
|
@ -19,7 +19,6 @@ beestat.component.title.prototype.decorate_ = function(parent) {
|
||||
.style({
|
||||
'font-size': beestat.style.font_size.normal,
|
||||
'font-weight': beestat.style.font_weight.bold,
|
||||
'margin-top': (beestat.style.size.gutter),
|
||||
'margin-bottom': (beestat.style.size.gutter / 2)
|
||||
})
|
||||
.innerText(this.title_);
|
||||
|
@ -116,6 +116,7 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
|
||||
echo '<script src="/js/component/modal/newsletter.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/modal/air_quality_detail_custom.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/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;
|
||||
@ -126,6 +127,7 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
|
||||
echo '<script src="/js/component/tile_group.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/tile.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/tile/floor_plan.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/tile/floor_plan_group.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/tile/thermostat.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/title.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/floor_plan_entity.js"></script>' . PHP_EOL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user