diff --git a/gallery/src/demos/demo-integration-card.ts b/gallery/src/demos/demo-integration-card.ts index 97e581f2cc..4f5162c176 100644 --- a/gallery/src/demos/demo-integration-card.ts +++ b/gallery/src/demos/demo-integration-card.ts @@ -31,10 +31,8 @@ const createConfigEntry = ( supports_options: false, supports_unload: true, disabled_by: null, - system_options: { - disable_new_entities: false, - disable_polling: false, - }, + pref_disable_new_entities: false, + pref_disable_polling: false, reason: null, ...override, }); @@ -68,10 +66,7 @@ const optionsFlowEntry = createConfigEntry("Options Flow", { supports_options: true, }); const disabledPollingEntry = createConfigEntry("Disabled Polling", { - system_options: { - disable_new_entities: false, - disable_polling: true, - }, + pref_disable_polling: true, }); const setupErrorEntry = createConfigEntry("Setup Error", { state: "setup_error", diff --git a/setup.py b/setup.py index 32ad5f3e1a..972990e191 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name="home-assistant-frontend", - version="20210601.0", + version="20210601.1", description="The Home Assistant frontend", url="https://github.com/home-assistant/home-assistant-polymer", author="The Home Assistant Authors", diff --git a/src/common/entity/domain_icon.ts b/src/common/entity/domain_icon.ts index 836c5024dc..adfb8873b4 100644 --- a/src/common/entity/domain_icon.ts +++ b/src/common/entity/domain_icon.ts @@ -89,8 +89,6 @@ export const domainIcon = ( } // eslint-disable-next-line - console.warn( - "Unable to find icon for domain " + domain + " (" + stateObj + ")" - ); + console.warn(`Unable to find icon for domain ${domain}`); return DEFAULT_DOMAIN_ICON; }; diff --git a/src/common/util/debounce.ts b/src/common/util/debounce.ts index 557d596540..70aaddf2e0 100644 --- a/src/common/util/debounce.ts +++ b/src/common/util/debounce.ts @@ -4,29 +4,25 @@ // be triggered. The function will be called after it stops being called for // N milliseconds. If `immediate` is passed, trigger the function on the // leading edge, instead of the trailing. -// eslint-disable-next-line: ban-types -export const debounce = unknown>( - func: T, - wait, + +export const debounce = ( + func: (...args: T) => void, + wait: number, immediate = false -): T => { - let timeout; - // @ts-ignore - return function (...args) { - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-this-alias - const context = this; +) => { + let timeout: number | undefined; + return (...args: T): void => { const later = () => { - timeout = null; + timeout = undefined; if (!immediate) { - func.apply(context, args); + func(...args); } }; const callNow = immediate && !timeout; clearTimeout(timeout); - timeout = setTimeout(later, wait); + timeout = window.setTimeout(later, wait); if (callNow) { - func.apply(context, args); + func(...args); } }; }; diff --git a/src/components/data-table/ha-data-table.ts b/src/components/data-table/ha-data-table.ts index 0811669c51..c7c2927c33 100644 --- a/src/components/data-table/ha-data-table.ts +++ b/src/components/data-table/ha-data-table.ts @@ -246,7 +246,7 @@ export class HaDataTable extends LitElement { aria-rowcount=${this._filteredData.length + 1} style=${styleMap({ height: this.autoHeight - ? `${(this._filteredData.length || 1) * 53 + 57}px` + ? `${(this._filteredData.length || 1) * 53 + 53}px` : `calc(100% - ${this._headerHeight}px)`, })} > @@ -919,13 +919,11 @@ export class HaDataTable extends LitElement { color: var(--secondary-text-color); } .scroller { - display: flex; - position: relative; - contain: strict; height: calc(100% - 57px); } - .mdc-data-table__table:not(.auto-height) .scroller { - overflow: auto; + + .mdc-data-table__table.auto-height .scroller { + overflow-y: hidden !important; } .grows { flex-grow: 1; diff --git a/src/components/state-history-chart-line.js b/src/components/state-history-chart-line.js index 412ca18e75..dc767fb45c 100644 --- a/src/components/state-history-chart-line.js +++ b/src/components/state-history-chart-line.js @@ -377,7 +377,10 @@ class StateHistoryChartLine extends LocalizeMixin(PolymerElement) { major: { fontStyle: "bold", }, + source: "auto", + sampleSize: 5, autoSkipPadding: 20, + maxRotation: 0, }, }, ], diff --git a/src/components/state-history-chart-timeline.js b/src/components/state-history-chart-timeline.js index 23f0a91e7d..fa29388da3 100644 --- a/src/components/state-history-chart-timeline.js +++ b/src/components/state-history-chart-timeline.js @@ -236,7 +236,9 @@ class StateHistoryChartTimeline extends LocalizeMixin(PolymerElement) { major: { fontStyle: "bold", }, + sampleSize: 5, autoSkipPadding: 50, + maxRotation: 0, }, categoryPercentage: undefined, barPercentage: undefined, diff --git a/src/data/config_entries.ts b/src/data/config_entries.ts index 8e4de41a9e..e83c0498d3 100644 --- a/src/data/config_entries.ts +++ b/src/data/config_entries.ts @@ -14,19 +14,18 @@ export interface ConfigEntry { | "failed_unload"; supports_options: boolean; supports_unload: boolean; - system_options: ConfigEntrySystemOptions; + pref_disable_new_entities: boolean; + pref_disable_polling: boolean; disabled_by: "user" | null; reason: string | null; } -export interface ConfigEntryMutableParams { - title: string; -} - -export interface ConfigEntrySystemOptions { - disable_new_entities: boolean; - disable_polling: boolean; -} +export type ConfigEntryMutableParams = Partial< + Pick< + ConfigEntry, + "title" | "pref_disable_new_entities" | "pref_disable_polling" + > +>; export const getConfigEntries = (hass: HomeAssistant) => hass.callApi("GET", "config/config_entries/entry"); @@ -34,9 +33,9 @@ export const getConfigEntries = (hass: HomeAssistant) => export const updateConfigEntry = ( hass: HomeAssistant, configEntryId: string, - updatedValues: Partial + updatedValues: ConfigEntryMutableParams ) => - hass.callWS({ + hass.callWS<{ require_restart: boolean; config_entry: ConfigEntry }>({ type: "config_entries/update", entry_id: configEntryId, ...updatedValues, @@ -52,13 +51,15 @@ export const reloadConfigEntry = (hass: HomeAssistant, configEntryId: string) => require_restart: boolean; }>("POST", `config/config_entries/entry/${configEntryId}/reload`); +export interface DisableConfigEntryResult { + require_restart: boolean; +} + export const disableConfigEntry = ( hass: HomeAssistant, configEntryId: string ) => - hass.callWS<{ - require_restart: boolean; - }>({ + hass.callWS({ type: "config_entries/disable", entry_id: configEntryId, disabled_by: "user", @@ -72,17 +73,3 @@ export const enableConfigEntry = (hass: HomeAssistant, configEntryId: string) => entry_id: configEntryId, disabled_by: null, }); - -export const updateConfigEntrySystemOptions = ( - hass: HomeAssistant, - configEntryId: string, - params: Partial -) => - hass.callWS<{ - require_restart: boolean; - system_options: ConfigEntrySystemOptions; - }>({ - type: "config_entries/system_options/update", - entry_id: configEntryId, - ...params, - }); diff --git a/src/dialogs/config-entry-system-options/dialog-config-entry-system-options.ts b/src/dialogs/config-entry-system-options/dialog-config-entry-system-options.ts index 92cac06fef..37d49e0a8a 100644 --- a/src/dialogs/config-entry-system-options/dialog-config-entry-system-options.ts +++ b/src/dialogs/config-entry-system-options/dialog-config-entry-system-options.ts @@ -7,7 +7,10 @@ import "../../components/ha-dialog"; import "../../components/ha-formfield"; import "../../components/ha-switch"; import type { HaSwitch } from "../../components/ha-switch"; -import { updateConfigEntrySystemOptions } from "../../data/config_entries"; +import { + ConfigEntryMutableParams, + updateConfigEntry, +} from "../../data/config_entries"; import { haStyleDialog } from "../../resources/styles"; import type { HomeAssistant } from "../../types"; import { showAlertDialog } from "../generic/show-dialog-box"; @@ -32,8 +35,8 @@ class DialogConfigEntrySystemOptions extends LitElement { ): Promise { this._params = params; this._error = undefined; - this._disableNewEntities = params.entry.system_options.disable_new_entities; - this._disablePolling = params.entry.system_options.disable_polling; + this._disableNewEntities = params.entry.pref_disable_new_entities; + this._disablePolling = params.entry.pref_disable_polling; } public closeDialog(): void { @@ -147,14 +150,14 @@ class DialogConfigEntrySystemOptions extends LitElement { private async _updateEntry(): Promise { this._submitting = true; - const data: Parameters[2] = { - disable_new_entities: this._disableNewEntities, + const data: ConfigEntryMutableParams = { + pref_disable_new_entities: this._disableNewEntities, }; if (this._allowUpdatePolling()) { - data.disable_polling = this._disablePolling; + data.pref_disable_polling = this._disablePolling; } try { - const result = await updateConfigEntrySystemOptions( + const result = await updateConfigEntry( this.hass, this._params!.entry.entry_id, data @@ -166,15 +169,8 @@ class DialogConfigEntrySystemOptions extends LitElement { ), }); } - const curEntry = this._params!.entry; - this._params!.entryUpdated({ - ...curEntry, - system_options: { - ...curEntry.system_options, - ...data, - }, - }); - this._params = undefined; + this._params!.entryUpdated(result.config_entry); + this.closeDialog(); } catch (err) { this._error = err.message || "Unknown error"; } finally { diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index 5b39620c92..e98c2375f0 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -638,18 +638,6 @@ export class QuickBar extends LitElement { margin-left: 8px; } - .uni-virtualizer-host { - display: block; - position: relative; - contain: strict; - overflow: auto; - height: 100%; - } - - .uni-virtualizer-host > * { - box-sizing: border-box; - } - mwc-list-item { width: 100%; } diff --git a/src/layouts/hass-tabs-subpage.ts b/src/layouts/hass-tabs-subpage.ts index ea691e1766..552f29544c 100644 --- a/src/layouts/hass-tabs-subpage.ts +++ b/src/layouts/hass-tabs-subpage.ts @@ -229,7 +229,7 @@ class HassTabsSubpage extends LitElement { color: var(--sidebar-text-color); text-decoration: none; } - :host([narrow]) .toolbar a { + .bottom-bar a { width: 25%; } diff --git a/src/panels/config/core/ha-config-network.ts b/src/panels/config/core/ha-config-network.ts index 6793673711..bded44d3d5 100644 --- a/src/panels/config/core/ha-config-network.ts +++ b/src/panels/config/core/ha-config-network.ts @@ -9,13 +9,14 @@ import { } from "lit"; import { customElement, property, state } from "lit/decorators"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; -import "../../../components/ha-network"; import "../../../components/ha-card"; import "../../../components/ha-checkbox"; +import "../../../components/ha-network"; import "../../../components/ha-settings-row"; +import { fetchNetworkInfo } from "../../../data/hassio/network"; import { - NetworkConfig, getNetworkConfig, + NetworkConfig, setNetworkConfig, } from "../../../data/network"; import { haStyle } from "../../../resources/styles"; @@ -73,7 +74,19 @@ class ConfigNetwork extends LitElement { private async _load() { this._error = undefined; try { - this._networkConfig = await getNetworkConfig(this.hass); + const coreNetwork = await getNetworkConfig(this.hass); + if (isComponentLoaded(this.hass, "hassio")) { + const supervisorNetwork = await fetchNetworkInfo(this.hass); + const interfaces = new Set( + supervisorNetwork.interfaces.map((int) => int.interface) + ); + if (interfaces.size) { + coreNetwork.adapters = coreNetwork.adapters.filter((adapter) => + interfaces.has(adapter.name) + ); + } + } + this._networkConfig = coreNetwork; } catch (err) { this._error = err.message || err; } diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index 3e2cdcfd4e..5ace01bdcb 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -11,7 +11,11 @@ import { slugify } from "../../../common/string/slugify"; import "../../../components/entity/ha-battery-icon"; import "../../../components/ha-icon-next"; import { AreaRegistryEntry } from "../../../data/area_registry"; -import { ConfigEntry, disableConfigEntry } from "../../../data/config_entries"; +import { + ConfigEntry, + disableConfigEntry, + DisableConfigEntryResult, +} from "../../../data/config_entries"; import { computeDeviceName, DeviceRegistryEntry, @@ -25,7 +29,10 @@ import { } from "../../../data/entity_registry"; import { SceneEntities, showSceneEditor } from "../../../data/scene"; import { findRelated, RelatedResult } from "../../../data/search"; -import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box"; +import { + showAlertDialog, + showConfirmationDialog, +} from "../../../dialogs/generic/show-dialog-box"; import "../../../layouts/hass-error-screen"; import "../../../layouts/hass-tabs-subpage"; import { haStyle } from "../../../resources/styles"; @@ -671,13 +678,41 @@ export class HaConfigDevicePage extends LitElement { dismissText: this.hass.localize("ui.common.no"), })) ) { - disableConfigEntry(this.hass, cnfg_entry); + let result: DisableConfigEntryResult; + try { + // eslint-disable-next-line no-await-in-loop + result = await disableConfigEntry(this.hass, cnfg_entry); + } catch (err) { + showAlertDialog(this, { + title: this.hass.localize( + "ui.panel.config.integrations.config_entry.disable_error" + ), + text: err.message, + }); + return; + } + if (result.require_restart) { + showAlertDialog(this, { + text: this.hass.localize( + "ui.panel.config.integrations.config_entry.disable_restart_confirm" + ), + }); + } delete updates.disabled_by; } } } } - await updateDeviceRegistryEntry(this.hass, this.deviceId, updates); + try { + await updateDeviceRegistryEntry(this.hass, this.deviceId, updates); + } catch (err) { + showAlertDialog(this, { + title: this.hass.localize( + "ui.panel.config.devices.update_device_error" + ), + text: err.message, + }); + } if ( !oldDeviceName || diff --git a/src/panels/config/integrations/ha-integration-card.ts b/src/panels/config/integrations/ha-integration-card.ts index 4e2a103c48..85663de87d 100644 --- a/src/panels/config/integrations/ha-integration-card.ts +++ b/src/panels/config/integrations/ha-integration-card.ts @@ -18,6 +18,7 @@ import { ConfigEntry, deleteConfigEntry, disableConfigEntry, + DisableConfigEntryResult, enableConfigEntry, reloadConfigEntry, updateConfigEntry, @@ -487,7 +488,18 @@ export class HaIntegrationCard extends LitElement { if (!confirmed) { return; } - const result = await disableConfigEntry(this.hass, entryId); + let result: DisableConfigEntryResult; + try { + result = await disableConfigEntry(this.hass, entryId); + } catch (err) { + showAlertDialog(this, { + title: this.hass.localize( + "ui.panel.config.integrations.config_entry.disable_error" + ), + text: err.message, + }); + return; + } if (result.require_restart) { showAlertDialog(this, { text: this.hass.localize( @@ -503,7 +515,18 @@ export class HaIntegrationCard extends LitElement { private async _enableIntegration(configEntry: ConfigEntry) { const entryId = configEntry.entry_id; - const result = await enableConfigEntry(this.hass, entryId); + let result: DisableConfigEntryResult; + try { + result = await enableConfigEntry(this.hass, entryId); + } catch (err) { + showAlertDialog(this, { + title: this.hass.localize( + "ui.panel.config.integrations.config_entry.disable_error" + ), + text: err.message, + }); + return; + } if (result.require_restart) { showAlertDialog(this, { @@ -567,10 +590,10 @@ export class HaIntegrationCard extends LitElement { if (newName === null) { return; } - const newEntry = await updateConfigEntry(this.hass, configEntry.entry_id, { + const result = await updateConfigEntry(this.hass, configEntry.entry_id, { title: newName, }); - fireEvent(this, "entry-updated", { entry: newEntry }); + fireEvent(this, "entry-updated", { entry: result.config_entry }); } static get styles(): CSSResultGroup { diff --git a/src/panels/config/integrations/ha-integration-header.ts b/src/panels/config/integrations/ha-integration-header.ts index d18ba01670..de6932d1a5 100644 --- a/src/panels/config/integrations/ha-integration-header.ts +++ b/src/panels/config/integrations/ha-integration-header.ts @@ -63,7 +63,7 @@ export class HaIntegrationHeader extends LitElement { ]); } - if (this.configEntry?.system_options.disable_polling) { + if (this.configEntry?.pref_disable_polling) { icons.push([ mdiSyncOff, this.hass.localize( diff --git a/src/panels/logbook/ha-logbook.ts b/src/panels/logbook/ha-logbook.ts index 3c62b1c3af..1a8d6864bc 100644 --- a/src/panels/logbook/ha-logbook.ts +++ b/src/panels/logbook/ha-logbook.ts @@ -353,15 +353,7 @@ class HaLogbook extends LitElement { } :host([virtualize]) .container { - display: block; - position: relative; - contain: strict; height: 100%; - overflow: auto; - } - - .container > * { - box-sizing: border-box; } .narrow .entry { diff --git a/src/translations/en.json b/src/translations/en.json index dae343b3c2..458e140bc3 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -1975,6 +1975,7 @@ "confirm_rename_entity_ids": "Do you also want to rename the entity IDs of your entities?", "confirm_rename_entity_ids_warning": "This will not change any configuration (like automations, scripts, scenes, dashboards) that is currently using these entities! You will have to update them yourself to use the new entity IDs!", "confirm_disable_config_entry": "There are no more devices for the config entry {entry_name}, do you want to instead disable the config entry?", + "update_device_error": "Updating the device failed", "disabled": "Disabled", "data_table": { "device": "Device", @@ -2163,6 +2164,7 @@ "reload_restart_confirm": "Restart Home Assistant to finish reloading this integration", "disable_restart_confirm": "Restart Home Assistant to finish disabling this integration", "enable_restart_confirm": "Restart Home Assistant to finish enabling this integration", + "disable_error": "Enabling or disabling of the integration failed", "manuf": "by {manufacturer}", "hub": "Connected via", "firmware": "Firmware: {version}",