From d33e035db784853f3bd0d305532e500089c8ec0d Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Tue, 11 Feb 2020 13:11:25 -0500 Subject: [PATCH 01/26] Update Media Card to check for supported features --- src/data/media-player.ts | 9 ++ .../lovelace/cards/hui-media-control-card.ts | 84 +++++++++++++------ 2 files changed, 66 insertions(+), 27 deletions(-) diff --git a/src/data/media-player.ts b/src/data/media-player.ts index 3aaf16e093..cfb17c91c5 100644 --- a/src/data/media-player.ts +++ b/src/data/media-player.ts @@ -3,8 +3,17 @@ import { HomeAssistant } from "../types"; import { timeCachePromiseFunc } from "../common/util/time-cache-function-promise"; export const SUPPORT_PAUSE = 1; +export const SUPPORT_VOLUME_SET = 4; +export const SUPPORT_VOLUME_MUTE = 8; +export const SUPPORT_PREVIOUS_TRACK = 16; export const SUPPORT_NEXT_TRACK = 32; +export const SUPPORT_TURN_ON = 128; +export const SUPPORT_TURN_OFF = 256; +export const SUPPORT_PLAY_MEDIA = 512; +export const SUPPORT_VOLUME_BUTTONS = 1024; +export const SUPPORT_SELECT_SOURCE = 2048; export const SUPPORTS_PLAY = 16384; +export const SUPPORT_SELECT_SOUND_MODE = 65536; export const OFF_STATES = ["off", "idle"]; export interface MediaPlayerThumbnail { diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index c5035a9c58..159efa1c54 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -16,7 +16,15 @@ import "../../../components/ha-card"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element"; import { computeStateName } from "../../../common/entity/compute_state_name"; import { supportsFeature } from "../../../common/entity/supports-feature"; -import { OFF_STATES, SUPPORT_PAUSE } from "../../../data/media-player"; +import { + OFF_STATES, + SUPPORT_PAUSE, + SUPPORT_TURN_ON, + SUPPORT_TURN_OFF, + SUPPORT_PREVIOUS_TRACK, + SUPPORT_NEXT_TRACK, + SUPPORTS_PLAY, +} from "../../../data/media-player"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import { HomeAssistant, MediaEntity } from "../../../types"; import { LovelaceCard, LovelaceCardEditor } from "../types"; @@ -89,7 +97,9 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { - ${OFF_STATES.includes(stateObj.state) + ${OFF_STATES.includes(stateObj.state) || + !stateObj.attributes.media_duration || + !stateObj.attributes.media_position ? "" : html` `}
- + ${(stateObj.state === "off" && + !supportsFeature(stateObj, SUPPORT_TURN_ON)) || + (stateObj.state === "on" && + !supportsFeature(stateObj, SUPPORT_TURN_OFF)) + ? "" + : html` + + `}
- - - + ${!supportsFeature(stateObj, SUPPORT_PREVIOUS_TRACK) + ? "" + : html` + + `} + ${stateObj.state !== "playing" && + !supportsFeature(stateObj, SUPPORTS_PLAY) + ? "" + : html` + + `} + ${!supportsFeature(stateObj, SUPPORT_NEXT_TRACK) + ? "" + : html` + + `}
Date: Thu, 13 Feb 2020 16:30:34 -0500 Subject: [PATCH 02/26] Review Updates --- .../lovelace/cards/hui-media-control-card.ts | 69 ++++++++++++------- src/types.ts | 1 + 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index 159efa1c54..0973b27f26 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -89,12 +89,21 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { })}" >
-
+
${this._config!.name || computeStateName(this.hass!.states[this._config!.entity])}
- ${this._computeMediaTitle(stateObj)} + ${stateObj.attributes.media_title || + this.hass.localize(`state.media_player.${stateObj.state}`) || + this.hass.localize(`state.default.${stateObj.state}`) || + stateObj.state}
+ ${this._computeSecondaryTitle(stateObj)}
${OFF_STATES.includes(stateObj.state) || @@ -116,7 +125,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { ? "" : html` @@ -126,18 +135,20 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { ? "" : html` `} - ${stateObj.state !== "playing" && - !supportsFeature(stateObj, SUPPORTS_PLAY) + ${(stateObj.state !== "playing" && + !supportsFeature(stateObj, SUPPORTS_PLAY)) || + stateObj.state === "unavailable" ? "" : html` `}
@@ -190,30 +201,30 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { } } - private _computeMediaTitle(stateObj: HassEntity): string { - let prefix; - let suffix; + private _computeSecondaryTitle(stateObj: HassEntity): string { + let secondaryTitle: string; switch (stateObj.attributes.media_content_type) { case "music": - prefix = stateObj.attributes.media_artist; - suffix = stateObj.attributes.media_title; + secondaryTitle = stateObj.attributes.media_artist; break; case "tvshow": - prefix = stateObj.attributes.media_series_title; - suffix = stateObj.attributes.media_title; + secondaryTitle = stateObj.attributes.media_series_title; + if (stateObj.attributes.media_season) { + secondaryTitle += " S" + stateObj.attributes.media_season; + + if (stateObj.attributes.media_episode) { + secondaryTitle += "E" + stateObj.attributes.media_episode; + } + } break; default: - prefix = - stateObj.attributes.media_title || - stateObj.attributes.app_name || - this.hass!.localize(`state.media_player.${stateObj.state}`) || - this.hass!.localize(`state.default.${stateObj.state}`) || - stateObj.state; - suffix = ""; + secondaryTitle = stateObj.attributes.app_name + ? stateObj.attributes.app_name + : ""; } - return prefix && suffix ? `${prefix}: ${suffix}` : prefix || suffix || ""; + return secondaryTitle; } private _handleMoreInfo() { @@ -235,6 +246,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { width: 100%; height: 0; padding-bottom: 56.25%; + transition: padding-bottom 0.8s; } .image { @@ -282,12 +294,14 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { width: 44px; height: 44px; } + paper-icon-button { opacity: var(--dark-primary-opacity); } paper-icon-button[disabled] { opacity: var(--dark-disabled-opacity); + background-color: rgba(0, 0, 0, var(--dark-disabled-opacity)); } .playPauseButton { @@ -313,9 +327,16 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { transition: background-color 0.5s; } + .caption.unavailable { + background-color: rgba(0, 0, 0, var(--dark-secondary-opacity)); + } + .title { font-size: 1.2em; margin: 8px 0 4px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; } .progress { diff --git a/src/types.ts b/src/types.ts index 9cef34e771..1e8626bec6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -204,6 +204,7 @@ export type MediaEntity = HassEntityBase & { attributes: HassEntityAttributeBase & { media_duration: number; media_position: number; + media_title: string; }; }; From f6b10232ec317b6ba3593d047f3d8ca3e847a110 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Thu, 13 Feb 2020 16:35:16 -0500 Subject: [PATCH 03/26] Disabled Style Updates --- src/panels/lovelace/cards/hui-media-control-card.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index 0973b27f26..531d8a70bb 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -136,6 +136,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { : html` @@ -162,6 +163,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { : html` @@ -301,7 +303,6 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { paper-icon-button[disabled] { opacity: var(--dark-disabled-opacity); - background-color: rgba(0, 0, 0, var(--dark-disabled-opacity)); } .playPauseButton { @@ -314,6 +315,10 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { transition: background-color 0.5s; } + .playPauseButton[disabled] { + background-color: rgba(0, 0, 0, var(--dark-disabled-opacity)); + } + .caption { position: absolute; left: 0; From 67706a312d9a68b8933cdb6328e79d62acef0643 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Sun, 16 Feb 2020 12:11:18 -0500 Subject: [PATCH 04/26] Support for requesting the image from the server --- .../lovelace/cards/hui-media-control-card.ts | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index 531d8a70bb..ba42dc3041 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -24,6 +24,7 @@ import { SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK, SUPPORTS_PLAY, + fetchMediaPlayerThumbnailWithCache, } from "../../../data/media-player"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import { HomeAssistant, MediaEntity } from "../../../types"; @@ -46,6 +47,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { @property() public hass?: HomeAssistant; @property() private _config?: MediaControlCardConfig; + @property() private _image?: string; public getCardSize(): number { return 3; @@ -76,19 +78,19 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { > `; } - const image = - stateObj.attributes.entity_picture || - "../static/images/card_media_player_bg.png"; return html`
-
+
{ + this._image = `data:${content_type};base64,${content}`; + } + ); } private _computeSecondaryTitle(stateObj: HassEntity): string { @@ -272,6 +295,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { background-repeat: no-repeat; background-color: var(--primary-color); background-size: initial; + background-image: "url(../static/images/card_media_player_bg.png)"; } .no-image > .caption { From 30e56118124537d7882f3d4016eaae3ff6332d0f Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Sun, 16 Feb 2020 12:15:56 -0500 Subject: [PATCH 05/26] Stupid mistake --- src/panels/lovelace/cards/hui-media-control-card.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index ba42dc3041..5b2e32358e 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -79,6 +79,8 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { `; } + const picture = this._image || "../static/images/card_media_player_bg.png"; + return html`
.caption { From 51ce481e7797ed5cab378fc50a5d9fedbffc7f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sun, 16 Feb 2020 23:32:47 +0200 Subject: [PATCH 06/26] Sort list of available events --- src/panels/developer-tools/event/events-list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/developer-tools/event/events-list.js b/src/panels/developer-tools/event/events-list.js index e2435c0dab..abf216b39a 100644 --- a/src/panels/developer-tools/event/events-list.js +++ b/src/panels/developer-tools/event/events-list.js @@ -58,7 +58,7 @@ class EventsList extends EventsMixin(LocalizeMixin(PolymerElement)) { super.connectedCallback(); this.hass.callApi("GET", "events").then( function(events) { - this.events = events; + this.events = events.sort((e1, e2) => compare(e1.event, e2.event)); }.bind(this) ); } From 2718ada9f96be1fe362e37fa0c27a2372af02899 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Mon, 17 Feb 2020 10:01:01 -0500 Subject: [PATCH 07/26] Review updates --- src/data/media-player.ts | 1 + .../lovelace/cards/hui-media-control-card.ts | 20 +++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/data/media-player.ts b/src/data/media-player.ts index cfb17c91c5..ddf024ac98 100644 --- a/src/data/media-player.ts +++ b/src/data/media-player.ts @@ -12,6 +12,7 @@ export const SUPPORT_TURN_OFF = 256; export const SUPPORT_PLAY_MEDIA = 512; export const SUPPORT_VOLUME_BUTTONS = 1024; export const SUPPORT_SELECT_SOURCE = 2048; +export const SUPPORT_STOP = 4096; export const SUPPORTS_PLAY = 16384; export const SUPPORT_SELECT_SOUND_MODE = 65536; export const OFF_STATES = ["off", "idle"]; diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index 5b2e32358e..d93791597b 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -25,12 +25,14 @@ import { SUPPORT_NEXT_TRACK, SUPPORTS_PLAY, fetchMediaPlayerThumbnailWithCache, + SUPPORT_STOP, } from "../../../data/media-player"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import { HomeAssistant, MediaEntity } from "../../../types"; import { LovelaceCard, LovelaceCardEditor } from "../types"; import { fireEvent } from "../../../common/dom/fire_event"; import { MediaControlCardConfig } from "./types"; +import { UNAVAILABLE } from "../../../data/entity"; @customElement("hui-media-control-card") export class HuiMediaControlCard extends LitElement implements LovelaceCard { @@ -94,9 +96,8 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { style="background-image: url(${this.hass.hassUrl(picture)})" >
${this._config!.name || @@ -129,7 +130,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { ? "" : html` @@ -139,7 +140,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { ? "" : html`
From 9a7f7f119d21dc6181d95c718bc03012926dbd6b Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Mon, 17 Feb 2020 10:28:13 -0500 Subject: [PATCH 08/26] Review updates again because I am a fool --- src/panels/lovelace/cards/hui-media-control-card.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index d93791597b..54944b0a0a 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -86,9 +86,8 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { return html`
@@ -140,7 +139,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { ? "" : html`
From da1dd4516902db96d7b7b401093ebc5c9c48b3e2 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Mon, 17 Feb 2020 11:31:27 -0500 Subject: [PATCH 09/26] Update for playlist information if music isnt present --- src/panels/lovelace/cards/hui-media-control-card.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index 54944b0a0a..c38940b375 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -238,6 +238,9 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { case "music": secondaryTitle = stateObj.attributes.media_artist; break; + case "playlist": + secondaryTitle = stateObj.attributes.media_playlist; + break; case "tvshow": secondaryTitle = stateObj.attributes.media_series_title; if (stateObj.attributes.media_season) { From be9ec50e3ad02839dfbd00e5aa1eb093ca005057 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Mon, 17 Feb 2020 11:51:05 -0500 Subject: [PATCH 10/26] When no image occurs mark the image as undefined --- src/panels/lovelace/cards/hui-media-control-card.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index c38940b375..bcc8e04b23 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -69,6 +69,8 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { } const stateObj = this.hass.states[this._config.entity] as MediaEntity; + console.log(stateObj); + if (!stateObj) { return html` Date: Mon, 17 Feb 2020 12:09:17 -0500 Subject: [PATCH 11/26] rookie mistake --- src/panels/lovelace/cards/hui-media-control-card.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index bcc8e04b23..c7dbe17f02 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -69,8 +69,6 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { } const stateObj = this.hass.states[this._config.entity] as MediaEntity; - console.log(stateObj); - if (!stateObj) { return html` Date: Mon, 17 Feb 2020 10:20:24 -0800 Subject: [PATCH 12/26] Add more info to system log (#4899) * Add more info to system log * Add util, oops * Tweak UI --- src/data/integration.ts | 10 ++++ src/data/system_log.ts | 6 +++ .../developer-tools/info/integrations-card.ts | 14 +++--- .../logs/dialog-system-log-detail.ts | 47 ++++++++++++++++++- .../developer-tools/logs/system-log-card.ts | 38 ++++++++------- src/panels/developer-tools/logs/util.ts | 13 +++++ 6 files changed, 102 insertions(+), 26 deletions(-) create mode 100644 src/data/integration.ts create mode 100644 src/panels/developer-tools/logs/util.ts diff --git a/src/data/integration.ts b/src/data/integration.ts new file mode 100644 index 0000000000..f322e96f10 --- /dev/null +++ b/src/data/integration.ts @@ -0,0 +1,10 @@ +import { LocalizeFunc } from "../common/translations/localize"; + +export const integrationDocsUrl = (domain: string) => + `https://www.home-assistant.io/integrations/${domain}`; + +export const integrationIssuesUrl = (domain: string) => + `https://github.com/home-assistant/home-assistant/issues?q=is%3Aissue+is%3Aopen+label%3A%22integration%3A+${domain}%22`; + +export const domainToName = (localize: LocalizeFunc, domain: string) => + localize(`domain.${domain}`) || domain; diff --git a/src/data/system_log.ts b/src/data/system_log.ts index 49f93b79ee..f780adffe3 100644 --- a/src/data/system_log.ts +++ b/src/data/system_log.ts @@ -1,6 +1,7 @@ import { HomeAssistant } from "../types"; export interface LoggedError { + name: string; message: string; level: string; source: string; @@ -14,3 +15,8 @@ export interface LoggedError { export const fetchSystemLog = (hass: HomeAssistant) => hass.callApi("GET", "error/all"); + +export const getLoggedErrorIntegration = (item: LoggedError) => + item.name.startsWith("homeassistant.components.") + ? item.name.split(".")[2] + : undefined; diff --git a/src/panels/developer-tools/info/integrations-card.ts b/src/panels/developer-tools/info/integrations-card.ts index e51f73366a..f16ad1e904 100644 --- a/src/panels/developer-tools/info/integrations-card.ts +++ b/src/panels/developer-tools/info/integrations-card.ts @@ -9,6 +9,10 @@ import { } from "lit-element"; import { HomeAssistant } from "../../../types"; import memoizeOne from "memoize-one"; +import { + integrationDocsUrl, + integrationIssuesUrl, +} from "../../../data/integration"; @customElement("integrations-card") class IntegrationsCard extends LitElement { @@ -28,18 +32,12 @@ class IntegrationsCard extends LitElement { ${domain} - + Documentation - + Issues diff --git a/src/panels/developer-tools/logs/dialog-system-log-detail.ts b/src/panels/developer-tools/logs/dialog-system-log-detail.ts index e7a89162a9..11c075ae1d 100644 --- a/src/panels/developer-tools/logs/dialog-system-log-detail.ts +++ b/src/panels/developer-tools/logs/dialog-system-log-detail.ts @@ -14,6 +14,13 @@ import { SystemLogDetailDialogParams } from "./show-dialog-system-log-detail"; import { PolymerChangedEvent } from "../../../polymer-types"; import { haStyleDialog } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; +import { + integrationDocsUrl, + integrationIssuesUrl, + domainToName, +} from "../../../data/integration"; +import { formatSystemLogTime } from "./util"; +import { getLoggedErrorIntegration } from "../../../data/system_log"; class DialogSystemLogDetail extends LitElement { @property() public hass!: HomeAssistant; @@ -30,6 +37,8 @@ class DialogSystemLogDetail extends LitElement { } const item = this._params.item; + const integration = getLoggedErrorIntegration(item); + return html` -

${new Date(item.timestamp * 1000)}

+

+ Logger: ${item.name} + ${integration + ? html` +
+ Integration: ${domainToName(this.hass.localize, integration)} + (documentation, + issues) + ` + : ""} +
+ ${item.count > 0 + ? html` + First occured: + ${formatSystemLogTime( + item.first_occured, + this.hass!.language + )} + (${item.count} occurences)
+ ` + : ""} + Last logged: + ${formatSystemLogTime(item.timestamp, this.hass!.language)} +

${item.message ? html`
${item.message}
@@ -73,6 +109,15 @@ class DialogSystemLogDetail extends LitElement { ha-paper-dialog { direction: ltr; } + a { + color: var(--primary-color); + } + p { + margin-top: 0; + } + pre { + margin-bottom: 0; + } `, ]; } diff --git a/src/panels/developer-tools/logs/system-log-card.ts b/src/panels/developer-tools/logs/system-log-card.ts index 1a03a72e1c..cf619d5c45 100644 --- a/src/panels/developer-tools/logs/system-log-card.ts +++ b/src/panels/developer-tools/logs/system-log-card.ts @@ -15,20 +15,14 @@ import "../../../components/ha-card"; import "../../../components/buttons/ha-call-service-button"; import "../../../components/buttons/ha-progress-button"; import { HomeAssistant } from "../../../types"; -import { LoggedError, fetchSystemLog } from "../../../data/system_log"; -import { formatDateTimeWithSeconds } from "../../../common/datetime/format_date_time"; -import { formatTimeWithSeconds } from "../../../common/datetime/format_time"; +import { + LoggedError, + fetchSystemLog, + getLoggedErrorIntegration, +} from "../../../data/system_log"; import { showSystemLogDetailDialog } from "./show-dialog-system-log-detail"; - -const formatLogTime = (date, language: string) => { - const today = new Date().setHours(0, 0, 0, 0); - const dateTime = new Date(date * 1000); - const dateTimeDay = new Date(date * 1000).setHours(0, 0, 0, 0); - - return dateTimeDay < today - ? formatDateTimeWithSeconds(dateTime, language) - : formatTimeWithSeconds(dateTime, language); -}; +import { formatSystemLogTime } from "./util"; +import { domainToName } from "../../../data/integration"; @customElement("system-log-card") export class SystemLogCard extends LitElement { @@ -42,6 +36,9 @@ export class SystemLogCard extends LitElement { } protected render(): TemplateResult { + const integrations = this._items + ? this._items.map((item) => getLoggedErrorIntegration(item)) + : []; return html`
@@ -61,25 +58,32 @@ export class SystemLogCard extends LitElement {
` : this._items.map( - (item) => html` + (item, idx) => html`
${item.message}
- ${formatLogTime( + ${formatSystemLogTime( item.timestamp, this.hass!.language )} - ${item.source} (${item.level}) + – + ${integrations[idx] + ? domainToName( + this.hass!.localize, + integrations[idx]! + ) + : item.source} + (${item.level}) ${item.count > 1 ? html` - ${this.hass.localize( "ui.panel.developer-tools.tabs.logs.multiple_messages", "time", - formatLogTime( + formatSystemLogTime( item.first_occured, this.hass!.language ), diff --git a/src/panels/developer-tools/logs/util.ts b/src/panels/developer-tools/logs/util.ts new file mode 100644 index 0000000000..53912f5f91 --- /dev/null +++ b/src/panels/developer-tools/logs/util.ts @@ -0,0 +1,13 @@ +import { formatDateTimeWithSeconds } from "../../../common/datetime/format_date_time"; + +import { formatTimeWithSeconds } from "../../../common/datetime/format_time"; + +export const formatSystemLogTime = (date, language: string) => { + const today = new Date().setHours(0, 0, 0, 0); + const dateTime = new Date(date * 1000); + const dateTimeDay = new Date(date * 1000).setHours(0, 0, 0, 0); + + return dateTimeDay < today + ? formatDateTimeWithSeconds(dateTime, language) + : formatTimeWithSeconds(dateTime, language); +}; From 1cc3936ec37716db1d405dedcc7bc5e959261a03 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Mon, 17 Feb 2020 13:36:21 -0500 Subject: [PATCH 13/26] Typing functions --- src/panels/lovelace/cards/hui-media-control-card.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index c7dbe17f02..6a319b4122 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -261,13 +261,13 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { return secondaryTitle; } - private _handleMoreInfo() { + private _handleMoreInfo(): void { fireEvent(this, "hass-more-info", { entityId: this._config!.entity, }); } - private _handleClick(e: MouseEvent) { + private _handleClick(e: MouseEvent): void { this.hass!.callService("media_player", (e.currentTarget! as any).action, { entity_id: this._config!.entity, }); From 2ab2ade6421cc374bcf56a6eb5e92ddd6fccda3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Mon, 17 Feb 2020 21:15:58 +0200 Subject: [PATCH 14/26] Import compare --- src/panels/developer-tools/event/events-list.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/panels/developer-tools/event/events-list.js b/src/panels/developer-tools/event/events-list.js index abf216b39a..b3f5e4e0c3 100644 --- a/src/panels/developer-tools/event/events-list.js +++ b/src/panels/developer-tools/event/events-list.js @@ -1,6 +1,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; +import { compare } from "../../../common/string/compare"; import { EventsMixin } from "../../../mixins/events-mixin"; import LocalizeMixin from "../../../mixins/localize-mixin"; From 099430238c9a74e5a72a3f7eecbe9a20c0ed49ac Mon Sep 17 00:00:00 2001 From: HomeAssistant Azure Date: Tue, 18 Feb 2020 00:32:41 +0000 Subject: [PATCH 15/26] [ci skip] Translation update --- translations/cs.json | 10 +++++++++- translations/en.json | 9 ++++++++- translations/fr.json | 4 ++-- translations/ko.json | 6 +++--- translations/lb.json | 19 +++++++++++++------ translations/nb.json | 24 ++++++++++++------------ 6 files changed, 47 insertions(+), 25 deletions(-) diff --git a/translations/cs.json b/translations/cs.json index 862f2e8be5..1f646fa05b 100644 --- a/translations/cs.json +++ b/translations/cs.json @@ -604,7 +604,8 @@ "config_entry_system_options": { "enable_new_entities_description": "Pokud je zakázáno, nově objevené entity pro {integration} nebudou automaticky přidány do Home Assistant.", "enable_new_entities_label": "Povolit nově přidané entity.", - "title": "Systémové možnosti pro {integration}" + "title": "Systémové možnosti pro {integration}", + "update": "Aktualizovat" }, "confirmation": { "cancel": "Zrušit", @@ -640,6 +641,9 @@ "more_info_control": { "dismiss": "Zavřít dialog", "edit": "Upravit entitu", + "person": { + "create_zone": "Vytvořit zónu z aktuálního umístění" + }, "restored": { "confirm_remove_text": "Opravdu chcete tuto entitu odebrat?", "confirm_remove_title": "Odebrat entitu?", @@ -891,6 +895,7 @@ }, "edit_ui": "Upravit pomocí uživatelského rozhraní", "edit_yaml": "Upravit jako YAML", + "enable_disable": "Povolit / zakázat automatizaci", "introduction": "Použijte automatizace k oživení svého domova", "load_error_not_editable": "Lze upravovat pouze automatizace v automations.yaml.", "load_error_unknown": "Chyba při načítání automatizace ({err_no}).", @@ -1923,6 +1928,9 @@ "available_states": "Dostupné stavy", "name": "Ovládací panel alarmu" }, + "button": { + "name": "Tlačítko" + }, "conditional": { "name": "Podmínka" }, diff --git a/translations/en.json b/translations/en.json index 0fd6358577..bd41790c3d 100644 --- a/translations/en.json +++ b/translations/en.json @@ -581,6 +581,7 @@ "entity": "Related entities", "group": "Part of the following groups", "integration": "Integration", + "no_related_found": "No related items found.", "scene": "Part of the following scenes", "script": "Part of the following scripts" }, @@ -630,6 +631,7 @@ "unavailable": "This entity is not currently available.", "update": "UPDATE" }, + "no_unique_id": "This entity does not have a unique ID, therefore it's settings can not be managed from the UI.", "related": "Related", "settings": "Settings" }, @@ -1323,6 +1325,7 @@ "filter": { "filter": "Filter", "show_disabled": "Show disabled entities", + "show_readonly": "Show read-only entities", "show_unavailable": "Show unavailable entities" }, "header": "Entities", @@ -1346,6 +1349,7 @@ "status": { "disabled": "Disabled", "ok": "Ok", + "readonly": "Read-only", "unavailable": "Unavailable" }, "unavailable": "(unavailable)" @@ -1701,7 +1705,10 @@ "required_error_msg": "This field is required", "update": "Update" }, - "edit_home_zone": "The location of your home can be changed in the general configuration.", + "edit_home_zone": "The radius of the Home zone can't be edited from the frontend yet. Drag the marker on the map to move the home zone.", + "edit_home_zone_narrow": "The radius of the Home zone can't be edited from the frontend yet. The location can be changed from the general configuration.", + "go_to_core_config": "Go to general configuration?", + "home_zone_core_config": "The location of your home zone is editable from the general configuration page. The radius of the Home zone can't be edited from the frontend yet. Do you want to go to the general configuration?", "introduction": "Zones allow you to specify certain regions on earth. When a person is within a zone, the state will take the name from the zone. Zones can also be used as a trigger or condition inside automation setups.", "no_zones_created_yet": "Looks like you have not created any zones yet." }, diff --git a/translations/fr.json b/translations/fr.json index 2a83688e88..51c1fd69bf 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -1696,7 +1696,7 @@ "name": "Nom", "new_zone": "Nouvelle zone", "passive": "Passif", - "passive_note": "Les zones passives sont cachées dans le frontend et ne sont pas utilisées comme emplacement pour les traceurs de périphériques. C'est utile si vous voulez seulement les utiliser pour des automations.", + "passive_note": "Les zones passives sont cachées dans l'interface utilisateur et ne sont pas utilisées comme emplacement pour les appareils suivis. Elles sont utiles si vous voulez les utiliser pour des automations.", "radius": "Rayon", "required_error_msg": "Ce champ est requis", "update": "Mettre à jour" @@ -2381,7 +2381,7 @@ "push_notifications": { "description": "Envoyer des notifications à cet appareil.", "error_load_platform": "Configurer notify.html5.", - "error_use_https": "Nécessite l'activation SSL pour le frontend.", + "error_use_https": "Nécessite l'activation SSL pour l'interface utilisateur.", "header": "Notifications push", "link_promo": "En savoir plus", "push_notifications": "Notifications push" diff --git a/translations/ko.json b/translations/ko.json index 102689e56b..0838c59ba5 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -647,7 +647,7 @@ "restored": { "confirm_remove_text": "이 구성요소를 제거하시겠습니까?", "confirm_remove_title": "구성요소를 제거하시겠습니까?", - "not_provided": "이 구성요소는 현재 사용할 수 없으며 제거, 변경 또는 기능 장애가 있는 통합 구성요소이거나 기기의 남겨진 잔여데이터 입니다.", + "not_provided": "이 구성요소는 현재 사용할 수 없습니다. 기기의 남겨진 잔여 데이터 이거나 제거, 변경 또는 기능 장애가 있는 통합 구성요소일 수 있습니다.", "remove_action": "구성요소 제거", "remove_intro": "구성요소를 더 이상 사용하지 않는 경우, 이를 제거하여 정리할 수 있습니다." }, @@ -1218,11 +1218,11 @@ } }, "customize": { - "attributes_customize": "다음 속성은 이미 customize.yaml 에 설정되어 있습니다", + "attributes_customize": "customize.yaml 에 설정된 속성은 다음과 같습니다.", "attributes_not_set": "다음의 속성이 설정되지 않았습니다. 원하는 경우 설정해주세요.", "attributes_outside": "다음 속성은 customize.yaml 이 아닌 다른 곳에서 사용자화됩니다", "attributes_override": "원하는 경우 재정의 할 수 있습니다.", - "attributes_set": "구성요소의 다음 속성은 프로그래밍 방식으로 설정됩니다.", + "attributes_set": "프로그래밍되어 자동으로 설정된 속성은 다음과 같습니다.", "caption": "사용자화", "description": "구성요소를 사용자화 합니다", "different_include": "도메인, 글로브 혹은 다른 포함 구성을 통해 가능할 수 있습니다.", diff --git a/translations/lb.json b/translations/lb.json index f16abd0b64..1c9de75892 100644 --- a/translations/lb.json +++ b/translations/lb.json @@ -602,9 +602,9 @@ }, "dialogs": { "config_entry_system_options": { - "enable_new_entities_description": "Falls desaktivéiert, ginn nei entdeckten Entitéiten net automatesch zu Home Assistant dobäigesat.", + "enable_new_entities_description": "Falls desaktivéiert, ginn nei entdeckten Entitéiten fir {integration} net automatesch zu Home Assistant dobäigesat.", "enable_new_entities_label": "Aktivéiert nei dobäigesate Entitéiten.", - "title": "System Optiounen", + "title": "System Optiounen fir {integration}", "update": "Aktualiséieren" }, "confirmation": { @@ -641,6 +641,9 @@ "more_info_control": { "dismiss": "Dialog ofbriechen", "edit": "Entitéit änneren", + "person": { + "create_zone": "Zone erstellen vun der aktueller Positioun" + }, "restored": { "confirm_remove_text": "Sécher fir dës Entitéit ze läsche?", "confirm_remove_title": "Entitéit läschen?", @@ -892,6 +895,7 @@ }, "edit_ui": "Mam Benotzer Inteface änneren", "edit_yaml": "Als YAML änneren", + "enable_disable": "Automatismen aktivéieren/deaktivieren", "introduction": "Benotzt Automatismen fir däin Haus zum Liewen ze bréngen", "load_error_not_editable": "Nëmmen Automatiounen am automations.yaml kënnen editéiert ginn.", "load_error_unknown": "Feeler beim luede vun der Automatioun ({err_no}).", @@ -1266,7 +1270,7 @@ "details": "Hei sinn all Detailer vun ärem Apparat.", "device_not_found": "Apparat net fonnt.", "entities": { - "add_entities_lovelace": "All Entitéiten zu Lovelace bäisetzen", + "add_entities_lovelace": "Zu Lovelace bäisetzen", "entities": "Entitéiten", "none": "Dësen Appart huet keng Entitéiten." }, @@ -1507,7 +1511,7 @@ "section": { "reloading": { "automation": "Automatisme nei lueden", - "core": "Kär néi lueden", + "core": "Standuert and Personnalisatioun néi lueden", "group": "Gruppe nei lueden", "heading": "Konfiguratioun gëtt frësch gelueden", "introduction": "E puer Deeler vum Home Assistant kënne frësch geluede ginn ouni datt een Neistart néideg ass. Klick op nei luede fir di aktuell Konfiguratioun z'entlueden an di nei Konfiguratioun ze lueden.", @@ -1692,7 +1696,7 @@ "name": "Numm", "new_zone": "Nei Zon", "passive": "Passiv", - "passive_note": "Passiv Zonë sinn am Frontend verstoppt a ginn net als Standuert fir Apparaten Tracker benotzt. Dëst ass nëtzlech wann Dir et just fir Automatisme wëllt benotzen.", + "passive_note": "Passiv Zone sinn am Frontend verstoppt a ginn net als Standuert fir Apparaten Tracker benotzt. Dëst ass nëtzlech wann Dir et just fir Automatisme wëllt benotzen.", "radius": "Radius", "required_error_msg": "Dëst Feld ass erfuerderlech", "update": "Aktualiséieren" @@ -1924,6 +1928,9 @@ "available_states": "Verfügbar Zoustänn", "name": "Alarm Zentral" }, + "button": { + "name": "Knäppchen" + }, "conditional": { "name": "Bedingungen" }, @@ -2101,7 +2108,7 @@ }, "suggest_card": { "add": "Zu Lovelace bäisetzen", - "create_own": "Erstellt är eegen", + "create_own": "Aner Kaart auswielen", "header": "Mir hun eng Suggestioun fir iech erstallt" }, "view": { diff --git a/translations/nb.json b/translations/nb.json index 304a56fc0e..140f0a897a 100644 --- a/translations/nb.json +++ b/translations/nb.json @@ -1010,7 +1010,7 @@ "cloud": { "account": { "alexa": { - "config_documentation": "Konfigurer dokumentasjon", + "config_documentation": "Konfigurasjonsdokumentasjon", "disable": "deaktiver", "enable": "aktiver", "enable_ha_skill": "Aktivere Home Assistant-ferdigheten for Alexa", @@ -1027,7 +1027,7 @@ "connection_status": "Status for skytilkobling", "fetching_subscription": "Henter abonnement...", "google": { - "config_documentation": "Konfigurer dokumentasjon", + "config_documentation": "Konfigurasjonsdokumentasjon", "devices_pin": "PIN-kode for sikkerhetsenheter", "enable_ha_skill": "Aktivere Home Assistant-ferdigheten for Google Assistant", "enable_state_reporting": "Aktiver tilstandsrapportering", @@ -1376,7 +1376,7 @@ "add_area": "Legg til område", "area_picker_label": "Område", "close": "Lukk", - "created_config": "Opprettet konfigurasjon for {name}.", + "created_config": "Opprettet konfigurasjon for {name} .", "dismiss": "Avvis dialog", "error_saving_area": "Feil ved lagring av område: {error}", "external_step": { @@ -1729,12 +1729,12 @@ "network_stopped": "Z-Wave nettverket stoppet" }, "node_config": { - "config_parameter": "Konfigurasjon parameter", - "config_value": "Konfigurasjon verdi", + "config_parameter": "Konfigurasjonsparameter", + "config_value": "Konfigurasjonsverdi", "false": "Usant", "header": "Alternativer for nodekonfigurasjon", "seconds": "sekunder", - "set_config_parameter": "Angi konfigurasjons parameter", + "set_config_parameter": "Angi konfigurasjonsparameter", "set_wakeup": "Angi vekkeintervall", "true": "Sant" }, @@ -2077,20 +2077,20 @@ "header": "Rediger brukergrensesnitt", "menu": { "open": "Åpne Lovelace UI-menyen", - "raw_editor": "Tekstbasert konfigurasjonsredigering" + "raw_editor": "Redigeringsprogram for raw-konfigurasjon" }, "migrate": { "header": "Inkompatibel Konfigurasjon", - "migrate": "Overfør konfigurasjon", - "para_migrate": "Home Assistant kan legge til ID-er på alle dine kort og visninger automatisk for deg ved å trykke på 'Overfør konfigurasjon' knappen.", + "migrate": "Migrer konfigurasjon", + "para_migrate": "Hjemmeassistent kan legge til ID-er på alle kortene og visningene automatisk for deg ved å trykke på 'Migrer konfigurasjon' -knappen.", "para_no_id": "Dette elementet har ingen ID. Vennligst legg til en ID på dette elementet i 'ui-lovelace.yaml'." }, "raw_editor": { "confirm_remove_config_text": "Vi vil automatisk generere Lovelace-visningene dine med områdene og enhetene dine hvis du fjerner Lovelace-konfigurasjonen.", "confirm_remove_config_title": "Er du sikker på at du vil fjerne Lovelace-konfigurasjonen? Vi vil automatisk generere Lovelace-visningene dine med områdene og enhetene dine.", "confirm_unsaved_changes": "Du har ulagrede endringer, er du sikker på at du vil avslutte?", - "confirm_unsaved_comments": "Konfigurasjonen din inneholder kommentar(er), disse vil ikke bli lagret. Vil du fortsette?", - "error_invalid_config": "Konfigurasjonen er ikke gyldig: {error}", + "confirm_unsaved_comments": "Konfigurasjonen din inneholder kommentarer, disse vil ikke bli lagret. Vil du fortsette?", + "error_invalid_config": "Konfigurasjonen din er ikke gyldig: {error}", "error_parse_yaml": "Kan ikke analysere YAML: {error}", "error_remove": "Kan ikke fjerne konfigurasjonen: {error}", "error_save_yaml": "Kan ikke lagre YAML: {error}", @@ -2216,7 +2216,7 @@ "data": { "password": "API-passord" }, - "description": "Vennligst skriv inn API-passordet i http-konfigurasjonen din:" + "description": "Skriv inn API-passordet i HTTP-konfigurasjonen:" }, "mfa": { "data": { From 52ae01ea7487ad19b24edd6abb160735a520d8f0 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 18 Feb 2020 11:27:27 +0100 Subject: [PATCH 16/26] Fix description and title of options flow (#4910) --- src/dialogs/config-flow/show-dialog-options-flow.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dialogs/config-flow/show-dialog-options-flow.ts b/src/dialogs/config-flow/show-dialog-options-flow.ts index 3e1b6d1742..493b1d2b77 100644 --- a/src/dialogs/config-flow/show-dialog-options-flow.ts +++ b/src/dialogs/config-flow/show-dialog-options-flow.ts @@ -47,7 +47,7 @@ export const showOptionsFlowDialog = ( renderShowFormStepHeader(hass, step) { return ( hass.localize( - `component.${step.handler}.options.step.${step.step_id}.title` + `component.${configEntry.domain}.options.step.${step.step_id}.title` ) || hass.localize(`ui.dialogs.options_flow.form.header`) ); }, @@ -55,7 +55,7 @@ export const showOptionsFlowDialog = ( renderShowFormStepDescription(hass, step) { const description = localizeKey( hass.localize, - `component.${step.handler}.config.step.${step.step_id}.description`, + `component.${configEntry.domain}.options.step.${step.step_id}.description`, step.description_placeholders ); return description From 4675579f79b00c140e17602e59834dc69d438708 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 18 Feb 2020 08:33:25 -0800 Subject: [PATCH 17/26] Add safe mode support (#4908) * Add safe mode support * Lint * Fix type in demo --- package.json | 2 +- src/fake_data/demo_config.ts | 1 + .../areas/dialog-area-registry-detail.ts | 1 + .../lovelace/cards/hui-safe-mode-card.ts | 70 +++++++++++++++++++ .../common/generate-lovelace-config.ts | 16 +++-- .../create-element/create-card-element.ts | 2 + src/panels/lovelace/hui-root.ts | 3 +- src/translations/en.json | 5 ++ yarn.lock | 8 +-- 9 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 src/panels/lovelace/cards/hui-safe-mode-card.ts diff --git a/package.json b/package.json index 8336c0692c..09facfc322 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "fuse.js": "^3.4.4", "google-timezones-json": "^1.0.2", "hls.js": "^0.12.4", - "home-assistant-js-websocket": "^4.4.0", + "home-assistant-js-websocket": "4.4.1", "intl-messageformat": "^2.2.0", "js-yaml": "^3.13.1", "leaflet": "^1.4.0", diff --git a/src/fake_data/demo_config.ts b/src/fake_data/demo_config.ts index 1361937db4..91e7080771 100644 --- a/src/fake_data/demo_config.ts +++ b/src/fake_data/demo_config.ts @@ -17,4 +17,5 @@ export const demoConfig: HassConfig = { version: "DEMO", whitelist_external_dirs: [], config_source: "storage", + safe_mode: false, }; diff --git a/src/panels/config/areas/dialog-area-registry-detail.ts b/src/panels/config/areas/dialog-area-registry-detail.ts index 520d676195..093f099766 100644 --- a/src/panels/config/areas/dialog-area-registry-detail.ts +++ b/src/panels/config/areas/dialog-area-registry-detail.ts @@ -6,6 +6,7 @@ import { TemplateResult, property, } from "lit-element"; +import "@material/mwc-button"; import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable"; import "@polymer/paper-input/paper-input"; diff --git a/src/panels/lovelace/cards/hui-safe-mode-card.ts b/src/panels/lovelace/cards/hui-safe-mode-card.ts new file mode 100644 index 0000000000..01f579d3f8 --- /dev/null +++ b/src/panels/lovelace/cards/hui-safe-mode-card.ts @@ -0,0 +1,70 @@ +import { + html, + LitElement, + TemplateResult, + customElement, + css, + CSSResult, + property, +} from "lit-element"; +import "@material/mwc-button"; + +import "../../../components/ha-card"; + +import { LovelaceCard } from "../types"; +import { HomeAssistant } from "../../../types"; + +@customElement("hui-safe-mode-card") +export class HuiSafeModeCard extends LitElement implements LovelaceCard { + @property() public hass?: HomeAssistant; + + public getCardSize(): number { + return 3; + } + + public setConfig(_config: any): void { + // No config necessary. + } + + protected render(): TemplateResult { + return html` + +
+ ${this.hass!.localize( + "ui.panel.lovelace.cards.safe-mode.description" + )} +
+ +
+ `; + } + + static get styles(): CSSResult { + return css` + ha-card { + --ha-card-header-color: var(--primary-color); + } + .card-actions a { + text-decoration: none; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-safe-mode-card": HuiSafeModeCard; + } +} diff --git a/src/panels/lovelace/common/generate-lovelace-config.ts b/src/panels/lovelace/common/generate-lovelace-config.ts index ae5c5dff95..8f450fcdea 100644 --- a/src/panels/lovelace/common/generate-lovelace-config.ts +++ b/src/panels/lovelace/common/generate-lovelace-config.ts @@ -404,6 +404,17 @@ export const generateLovelaceConfigFromData = async ( entities: HassEntities, localize: LocalizeFunc ): Promise => { + if (config.safe_mode) { + return { + title: config.location_name, + views: [ + { + cards: [{ type: "safe-mode" }], + }, + ], + }; + } + const viewEntities = extractViews(entities); const views = viewEntities.map((viewEntity: GroupEntity) => { @@ -461,11 +472,8 @@ export const generateLovelaceConfigFromData = async ( // User has no entities if (views.length === 1 && views[0].cards!.length === 0) { - import( - /* webpackChunkName: "hui-empty-state-card" */ "../cards/hui-empty-state-card" - ); views[0].cards!.push({ - type: "custom:hui-empty-state-card", + type: "empty-state", }); } diff --git a/src/panels/lovelace/create-element/create-card-element.ts b/src/panels/lovelace/create-element/create-card-element.ts index 74f171580f..d3acc76267 100644 --- a/src/panels/lovelace/create-element/create-card-element.ts +++ b/src/panels/lovelace/create-element/create-card-element.ts @@ -31,11 +31,13 @@ const ALWAYS_LOADED_TYPES = new Set([ const LAZY_LOAD_TYPES = { "alarm-panel": () => import("../cards/hui-alarm-panel-card"), + "empty-state": () => import("../cards/hui-empty-state-card"), "entity-filter": () => import("../cards/hui-entity-filter-card"), "picture-elements": () => import("../cards/hui-picture-elements-card"), "picture-entity": () => import("../cards/hui-picture-entity-card"), "picture-glance": () => import("../cards/hui-picture-glance-card"), "plant-status": () => import("../cards/hui-plant-status-card"), + "safe-mode": () => import("../cards/hui-safe-mode-card"), "shopping-list": () => import("../cards/hui-shopping-list-card"), conditional: () => import("../cards/hui-conditional-card"), gauge: () => import("../cards/hui-gauge-card"), diff --git a/src/panels/lovelace/hui-root.ts b/src/panels/lovelace/hui-root.ts index 33f3191644..abedfe33f0 100644 --- a/src/panels/lovelace/hui-root.ts +++ b/src/panels/lovelace/hui-root.ts @@ -226,7 +226,8 @@ class HUIRoot extends LitElement { ` : ""} - ${this.hass!.user!.is_admin + ${this.hass!.user!.is_admin && + !this.hass!.config.safe_mode ? html` Date: Tue, 18 Feb 2020 22:17:52 +0100 Subject: [PATCH 18/26] Fix multiselect without data (#4906) --- src/components/ha-form/ha-form-multi_select.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/ha-form/ha-form-multi_select.ts b/src/components/ha-form/ha-form-multi_select.ts index 2f21740a14..dc85f3f6cc 100644 --- a/src/components/ha-form/ha-form-multi_select.ts +++ b/src/components/ha-form/ha-form-multi_select.ts @@ -41,6 +41,7 @@ export class HaFormMultiSelect extends LitElement implements HaFormElement { ? this.schema.options : Object.entries(this.schema.options!); + const data = this.data || []; return html`