Add support for entity cards
This commit is contained in:
parent
1fb3f2bbf4
commit
09d0e529ed
|
@ -0,0 +1,37 @@
|
|||
<link rel='import' href='../../bower_components/polymer/polymer.html'>
|
||||
<link rel="import" href="../../bower_components/paper-material/paper-material.html">
|
||||
|
||||
<dom-module id='ha-camera-card'>
|
||||
<style include="paper-material">
|
||||
:host {
|
||||
display: block;
|
||||
position: relative;
|
||||
font-size: 0px;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.camera-feed {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.caption {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
padding: 16px;
|
||||
|
||||
text-transform: capitalize;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 16px;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<img src='[[cameraFeedSrc]]' class='camera-feed'>
|
||||
<div class='caption'>[[stateObj.entityDisplay]]</div>
|
||||
</template>
|
||||
</dom-module>
|
|
@ -0,0 +1,52 @@
|
|||
import Polymer from '../polymer';
|
||||
import hass from '../util/home-assistant-js-instance';
|
||||
|
||||
const { moreInfoActions } = hass;
|
||||
|
||||
const UPDATE_INTERVAL = 10000; // ms
|
||||
|
||||
export default new Polymer({
|
||||
is: 'ha-camera-card',
|
||||
|
||||
properties: {
|
||||
stateObj: {
|
||||
type: Object,
|
||||
observer: 'updateCameraFeedSrc',
|
||||
},
|
||||
|
||||
cameraFeedSrc: {
|
||||
type: String,
|
||||
},
|
||||
|
||||
/**
|
||||
* The z-depth of the card, from 0-5.
|
||||
*/
|
||||
elevation: {
|
||||
type: Number,
|
||||
value: 1,
|
||||
reflectToAttribute: true,
|
||||
},
|
||||
},
|
||||
|
||||
listeners: {
|
||||
tap: 'cardTapped',
|
||||
},
|
||||
|
||||
attached() {
|
||||
this.timer = setInterval(() => this.updateCameraFeedSrc(this.stateObj),
|
||||
UPDATE_INTERVAL);
|
||||
},
|
||||
|
||||
detached() {
|
||||
clearInterval(this.timer);
|
||||
},
|
||||
|
||||
cardTapped() {
|
||||
this.async(() => moreInfoActions.selectEntity(this.stateObj.entityId), 1);
|
||||
},
|
||||
|
||||
updateCameraFeedSrc(stateObj) {
|
||||
const time = (new Date()).getTime();
|
||||
this.cameraFeedSrc = `${stateObj.attributes.entity_picture}?time=${time}`;
|
||||
},
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
<link rel='import' href='../../bower_components/polymer/polymer.html'>
|
||||
|
||||
<link rel='import' href='./ha-camera-card.html'>
|
||||
<link rel='import' href='./ha-entities-card.html'>
|
||||
<link rel='import' href='./ha-introduction-card.html'>
|
|
@ -0,0 +1,53 @@
|
|||
import Polymer from '../polymer';
|
||||
|
||||
require('./ha-camera-card');
|
||||
require('./ha-entities-card');
|
||||
require('./ha-introduction-card');
|
||||
|
||||
export default new Polymer({
|
||||
is: 'ha-card-chooser',
|
||||
|
||||
properties: {
|
||||
cardData: {
|
||||
type: Object,
|
||||
observer: 'cardDataChanged',
|
||||
},
|
||||
},
|
||||
|
||||
cardDataChanged(newData, oldData) {
|
||||
const root = Polymer.dom(this);
|
||||
|
||||
if (!newData) {
|
||||
if (root.lastChild) {
|
||||
root.removeChild(root.lastChild);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const newElement = !oldData || oldData.cardType !== newData.cardType;
|
||||
let card;
|
||||
if (newElement) {
|
||||
if (root.lastChild) {
|
||||
root.removeChild(root.lastChild);
|
||||
}
|
||||
|
||||
card = document.createElement(`ha-${newData.cardType}-card`);
|
||||
} else {
|
||||
card = root.lastChild;
|
||||
}
|
||||
|
||||
Object.keys(newData).forEach(key => card[key] = newData[key]);
|
||||
|
||||
if (oldData) {
|
||||
Object.keys(oldData).forEach(key => {
|
||||
if (!(key in newData)) {
|
||||
card[key] = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (newElement) {
|
||||
root.appendChild(card);
|
||||
}
|
||||
},
|
||||
});
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
<link rel="import" href="./ha-demo-badge.html">
|
||||
<link rel="import" href="../cards/ha-badges-card.html">
|
||||
<link rel="import" href="../cards/ha-entities-card.html">
|
||||
<link rel="import" href="../cards/ha-introduction-card.html">
|
||||
<link rel="import" href="../cards/ha-card-chooser.html">
|
||||
|
||||
<dom-module id="ha-cards">
|
||||
<style>
|
||||
|
@ -53,7 +52,7 @@
|
|||
|
||||
<template>
|
||||
<div class='main'>
|
||||
<template is='dom-if' if='[[cards._badges.length]]'>
|
||||
<template is='dom-if' if='[[cards._badges]]'>
|
||||
<div class='badges'>
|
||||
<template is='dom-if' if='[[cards._demo]]'>
|
||||
<ha-demo-badge></ha-demo-badge>
|
||||
|
@ -62,29 +61,20 @@
|
|||
<ha-badges-card states='[[cards._badges]]'></ha-badges-card>
|
||||
</div>
|
||||
</template>
|
||||
<template is='dom-if' if='[[!cards._badges.length]]'>
|
||||
<template is='dom-if' if='[[!cards._badges]]'>
|
||||
<div class='no-badges'> </div>
|
||||
</template>
|
||||
|
||||
<div class='horizontal layout'>
|
||||
<template is='dom-repeat' items='[[cards._columns]]' as='column'>
|
||||
<template is='dom-if'
|
||||
if='[[computeShouldRenderColumn(index, column)]]'>
|
||||
<div class='column flex-1'>
|
||||
<template is='dom-if' if='[[computeShowIntroduction(index, showIntroduction, cards)]]'>
|
||||
<div class='zone-card'>
|
||||
<ha-introduction-card show-hide-instruction='[[computeShowHideInstruction(states, cards)]]'></ha-introduction-card>
|
||||
</div>
|
||||
</template>
|
||||
<template is='dom-repeat' items='[[column]]' as='domain'>
|
||||
<div class='zone-card'>
|
||||
<ha-entities-card
|
||||
states='[[computeStatesOfCard(cards, domain)]]'
|
||||
group-entity='[[computeGroupEntityOfCard(cards, domain)]]'
|
||||
></ha-entities-card>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<div class='column flex-1'>
|
||||
<template is='dom-repeat' items='[[column]]' as='card'>
|
||||
<div class='zone-card'>
|
||||
<ha-card-chooser card-data='[[computeCardDataOfCard(cards, card)]]'
|
||||
></ha-entities-card>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -3,10 +3,12 @@ import hass from '../util/home-assistant-js-instance';
|
|||
|
||||
require('.//ha-demo-badge');
|
||||
require('../cards/ha-badges-card');
|
||||
require('../cards/ha-entities-card');
|
||||
require('../cards/ha-introduction-card');
|
||||
require('../cards/ha-card-chooser');
|
||||
|
||||
const { util } = hass;
|
||||
|
||||
const DOMAINS_WITH_CARD = ['camera'];
|
||||
|
||||
const PRIORITY = {
|
||||
configurator: -20,
|
||||
group: -10,
|
||||
|
@ -15,7 +17,6 @@ const PRIORITY = {
|
|||
sun: 1,
|
||||
device_tracker: 2,
|
||||
alarm_control_panel: 3,
|
||||
camera: 4,
|
||||
sensor: 5,
|
||||
binary_sensor: 6,
|
||||
scene: 7,
|
||||
|
@ -77,15 +78,45 @@ export default new Polymer({
|
|||
return old;
|
||||
}
|
||||
if (showIntroduction) {
|
||||
increaseIndex();
|
||||
cards._columns[increaseIndex()].push('ha-introduction');
|
||||
cards['ha-introduction'] = {
|
||||
cardType: 'introduction',
|
||||
showHideInstruction: states.size > 0 && !__DEMO__,
|
||||
};
|
||||
}
|
||||
|
||||
function pushCard(name, entities, groupEntity = false) {
|
||||
if (entities.length === 0) {
|
||||
return;
|
||||
function addEntitiesCard(name, entities, groupEntity = false) {
|
||||
if (entities.length === 0) return;
|
||||
|
||||
const owncard = [];
|
||||
const other = [];
|
||||
|
||||
entities.forEach(entity => {
|
||||
if (DOMAINS_WITH_CARD.indexOf(entity.domain) === -1) {
|
||||
other.push(entity);
|
||||
} else {
|
||||
owncard.push(entity);
|
||||
}
|
||||
});
|
||||
|
||||
const curIndex = increaseIndex();
|
||||
|
||||
if (other.length > 0) {
|
||||
cards._columns[curIndex].push(name);
|
||||
cards[name] = {
|
||||
cardType: 'entities',
|
||||
states: other,
|
||||
groupEntity,
|
||||
};
|
||||
}
|
||||
cards._columns[increaseIndex()].push(name);
|
||||
cards[name] = { entities, groupEntity };
|
||||
|
||||
owncard.forEach(entity => {
|
||||
cards._columns[curIndex].push(entity.entityId);
|
||||
cards[entity.entityId] = {
|
||||
cardType: entity.domain,
|
||||
stateObj: entity,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
byDomain.keySeq().sortBy(domain => getPriority(domain))
|
||||
|
@ -106,34 +137,19 @@ export default new Polymer({
|
|||
.forEach(groupState => {
|
||||
const entities = util.expandGroup(groupState, states);
|
||||
entities.forEach(entity => hasGroup[entity.entityId] = true);
|
||||
pushCard(groupState.entityDisplay, entities.toArray(), groupState);
|
||||
addEntitiesCard(groupState.entityId, entities.toArray(), groupState);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
pushCard(domain, filterGrouped(byDomain.get(domain)).sortBy(entitySortBy).toArray());
|
||||
addEntitiesCard(
|
||||
domain, filterGrouped(byDomain.get(domain)).sortBy(entitySortBy).toArray());
|
||||
}
|
||||
}
|
||||
);
|
||||
return cards;
|
||||
},
|
||||
|
||||
computeShouldRenderColumn(index, items) {
|
||||
return index === 0 || items.length;
|
||||
},
|
||||
|
||||
computeShowIntroduction(index, showIntroduction, cards) {
|
||||
return index === 0 && (showIntroduction || cards._demo);
|
||||
},
|
||||
|
||||
computeShowHideInstruction(states, cards) {
|
||||
return states.size > 0 && !__DEMO__ && !cards._demo;
|
||||
},
|
||||
|
||||
computeGroupEntityOfCard(cards, card) {
|
||||
return card in cards && cards[card].groupEntity;
|
||||
},
|
||||
|
||||
computeStatesOfCard(cards, card) {
|
||||
return card in cards && cards[card].entities;
|
||||
computeCardDataOfCard(cards, card) {
|
||||
return cards[card];
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue