mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Tweaks (#1489)
* Tweaks * Lint * No need for copy plugin * Allow handling more complex service calls * Missed a state * Add locks * Lint * Add cover entity * Make generic entity constructor * Light to handle homeassistant.X services * Lint * Fix translations * final tweaks
This commit is contained in:
parent
3b2d4de313
commit
bdf26bbccd
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@ -48,6 +48,10 @@ class DemoCard extends PolymerElement {
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: {
|
||||
type: Object,
|
||||
observer: '_hassChanged',
|
||||
},
|
||||
config: {
|
||||
type: Object,
|
||||
observer: '_configChanged'
|
||||
@ -62,17 +66,27 @@ class DemoCard extends PolymerElement {
|
||||
card.removeChild(card.lastChild);
|
||||
}
|
||||
|
||||
const hass = new HomeAssistant();
|
||||
hass.config = demoConfig;
|
||||
hass.resources = demoResources;
|
||||
hass.language = 'en';
|
||||
hass.states = demoStates;
|
||||
|
||||
const el = createCardElement(JsYaml.safeLoad(config.config)[0]);
|
||||
el.hass = hass;
|
||||
|
||||
if (this.hass) {
|
||||
el.hass = this.hass;
|
||||
} else {
|
||||
const hass = new HomeAssistant(demoStates);
|
||||
hass.config = demoConfig;
|
||||
hass.resources = demoResources;
|
||||
hass.language = 'en';
|
||||
hass.states = demoStates;
|
||||
el.hass = hass;
|
||||
}
|
||||
|
||||
card.appendChild(el);
|
||||
}
|
||||
|
||||
_hassChanged(hass) {
|
||||
const card = this.$.card.lastChild;
|
||||
if (card) card.hass = hass;
|
||||
}
|
||||
|
||||
_trim(config) {
|
||||
return config.trim();
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ class DemoCards extends PolymerElement {
|
||||
<demo-card
|
||||
config='[[item]]'
|
||||
show-config='[[showConfig]]'
|
||||
hass='[[hass]]'
|
||||
></demo-card>
|
||||
</template>
|
||||
</div>
|
||||
@ -45,6 +46,7 @@ class DemoCards extends PolymerElement {
|
||||
static get properties() {
|
||||
return {
|
||||
configs: Object,
|
||||
hass: Object,
|
||||
showConfig: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
|
116
gallery/src/data/entity.js
Normal file
116
gallery/src/data/entity.js
Normal file
@ -0,0 +1,116 @@
|
||||
const now = () => new Date().toISOString();
|
||||
const randomTime = () =>
|
||||
new Date(new Date().getTime() - (Math.random() * 80 * 60 * 1000)).toISOString();
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
|
||||
export class Entity {
|
||||
constructor(domain, objectId, state, baseAttributes) {
|
||||
this.domain = domain;
|
||||
this.objectId = objectId;
|
||||
this.entityId = `${domain}.${objectId}`;
|
||||
this.lastChanged = randomTime();
|
||||
this.lastUpdated = randomTime();
|
||||
this.state = state;
|
||||
// These are the attributes that we always write to the state machine
|
||||
this.baseAttributes = baseAttributes;
|
||||
this.attributes = baseAttributes;
|
||||
}
|
||||
|
||||
async handleService(domain, service, data) {
|
||||
console.log(`Unmocked service for ${this.entityId}: ${domain}/${service}`, data);
|
||||
}
|
||||
|
||||
update(state, attributes = {}) {
|
||||
this.state = state;
|
||||
this.lastUpdated = now();
|
||||
this.lastChanged = state === this.state ? this.lastChanged : this.lastUpdated;
|
||||
this.attributes = Object.assign({}, this.baseAttributes, attributes);
|
||||
|
||||
console.log('update', this.entityId, this);
|
||||
|
||||
this.hass.updateStates({
|
||||
[this.entityId]: this.toState()
|
||||
});
|
||||
}
|
||||
|
||||
toState() {
|
||||
return {
|
||||
entity_id: this.entityId,
|
||||
state: this.state,
|
||||
attributes: this.attributes,
|
||||
last_changed: this.lastChanged,
|
||||
last_updated: this.lastUpdated,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class LightEntity extends Entity {
|
||||
async handleService(domain, service, data) {
|
||||
if (!['homeassistant', this.domain].includes(domain)) return;
|
||||
|
||||
if (service === 'turn_on') {
|
||||
// eslint-disable-next-line
|
||||
const { brightness, hs_color } = data;
|
||||
this.update('on', Object.assign(this.attributes, {
|
||||
brightness,
|
||||
hs_color,
|
||||
}));
|
||||
} else if (service === 'turn_off') {
|
||||
this.update('off');
|
||||
} else if (service === 'toggle') {
|
||||
if (this.state === 'on') {
|
||||
this.handleService(domain, 'turn_off', data);
|
||||
} else {
|
||||
this.handleService(domain, 'turn_on', data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class LockEntity extends Entity {
|
||||
async handleService(domain, service, data) {
|
||||
if (domain !== this.domain) return;
|
||||
|
||||
if (service === 'lock') {
|
||||
this.update('locked');
|
||||
} else if (service === 'unlock') {
|
||||
this.update('unlocked');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class CoverEntity extends Entity {
|
||||
async handleService(domain, service, data) {
|
||||
if (domain !== this.domain) return;
|
||||
|
||||
if (service === 'open_cover') {
|
||||
this.update('open');
|
||||
} else if (service === 'close_cover') {
|
||||
this.update('closing');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class GroupEntity extends Entity {
|
||||
async handleService(domain, service, data) {
|
||||
if (!['homeassistant', this.domain].includes(domain)) return;
|
||||
|
||||
await Promise.all(this.attributes.entity_id.map((ent) => {
|
||||
const entity = this.hass.mockEntities[ent];
|
||||
return entity.handleService(entity.domain, service, data);
|
||||
}));
|
||||
|
||||
this.update(service === 'turn_on' ? 'on' : 'off');
|
||||
}
|
||||
}
|
||||
|
||||
const TYPES = {
|
||||
light: LightEntity,
|
||||
lock: LockEntity,
|
||||
cover: CoverEntity,
|
||||
group: GroupEntity,
|
||||
};
|
||||
|
||||
export default (domain, objectId, state, baseAttributes = {}) =>
|
||||
new (TYPES[domain] || Entity)(domain, objectId, state, baseAttributes);
|
@ -1,6 +1,6 @@
|
||||
export default class FakeHass {
|
||||
constructor() {
|
||||
this.states = {};
|
||||
constructor(states = {}) {
|
||||
this.states = states;
|
||||
this._wsCommands = {};
|
||||
}
|
||||
|
||||
|
79
gallery/src/data/provide_hass.js
Normal file
79
gallery/src/data/provide_hass.js
Normal file
@ -0,0 +1,79 @@
|
||||
import fireEvent from '../../../src/common/dom/fire_event.js';
|
||||
|
||||
import demoConfig from './demo_config.js';
|
||||
import demoResources from './demo_resources.js';
|
||||
|
||||
const ensureArray = val => (Array.isArray(val) ? val : [val]);
|
||||
|
||||
export default (elements, { initialStates = {} } = {}) => {
|
||||
elements = ensureArray(elements);
|
||||
|
||||
const wsCommands = {};
|
||||
let hass;
|
||||
const entities = {};
|
||||
|
||||
function updateHass(obj) {
|
||||
hass = Object.assign({}, hass, obj);
|
||||
elements.forEach((el) => { el.hass = hass; });
|
||||
}
|
||||
|
||||
updateHass({
|
||||
// Home Assistant properties
|
||||
config: demoConfig,
|
||||
language: 'en',
|
||||
resources: demoResources,
|
||||
states: initialStates,
|
||||
|
||||
// Mock properties
|
||||
mockEntities: entities,
|
||||
|
||||
// Home Assistant functions
|
||||
async callService(domain, service, data) {
|
||||
fireEvent(elements[0], 'show-notification', { message: `Called service ${domain}/${service}` });
|
||||
if (data.entity_id) {
|
||||
await Promise.all(ensureArray(data.entity_id).map(ent =>
|
||||
entities[ent].handleService(domain, service, data)));
|
||||
} else {
|
||||
console.log('unmocked callService', domain, service, data);
|
||||
}
|
||||
},
|
||||
|
||||
async callWS(msg) {
|
||||
const callback = wsCommands[msg.type];
|
||||
return callback ? callback(msg) : Promise.reject({
|
||||
code: 'command_not_mocked',
|
||||
message: 'This command is not implemented in the gallery.',
|
||||
});
|
||||
},
|
||||
|
||||
async sendWS(msg) {
|
||||
const callback = wsCommands[msg.type];
|
||||
|
||||
if (callback) {
|
||||
callback(msg);
|
||||
} else {
|
||||
console.error(`Unknown command: ${msg.type}`);
|
||||
}
|
||||
console.log('sendWS', msg);
|
||||
},
|
||||
|
||||
// Mock functions
|
||||
updateHass,
|
||||
updateStates(newStates) {
|
||||
updateHass({
|
||||
states: Object.assign({}, hass.states, newStates),
|
||||
});
|
||||
},
|
||||
addEntities(newEntities) {
|
||||
const states = {};
|
||||
ensureArray(newEntities).forEach((ent) => {
|
||||
ent.hass = hass;
|
||||
entities[ent.entityId] = ent;
|
||||
states[ent.entityId] = ent.toState();
|
||||
});
|
||||
this.updateStates(states);
|
||||
}
|
||||
});
|
||||
|
||||
return hass;
|
||||
};
|
@ -1,8 +1,45 @@
|
||||
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
|
||||
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
||||
|
||||
import getEntity from '../data/entity.js';
|
||||
import provideHass from '../data/provide_hass.js';
|
||||
import '../components/demo-cards.js';
|
||||
|
||||
const ENTITIES = [
|
||||
getEntity('light', 'bed_light', 'on', {
|
||||
friendly_name: 'Bed Light'
|
||||
}),
|
||||
getEntity('group', 'kitchen', 'on', {
|
||||
entity_id: [
|
||||
'light.bed_light',
|
||||
],
|
||||
order: 8,
|
||||
friendly_name: 'Kitchen'
|
||||
}),
|
||||
getEntity('lock', 'kitchen_door', 'locked', {
|
||||
friendly_name: 'Kitchen Door'
|
||||
}),
|
||||
getEntity('cover', 'kitchen_window', 'open', {
|
||||
friendly_name: 'Kitchen Window',
|
||||
supported_features: 11
|
||||
}),
|
||||
getEntity('scene', 'romantic_lights', 'scening', {
|
||||
entity_id: [
|
||||
'light.bed_light',
|
||||
'light.ceiling_lights'
|
||||
],
|
||||
friendly_name: 'Romantic lights'
|
||||
}),
|
||||
getEntity('device_tracker', 'demo_paulus', 'home', {
|
||||
source_type: 'gps',
|
||||
latitude: 32.877105,
|
||||
longitude: 117.232185,
|
||||
gps_accuracy: 91,
|
||||
battery: 71,
|
||||
friendly_name: 'Paulus'
|
||||
}),
|
||||
];
|
||||
|
||||
const CONFIGS = [
|
||||
{
|
||||
heading: 'Basic',
|
||||
@ -48,7 +85,7 @@ const CONFIGS = [
|
||||
`
|
||||
},
|
||||
{
|
||||
heading: 'With title, cant\'t toggle',
|
||||
heading: 'With title, can\'t toggle',
|
||||
config: `
|
||||
- type: entities
|
||||
entities:
|
||||
@ -80,7 +117,11 @@ const CONFIGS = [
|
||||
class DemoEntities extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-cards configs="[[_configs]]"></demo-cards>
|
||||
<demo-cards
|
||||
id='demos'
|
||||
hass='[[hass]]'
|
||||
configs="[[_configs]]"
|
||||
></demo-cards>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -89,9 +130,16 @@ class DemoEntities extends PolymerElement {
|
||||
_configs: {
|
||||
type: Object,
|
||||
value: CONFIGS
|
||||
}
|
||||
},
|
||||
hass: Object,
|
||||
};
|
||||
}
|
||||
|
||||
ready() {
|
||||
super.ready();
|
||||
const hass = provideHass(this.$.demos);
|
||||
hass.addEntities(ENTITIES);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('demo-hui-entities-card', DemoEntities);
|
||||
|
@ -9,6 +9,8 @@ import '@polymer/paper-icon-button/paper-icon-button.js';
|
||||
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
|
||||
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
||||
|
||||
import '../../src/managers/notification-manager.js';
|
||||
|
||||
const demos = require.context('./demos', true, /^(.*\.(js$))[^.]*$/im);
|
||||
|
||||
const fixPath = path => path.substr(2, path.length - 5);
|
||||
@ -91,6 +93,7 @@ class HaGallery extends PolymerElement {
|
||||
</template>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
<notification-manager id='notifications'></notification-manager>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -111,8 +114,15 @@ class HaGallery extends PolymerElement {
|
||||
ready() {
|
||||
super.ready();
|
||||
|
||||
this.addEventListener(
|
||||
'show-notification',
|
||||
ev => this.$.notifications.showNotification(ev.detail.message)
|
||||
);
|
||||
|
||||
this.addEventListener('hass-more-info', (ev) => {
|
||||
if (ev.detail.entityId) alert(`Showing more info for ${ev.detail.entityId}`);
|
||||
if (ev.detail.entityId) {
|
||||
this.$.notifications.showNotification(`Showing more info for ${ev.detail.entityId}`);
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('hashchange', () => { this._demo = document.location.hash.substr(1); });
|
||||
|
@ -49,12 +49,11 @@ module.exports = {
|
||||
plugins: [
|
||||
new CopyWebpackPlugin([
|
||||
'public',
|
||||
{ from: '../public', to: 'static' },
|
||||
{ from: '../build-translations/output', to: 'static/translations' },
|
||||
{ from: '../node_modules/leaflet/dist/leaflet.css', to: 'static/images/leaflet/' },
|
||||
{ from: '../node_modules/@polymer/font-roboto-local/fonts', to: 'static/fonts' },
|
||||
{ from: '../node_modules/leaflet/dist/images', to: 'static/images/leaflet/' },
|
||||
{ from: './src/data/media_player_images/media_player.bedroom.jpg', to: 'api/media_player_proxy/media_player.bedroom' },
|
||||
{ from: './src/data/media_player_images/media_player.living_room.jpg', to: 'api/media_player_proxy/media_player.living_room' },
|
||||
{ from: './src/data/media_player_images/media_player.walkman.jpg', to: 'api/media_player_proxy/media_player.walkman' },
|
||||
]),
|
||||
isProd && new UglifyJsPlugin({
|
||||
extractComments: true,
|
||||
|
@ -13,7 +13,7 @@ class NotificationManager extends LocalizeMixin(PolymerElement) {
|
||||
}
|
||||
</style>
|
||||
|
||||
<paper-toast id="toast" text="[[_text]]" no-cancel-on-outside-click="[[_cancelOnOutsideClick]]"></paper-toast>
|
||||
<paper-toast id="toast" no-cancel-on-outside-click="[[_cancelOnOutsideClick]]"></paper-toast>
|
||||
<paper-toast id="connToast" duration="0" text="[[localize('ui.notification_toast.connection_lost')]]" opened="[[connectionLost]]"></paper-toast>
|
||||
`;
|
||||
}
|
||||
@ -40,11 +40,6 @@ class NotificationManager extends LocalizeMixin(PolymerElement) {
|
||||
value: false,
|
||||
},
|
||||
|
||||
_text: {
|
||||
type: String,
|
||||
readOnly: true,
|
||||
},
|
||||
|
||||
toastClass: {
|
||||
type: String,
|
||||
value: '',
|
||||
@ -90,8 +85,7 @@ class NotificationManager extends LocalizeMixin(PolymerElement) {
|
||||
}
|
||||
|
||||
showNotification(message) {
|
||||
this._set_text(message);
|
||||
this.$.toast.show();
|
||||
this.$.toast.show(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user