From 01e5dfc9b33dc6e0fa17b628cb35045e38ec0ef9 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 27 Apr 2020 20:40:30 +0200 Subject: [PATCH 01/49] Fix demo themes (#5643) --- demo/src/configs/jimpower/theme.ts | 2 +- demo/src/configs/kernehed/theme.ts | 2 +- demo/src/configs/teachingbirds/theme.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/demo/src/configs/jimpower/theme.ts b/demo/src/configs/jimpower/theme.ts index 655c6da45d..5d269d38a9 100644 --- a/demo/src/configs/jimpower/theme.ts +++ b/demo/src/configs/jimpower/theme.ts @@ -33,7 +33,7 @@ export const demoThemeJimpower = () => ({ "label-badge-border-color": "green", "paper-listbox-color": "var(--primary-color)", "paper-slider-disabled-secondary-color": "var(--disabled-text-color)", - "paper-card-background-color": "#434954", + "card-background-color": "#434954", "label-badge-text-color": "var(--primary-text-color)", "paper-slider-knob-start-color": "var(--accent-color)", "switch-unchecked-track-color": "var(--disabled-text-color)", diff --git a/demo/src/configs/kernehed/theme.ts b/demo/src/configs/kernehed/theme.ts index 078dc5ac93..e1cb10e78a 100644 --- a/demo/src/configs/kernehed/theme.ts +++ b/demo/src/configs/kernehed/theme.ts @@ -34,7 +34,7 @@ export const demoThemeKernehed = () => ({ "label-badge-border-color": "green", "paper-listbox-color": "#777777", "paper-slider-disabled-secondary-color": "var(--disabled-text-color)", - "paper-card-background-color": "#292929", + "card-background-color": "#292929", "label-badge-text-color": "var(--primary-text-color)", "paper-slider-knob-start-color": "var(--accent-color)", "switch-unchecked-track-color": "var(--disabled-text-color)", diff --git a/demo/src/configs/teachingbirds/theme.ts b/demo/src/configs/teachingbirds/theme.ts index 8861bd0663..34687a23f1 100644 --- a/demo/src/configs/teachingbirds/theme.ts +++ b/demo/src/configs/teachingbirds/theme.ts @@ -13,7 +13,7 @@ export const demoThemeTeachingbirds = () => ({ "paper-listbox-color": "#FFFFFF", "paper-toggle-button-checked-bar-color": "var(--light-primary-color)", "switch-unchecked-track-color": "var(--primary-text-color)", - "paper-card-background-color": "#4e4e4e", + "card-background-color": "#4e4e4e", "label-badge-text-color": "var(--text-primary-color)", "primary-background-color": "#303030", "sidebar-icon-color": "var(--paper-item-icon-color)", From 88217473f727fccbd89b0f985819d580cd8f24e4 Mon Sep 17 00:00:00 2001 From: Aidan Timson Date: Mon, 27 Apr 2020 19:42:37 +0100 Subject: [PATCH 02/49] =?UTF-8?q?Add=20search=20to=20integrations=20?= =?UTF-8?q?=F0=9F=94=8D=20(#5593)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bram Kragten --- .../config/entities/ha-config-entities.ts | 4 + .../integrations/ha-config-integrations.ts | 226 +++++++++++++++--- src/translations/en.json | 2 + 3 files changed, 197 insertions(+), 35 deletions(-) diff --git a/src/panels/config/entities/ha-config-entities.ts b/src/panels/config/entities/ha-config-entities.ts index 2da4fb17d4..21585f8001 100644 --- a/src/panels/config/entities/ha-config-entities.ts +++ b/src/panels/config/entities/ha-config-entities.ts @@ -745,6 +745,10 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { position: relative; top: 2px; } + .search-toolbar search-input { + margin-left: 8px; + top: 1px; + } .search-toolbar { display: flex; justify-content: space-between; diff --git a/src/panels/config/integrations/ha-config-integrations.ts b/src/panels/config/integrations/ha-config-integrations.ts index 806e2e74c6..f347ce34da 100644 --- a/src/panels/config/integrations/ha-config-integrations.ts +++ b/src/panels/config/integrations/ha-config-integrations.ts @@ -10,9 +10,14 @@ import { PropertyValues, TemplateResult, } from "lit-element"; +import memoizeOne from "memoize-one"; +import * as Fuse from "fuse.js"; import { compare } from "../../../common/string/compare"; import { computeRTL } from "../../../common/util/compute_rtl"; -import { afterNextRender } from "../../../common/util/render-status"; +import { + afterNextRender, + nextRender, +} from "../../../common/util/render-status"; import "../../../components/entity/ha-state-icon"; import "../../../components/ha-card"; import "../../../components/ha-fab"; @@ -29,7 +34,7 @@ import { localizeConfigFlowTitle, subscribeConfigFlowInProgress, } from "../../../data/config_flow"; -import { DataEntryFlowProgress } from "../../../data/data_entry_flow"; +import type { DataEntryFlowProgress } from "../../../data/data_entry_flow"; import { DeviceRegistryEntry, subscribeDeviceRegistry, @@ -52,6 +57,15 @@ import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; import { haStyle } from "../../../resources/styles"; import { HomeAssistant, Route } from "../../../types"; import { configSections } from "../ha-panel-config"; +import "../../../common/search/search-input"; + +interface DataEntryFlowProgressExtended extends DataEntryFlowProgress { + localized_title?: string; +} + +interface ConfigEntryExtended extends ConfigEntry { + localized_domain_name?: string; +} @customElement("ha-config-integrations") class HaConfigIntegrations extends SubscribeMixin(LitElement) { @@ -65,9 +79,10 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { @property() public route!: Route; - @property() private _configEntries: ConfigEntry[] = []; + @property() private _configEntries: ConfigEntryExtended[] = []; - @property() private _configEntriesInProgress: DataEntryFlowProgress[] = []; + @property() + private _configEntriesInProgress: DataEntryFlowProgressExtended[] = []; @property() private _entityRegistryEntries: EntityRegistryEntry[] = []; @@ -79,6 +94,8 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { window.location.hash.substring(1) ); + @property() private _filter?: string; + public hassSubscribe(): UnsubscribeFunc[] { return [ subscribeEntityRegistry(this.hass.connection, (entries) => { @@ -87,18 +104,72 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { subscribeDeviceRegistry(this.hass.connection, (entries) => { this._deviceRegistryEntries = entries; }), - subscribeConfigFlowInProgress(this.hass, (flowsInProgress) => { - this._configEntriesInProgress = flowsInProgress; - for (const flow of flowsInProgress) { + subscribeConfigFlowInProgress(this.hass, async (flowsInProgress) => { + const translationsPromisses: Promise[] = []; + flowsInProgress.forEach((flow) => { // To render title placeholders if (flow.context.title_placeholders) { - this.hass.loadBackendTranslation("config", flow.handler); + translationsPromisses.push( + this.hass.loadBackendTranslation("config", flow.handler) + ); } - } + }); + await Promise.all(translationsPromisses); + await nextRender(); + this._configEntriesInProgress = flowsInProgress.map((flow) => { + return { + ...flow, + localized_title: localizeConfigFlowTitle(this.hass.localize, flow), + }; + }); }), ]; } + private _filterConfigEntries = memoizeOne( + ( + configEntries: ConfigEntryExtended[], + filter?: string + ): ConfigEntryExtended[] => { + if (!filter) { + return configEntries; + } + const options: Fuse.FuseOptions = { + keys: ["domain", "localized_domain_name", "title"], + caseSensitive: false, + minMatchCharLength: 2, + threshold: 0.2, + }; + const fuse = new Fuse(configEntries, options); + return fuse.search(filter); + } + ); + + private _filterConfigEntriesInProgress = memoizeOne( + ( + configEntriesInProgress: DataEntryFlowProgressExtended[], + filter?: string + ): DataEntryFlowProgressExtended[] => { + configEntriesInProgress = configEntriesInProgress.map( + (flow: DataEntryFlowProgressExtended) => ({ + ...flow, + title: localizeConfigFlowTitle(this.hass.localize, flow), + }) + ); + if (!filter) { + return configEntriesInProgress; + } + const options: Fuse.FuseOptions = { + keys: ["handler", "localized_title"], + caseSensitive: false, + minMatchCharLength: 2, + threshold: 0.2, + }; + const fuse = new Fuse(configEntriesInProgress, options); + return fuse.search(filter); + } + ); + protected firstUpdated(changed: PropertyValues) { super.firstUpdated(changed); this._loadConfigEntries(); @@ -126,6 +197,15 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { } protected render(): TemplateResult { + const configEntries = this._filterConfigEntries( + this._configEntries, + this._filter + ); + const configEntriesInProgress = this._filterConfigEntriesInProgress( + this._configEntriesInProgress, + this._filter + ); + return html` + ${this.narrow + ? html` +
+ + + +
+ ` + : ""} - + ${this.hass.localize( this._showIgnored @@ -161,12 +252,25 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { + ${!this.narrow + ? html` + + ` + : ""} +
${this._showIgnored - ? this._configEntries + ? configEntries .filter((item) => item.source === "ignore") .map( - (item: ConfigEntry) => html` + (item: ConfigEntryExtended) => html`
${this.hass.localize( @@ -183,7 +287,7 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { />

- ${domainToName(this.hass.localize, item.domain)} + ${item.localized_domain_name}

html` + ${configEntriesInProgress.length + ? configEntriesInProgress.map( + (flow: DataEntryFlowProgressExtended) => html`
${this.hass.localize( @@ -219,7 +323,7 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { />

- ${localizeConfigFlowTitle(this.hass.localize, flow)} + ${flow.localized_title}

{ + ${configEntries.length + ? configEntries.map((item: ConfigEntryExtended) => { const devices = this._getDevices(item); const entities = this._getEntities(item); - const integrationName = domainToName( - this.hass.localize, - item.domain - ); return item.source === "ignore" ? "" : html` @@ -274,10 +374,10 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { />

- ${integrationName} + ${item.localized_domain_name}

- ${integrationName === item.title + ${item.localized_domain_name === item.title ? html` ` : item.title}

@@ -365,7 +465,8 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { `; }) - : html` + : !this._configEntries.length + ? html`

@@ -383,7 +484,27 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { >

- `} + ` + : ""} + ${this._filter && + !configEntriesInProgress.length && + !configEntries.length && + this._configEntries.length + ? html` +
+

+ ${this.hass.localize( + "ui.panel.config.integrations.none_found" + )} +

+

+ ${this.hass.localize( + "ui.panel.config.integrations.none_found_detail" + )} +

+
+ ` + : ""} { - this._configEntries = configEntries.sort((conf1, conf2) => - compare(conf1.domain + conf1.title, conf2.domain + conf2.title) - ); + this._configEntries = configEntries + .sort((conf1, conf2) => + compare(conf1.domain + conf1.title, conf2.domain + conf2.title) + ) + .map( + (entry: ConfigEntry): ConfigEntryExtended => ({ + ...entry, + localized_domain_name: domainToName( + this.hass.localize, + entry.domain + ), + }) + ); }); } @@ -565,6 +696,10 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { }); } + private _handleSearchChange(ev: CustomEvent) { + this._filter = ev.detail.value; + } + static get styles(): CSSResult[] { return [ haStyle, @@ -573,7 +708,7 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); grid-gap: 16px 16px; - padding: 16px; + padding: 8px 16px 16px; margin-bottom: 64px; } ha-card { @@ -630,6 +765,27 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { margin-bottom: 16px; vertical-align: middle; } + .none-found { + margin: auto; + text-align: center; + } + search-input.header { + display: block; + position: relative; + left: -8px; + top: -7px; + color: var(--secondary-text-color); + margin-left: 16px; + } + .search { + padding: 0 16px; + background: var(--sidebar-background-color); + border-bottom: 1px solid var(--divider-color); + } + .search search-input { + position: relative; + top: 2px; + } img { max-height: 60px; max-width: 90%; diff --git a/src/translations/en.json b/src/translations/en.json index 2c959b6786..883374aea1 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -1351,6 +1351,8 @@ "home_assistant_website": "Home Assistant website", "configure": "Configure", "none": "Nothing configured yet", + "none_found": "No integrations found", + "none_found_detail": "Adjust your search criteria.", "integration_not_found": "Integration not found.", "details": "Integration details", "rename_dialog": "Edit the name of this config entry", From 75ba343b5eecfd824d837f7051d7839cb30c2d74 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Mon, 27 Apr 2020 14:43:23 -0400 Subject: [PATCH 03/49] Weather Card: Switch Importance of Name and State (#5624) * Improvements to the name and state importance * Bram Suggestions --- src/data/weather.ts | 4 +- .../cards/hui-weather-forecast-card.ts | 234 +++++++++--------- 2 files changed, 125 insertions(+), 113 deletions(-) diff --git a/src/data/weather.ts b/src/data/weather.ts index 45b6423e37..5eb946cc2e 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -150,7 +150,7 @@ const getWeatherExtrema = ( ${ tempHigh ? ` - ${hass!.localize(`ui.card.weather.high`)} ${tempHigh} ${unit} + ${tempHigh} ${unit} ` : "" } @@ -158,7 +158,7 @@ const getWeatherExtrema = ( ${ tempLow ? ` - ${hass!.localize(`ui.card.weather.low`)} ${tempLow} ${unit} + ${tempLow} ${unit} ` : "" } diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.ts b/src/panels/lovelace/cards/hui-weather-forecast-card.ts index de40b4af6a..060139f125 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.ts +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.ts @@ -165,7 +165,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { tabindex="0" >
-
+
${stateObj.state in weatherImages ? html` `} -
+
+
+
${this._config.name || computeStateName(stateObj)}
@@ -191,15 +193,15 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { )}
-
-
-
- ${stateObj.attributes.temperature}${getWeatherUnit(this.hass, "temperature")} -
-
- ${getSecondaryWeatherAttribute(this.hass, stateObj)} +
+
+ ${stateObj.attributes.temperature}${getWeatherUnit(this.hass, "temperature")} +
+
+ ${getSecondaryWeatherAttribute(this.hass, stateObj)} +
@@ -312,7 +314,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { } else { this.removeAttribute("verynarrow"); } - if (this.offsetWidth < 200) { + if (this.offsetWidth < 225) { this.setAttribute("veryverynarrow", ""); } else { this.removeAttribute("veryverynarrow"); @@ -337,61 +339,72 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { align-items: center; } - .icon-info { + .icon-image { display: flex; align-items: center; - min-width: 0; - flex: 1; + min-width: 64px; + margin-right: 16px; } .weather-image, .weather-icon { - flex: 0 0 66px; - margin-right: 16px; + flex: 0 0 64px; } .weather-icon { - --iron-icon-width: 66px; - --iron-icon-height: 66px; + --iron-icon-width: 64px; + --iron-icon-height: 64px; } .info { + display: flex; + justify-content: space-between; + flex-grow: 1; overflow: hidden; } - .name { - font-size: 16px; - color: var(--secondary-text-color); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .state { - font-size: 28px; - line-height: 1.2; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - .temp-attribute { - display: flex; - flex-direction: column; - align-items: flex-end; + text-align: right; } .temp-attribute .temp { position: relative; - font-size: 38px; - line-height: 1; margin-right: 24px; } .temp-attribute .temp span { position: absolute; font-size: 24px; - top: 4px; + top: 1px; + } + + .name, + .temp-attribute .temp { + font-size: 28px; + line-height: 1.2; + } + + .state, + .attribute { + font-size: 14px; + line-height: 1; + } + + .name-state { + overflow: hidden; + padding-right: 12px; + width: 100%; + } + + .name, + .state { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .attribute { + white-space: nowrap; } .forecast { @@ -427,80 +440,12 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { --iron-icon-height: 40px; } - .attribute { - line-height: 1; - } - .attribute, - .templow { + .templow, + .state { color: var(--secondary-text-color); } - :host([narrow]) .weather-image { - flex: 0 0 58px; - } - - :host([narrow]) .weather-icon { - --iron-icon-width: 58px; - --iron-icon-height: 58px; - } - - :host([narrow]) .state { - font-size: 22px; - } - - :host([narrow]) .temp-attribute .temp { - font-size: 44px; - margin-right: 18px; - } - - :host([narrow]) .temp-attribute .temp span { - font-size: 18px; - top: 3px; - } - - :host([narrow]) .attribute { - display: none; - } - - :host([narrow]) .forecast { - justify-content: space-around; - } - - :host([veryVeryNarrow]) .content { - flex-wrap: wrap; - justify-content: center; - } - - :host([veryNarrow]) .icon-info { - flex: initial; - } - - :host([narrow]) .weather-image { - flex: 0 0 48px; - } - - :host([narrow]) .weather-icon { - --iron-icon-width: 48px; - --iron-icon-height: 48px; - } - - :host([veryNarrow]) .info { - display: none; - } - - :host([veryNarrow]) .temp-attribute .temp { - font-size: 36px; - } - - :host([veryNarrow]) .temp-attribute .temp span { - top: 2px; - } - - :host([veryVeryNarrow]) .temp-attribute { - padding-top: 4px; - } - .unavailable { height: 100px; display: flex; @@ -510,6 +455,73 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { padding: 10px 20px; text-align: center; } + + /* ============= NARROW ============= */ + + :host([narrow]) .icon-image { + min-width: 52px; + } + + :host([narrow]) .weather-image { + flex: 0 0 52px; + width: 52px; + } + + :host([narrow]) .weather-icon { + --iron-icon-width: 52px; + --iron-icon-height: 52px; + } + + :host([narrow]) .forecast { + justify-content: space-around; + } + + :host([narrow]) .name, + :host([narrow]) .temp-attribute .temp { + font-size: 22px; + } + + :host([narrow]) .temp-attribute .temp { + margin-right: 16px; + } + + :host([narrow]) .temp span { + top: 1px; + font-size: 16px; + } + + /* ============= VERY NARROW ============= */ + + :host([veryNarrow]) .state, + :host([veryNarrow]) .attribute { + display: none; + } + + :host([veryNarrow]) .info { + flex-direction: column; + align-items: flex-start; + } + + :host([veryNarrow]) .name-state { + padding-right: 0; + } + + /* ============= VERY VERY NARROW ============= */ + + :host([veryVeryNarrow]) .info { + padding-top: 4px; + align-items: center; + } + + :host([veryVeryNarrow]) .content { + flex-wrap: wrap; + justify-content: center; + flex-direction: column; + } + + :host([veryVeryNarrow]) .icon-image { + margin-right: 0; + } `; } } From b0168fbb85ba916b384cddf11637b01331d6c241 Mon Sep 17 00:00:00 2001 From: Sean Mooney Date: Tue, 28 Apr 2020 04:03:54 -0400 Subject: [PATCH 04/49] Updated repo links on Dev Tools Info panel (#5644) These were still using the old names of the repos. home-assistant is now "core" and home-assistant-polymer is now "frontend". --- src/panels/developer-tools/info/developer-tools-info.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/panels/developer-tools/info/developer-tools-info.ts b/src/panels/developer-tools/info/developer-tools-info.ts index 4bebb76103..ba5fc85dd3 100644 --- a/src/panels/developer-tools/info/developer-tools-info.ts +++ b/src/panels/developer-tools/info/developer-tools-info.ts @@ -59,7 +59,7 @@ class HaPanelDevInfo extends LitElement { )}
${this.hass.localize("ui.panel.developer-tools.tabs.info.source")} ${this.hass.localize( "ui.panel.developer-tools.tabs.info.server" @@ -67,7 +67,7 @@ class HaPanelDevInfo extends LitElement { > — ${this.hass.localize( "ui.panel.developer-tools.tabs.info.frontend" From b04fe141ac7e3f74cb6ea4ad4d46493904e0d484 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 28 Apr 2020 23:09:20 +0200 Subject: [PATCH 05/49] Improve styling of MQTT debug info (#5626) --- src/data/mqtt.ts | 1 + .../dialog-mqtt-device-debug-info.ts | 44 +++++--- .../mqtt-discovery-payload.ts | 61 ++++++++-- .../mqtt-messages.ts | 104 ++++++++++++++---- 4 files changed, 165 insertions(+), 45 deletions(-) diff --git a/src/data/mqtt.ts b/src/data/mqtt.ts index d00f9f2415..ff3a960752 100644 --- a/src/data/mqtt.ts +++ b/src/data/mqtt.ts @@ -5,6 +5,7 @@ export interface MQTTMessage { payload: string; qos: number; retain: number; + time: string; } export interface MQTTTopicDebugInfo { diff --git a/src/dialogs/mqtt-device-debug-info-dialog/dialog-mqtt-device-debug-info.ts b/src/dialogs/mqtt-device-debug-info-dialog/dialog-mqtt-device-debug-info.ts index a825d12396..4eb09e5382 100644 --- a/src/dialogs/mqtt-device-debug-info-dialog/dialog-mqtt-device-debug-info.ts +++ b/src/dialogs/mqtt-device-debug-info-dialog/dialog-mqtt-device-debug-info.ts @@ -80,7 +80,7 @@ class DialogMQTTDeviceDebugInfo extends LitElement {

${this.hass!.localize("ui.dialogs.mqtt_device_debug_info.entities")}

-