Merge pull request #2345 from home-assistant/20181211-1

20181211 1
This commit is contained in:
Paulus Schoutsen 2018-12-17 10:20:35 +01:00 committed by GitHub
commit 5f5bf17df0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 153 additions and 48 deletions

View File

@ -76,6 +76,55 @@ const CONFIGS = [
left: 35%
`,
},
{
heading: "Card with header",
config: `
- type: picture-elements
image: /images/floorplan.png
title: My House
elements:
- type: service-button
title: Lights Off
style:
top: 97%
left: 90%
padding: 0px
service: light.turn_off
service_data:
entity_id: group.all_lights
- type: icon
icon: mdi:cctv
entity: camera.demo_camera
style:
top: 12%
left: 6%
transform: rotate(-60deg) scaleX(-1)
--iron-icon-height: 30px
--iron-icon-width: 30px
--iron-icon-stroke-color: black
--iron-icon-fill-color: rgba(50, 50, 50, .75)
- type: image
entity: light.bed_light
tap_action:
action: toggle
image: /images/light_bulb_off.png
state_image:
'on': /images/light_bulb_on.png
state_filter:
'on': brightness(130%) saturate(1.5) drop-shadow(0px 0px 10px gold)
'off': brightness(80%) saturate(0.8)
style:
top: 35%
left: 65%
width: 7%
padding: 50px 50px 100px 50px
- type: state-icon
entity: binary_sensor.movement_backyard
style:
top: 8%
left: 35%
`,
},
];
class DemoPicElements extends PolymerElement {

View File

@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name="home-assistant-frontend",
version="20181211.0",
version="20181211.1",
description="The Home Assistant frontend",
url="https://github.com/home-assistant/home-assistant-polymer",
author="The Home Assistant Authors",

View File

@ -119,7 +119,7 @@ class HaPlantCard extends EventsMixin(PolymerElement) {
}
computeTitle(stateObj) {
return this.config.name || computeStateName(stateObj);
return (this.config && this.config.name) || computeStateName(stateObj);
}
computeAttributes(data) {

View File

@ -39,6 +39,7 @@ class HaWeatherCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
opacity: var(--dark-primary-opacity);
padding: 24px 16px 16px;
display: flex;
align-items: baseline;
}
.name {
@ -195,6 +196,7 @@ class HaWeatherCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
static get properties() {
return {
hass: Object,
config: Object,
stateObj: Object,
forecast: {
type: Array,
@ -274,7 +276,7 @@ class HaWeatherCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
}
computeName(stateObj) {
return this.config.name || computeStateName(stateObj);
return (this.config && this.config.name) || computeStateName(stateObj);
}
showWeatherIcon(condition) {

View File

@ -1,24 +1,30 @@
export default function parseAspectRatio(input) {
// Handle 16x9, 16:9, 1.78x1, 1.78:1, 1.78
// Ignore everything else
function parseOrThrow(num) {
const parsed = parseFloat(num);
if (isNaN(parsed)) {
throw new Error(`${num} is not a number`);
}
return parsed;
// Handle 16x9, 16:9, 1.78x1, 1.78:1, 1.78
// Ignore everything else
const parseOrThrow = (num) => {
const parsed = parseFloat(num);
if (isNaN(parsed)) {
throw new Error(`${num} is not a number`);
}
return parsed;
};
export default function parseAspectRatio(input: string) {
if (!input) {
return null;
}
try {
if (input) {
const arr = input.replace(":", "x").split("x");
if (arr.length === 0) {
return null;
}
return arr.length === 1
? { w: parseOrThrow(arr[0]), h: 1 }
: { w: parseOrThrow(arr[0]), h: parseOrThrow(arr[1]) };
if (input.endsWith("%")) {
return { w: 100, h: parseOrThrow(input.substr(0, input.length - 1)) };
}
const arr = input.replace(":", "x").split("x");
if (arr.length === 0) {
return null;
}
return arr.length === 1
? { w: parseOrThrow(arr[0]), h: 1 }
: { w: parseOrThrow(arr[0]), h: parseOrThrow(arr[1]) };
} catch (err) {
// Ignore the error
}

View File

@ -56,6 +56,10 @@ export default (superClass) =>
dockedSidebar: false,
moreInfoEntityId: null,
callService: async (domain, service, serviceData = {}) => {
if (__DEV__) {
// eslint-disable-next-line
console.log("Calling service", domain, service, serviceData);
}
try {
await callService(conn, domain, service, serviceData);
@ -91,6 +95,15 @@ export default (superClass) =>
}
this.fire("hass-notification", { message });
} catch (err) {
if (__DEV__) {
// eslint-disable-next-line
console.error(
"Error calling service",
domain,
service,
serviceData
);
}
const message = this.localize(
"ui.notification_toast.service_call_failed",
"service",
@ -106,21 +119,25 @@ export default (superClass) =>
fetchWithAuth(auth, `${auth.data.hassUrl}${path}`, init),
// For messages that do not get a response
sendWS: (msg) => {
// eslint-disable-next-line
if (__DEV__) console.log("Sending", msg);
if (__DEV__) {
// eslint-disable-next-line
console.log("Sending", msg);
}
conn.sendMessage(msg);
},
// For messages that expect a response
callWS: (msg) => {
/* eslint-disable no-console */
if (__DEV__) console.log("Sending", msg);
if (__DEV__) {
/* eslint-disable no-console */
console.log("Sending", msg);
}
const resp = conn.sendMessagePromise(msg);
if (__DEV__) {
resp.then(
(result) => console.log("Received", result),
(err) => console.log("Error", err)
(err) => console.error("Error", err)
);
}
return resp;

View File

@ -70,6 +70,7 @@ export class CloudExposedEntities extends LitElement {
}
protected updated(changedProperties: PropertyValues) {
super.updated(changedProperties);
if (
changedProperties.has("filter") &&
changedProperties.get("filter") !== this.filter

View File

@ -79,6 +79,7 @@ export class CloudWebhooks extends LitElement {
}
protected updated(changedProps: PropertyValues) {
super.updated(changedProps);
if (changedProps.has("cloudStatus") && this.cloudStatus) {
this._cloudHooks = this.cloudStatus.prefs.cloudhooks || {};
}

View File

@ -88,7 +88,8 @@ class HuiEntitiesCard extends hassLocalizeLitMixin(LitElement)
this._configEntities = entities;
}
protected updated(_changedProperties: PropertyValues): void {
protected updated(changedProperties: PropertyValues): void {
super.updated(changedProperties);
if (this._hass && this._config) {
applyThemesOnElement(this, this._hass.themes, this._config.theme);
}

View File

@ -116,6 +116,7 @@ class HuiEntityButtonCard extends hassLocalizeLitMixin(LitElement)
}
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (!this._config || !this.hass) {
return;
}

View File

@ -110,11 +110,8 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
}
protected updated(changedProps: PropertyValues): void {
if (
!this._config ||
!this.hass ||
!this.shadowRoot!.getElementById("gauge")
) {
super.updated(changedProps);
if (!this._config || !this.hass) {
return;
}
const stateObj = this.hass.states[this._config.entity];

View File

@ -135,6 +135,7 @@ export class HuiGlanceCard extends hassLocalizeLitMixin(LitElement)
}
protected updated(changedProperties: PropertyValues): void {
super.updated(changedProperties);
if (!this._config || !this.hass) {
return;
}

View File

@ -36,6 +36,7 @@ const lightConfig = {
lineCap: "round",
handleSize: "+12",
showTooltip: false,
animation: false,
};
interface Config extends LovelaceCardConfig {
@ -154,6 +155,7 @@ export class HuiLightCard extends hassLocalizeLitMixin(LitElement)
}
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (!this._config || !this.hass || !this._jQuery) {
return;
}

View File

@ -63,15 +63,15 @@ class HuiPictureElementsCard extends LitElement implements LovelaceCard {
return html`
${this.renderStyle()}
<ha-card .header="${this._config.title}">
<hui-image
.hass="${this._hass}"
.image="${this._config.image}"
.stateImage="${this._config.state_image}"
.cameraImage="${this._config.camera_image}"
.entity="${this._config.entity}"
.aspectRatio="${this._config.aspect_ratio}"
></hui-image>
<div id="root">
<hui-image
.hass="${this._hass}"
.image="${this._config.image}"
.stateImage="${this._config.state_image}"
.cameraImage="${this._config.camera_image}"
.entity="${this._config.entity}"
.aspectRatio="${this._config.aspect_ratio}"
></hui-image>
${
this._config.elements.map((elementConfig: LovelaceElementConfig) =>
this._createHuiElement(elementConfig)
@ -85,9 +85,9 @@ class HuiPictureElementsCard extends LitElement implements LovelaceCard {
private renderStyle(): TemplateResult {
return html`
<style>
ha-card {
overflow: hidden;
#root {
position: relative;
overflow: hidden;
}
.element {
position: absolute;

View File

@ -265,6 +265,7 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
}
protected updated(changedProps: PropertyValues) {
super.updated(changedProps);
if (!this._config || this._config.graph !== "line" || !this.hass) {
return;
}

View File

@ -29,6 +29,7 @@ const thermostatConfig = {
lineCap: "round",
handleSize: "+10",
showTooltip: false,
animation: false,
};
const modeIcons = {

View File

@ -25,6 +25,7 @@ class HuiEntitiesToggle extends LitElement {
}
public updated(changedProperties: PropertyValues) {
super.updated(changedProperties);
if (changedProperties.has("entities")) {
this._toggleEntities = this.entities!.filter(
(entityId) =>

View File

@ -78,6 +78,7 @@ class HuiTimestampDisplay extends hassLocalizeLitMixin(LitElement) {
}
protected updated(changedProperties: PropertyValues) {
super.updated(changedProperties);
if (!changedProperties.has("format") || !this._connected) {
return;
}

View File

@ -58,6 +58,7 @@ export class HuiDialogEditCard extends LitElement {
<hui-dialog-pick-card
.hass="${this.hass}"
.cardPicked="${this._cardPicked}"
.closeDialog="${this._cancel}"
></hui-dialog-pick-card>
`;
}

View File

@ -11,6 +11,7 @@ import { LovelaceCardConfig } from "../../../../data/lovelace";
export class HuiDialogPickCard extends hassLocalizeLitMixin(LitElement) {
public hass?: HomeAssistant;
public cardPicked?: (cardConf: LovelaceCardConfig) => void;
public closeDialog?: () => void;
static get properties(): PropertyDeclarations {
return {};
@ -18,7 +19,11 @@ export class HuiDialogPickCard extends hassLocalizeLitMixin(LitElement) {
protected render(): TemplateResult {
return html`
<paper-dialog with-backdrop opened>
<paper-dialog
with-backdrop
opened
@opened-changed="${this._openedChanged}"
>
<h2>${this.localize("ui.panel.lovelace.editor.edit_card.header")}</h2>
<paper-dialog-scrollable>
<hui-card-picker
@ -33,6 +38,12 @@ export class HuiDialogPickCard extends hassLocalizeLitMixin(LitElement) {
`;
}
private _openedChanged(ev) {
if (!ev.detail.value) {
this.closeDialog!();
}
}
private _skipPick() {
this.cardPicked!({ type: "" });
}

View File

@ -132,7 +132,11 @@ export class HuiEditCard extends hassLocalizeLitMixin(LitElement) {
return html`
${this.renderStyle()}
<paper-dialog with-backdrop opened>
<paper-dialog
with-backdrop
opened
@opened-changed="${this._openedChanged}"
>
<h2>${this.localize("ui.panel.lovelace.editor.edit_card.header")}</h2>
<paper-spinner
?active="${this._loading}"
@ -436,6 +440,12 @@ export class HuiEditCard extends hassLocalizeLitMixin(LitElement) {
private get _creatingCard(): boolean {
return this.path!.length === 1;
}
private _openedChanged(ev) {
if (!ev.detail.value) {
this.closeDialog!();
}
}
}
declare global {

View File

@ -48,7 +48,7 @@ export class HuiServiceButtonElement extends LitElement
.hass="${this.hass}"
.domain="${this._domain}"
.service="${this._service}"
.service-data="${this._config.service_data}"
.serviceData="${this._config.service_data}"
>${this._config.title}</ha-call-service-button
>
`;

View File

@ -105,6 +105,7 @@ class LovelacePanel extends hassLocalizeLitMixin(LitElement) {
}
public updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (changedProps.has("narrow") || changedProps.has("showMenu")) {
this._updateColumns();
}

View File

@ -31,9 +31,9 @@ describe("parseAspectRatio", () => {
assert.deepEqual(r, ratio178);
});
it("Skips null states", () => {
const r = parseAspectRatio(null);
assert.equal(r, null);
it("Parses 23%", () => {
const r = parseAspectRatio("23%");
assert.deepEqual(r, { w: 100, h: 23 });
});
it("Skips empty states", () => {