mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-25 05:47:20 +00:00
Merge pull request #9334 from home-assistant/dev
This commit is contained in:
commit
2db9f33c41
@ -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",
|
||||
|
2
setup.py
2
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",
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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 = <T extends (...args) => unknown>(
|
||||
func: T,
|
||||
wait,
|
||||
|
||||
export const debounce = <T extends any[]>(
|
||||
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);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -377,7 +377,10 @@ class StateHistoryChartLine extends LocalizeMixin(PolymerElement) {
|
||||
major: {
|
||||
fontStyle: "bold",
|
||||
},
|
||||
source: "auto",
|
||||
sampleSize: 5,
|
||||
autoSkipPadding: 20,
|
||||
maxRotation: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -236,7 +236,9 @@ class StateHistoryChartTimeline extends LocalizeMixin(PolymerElement) {
|
||||
major: {
|
||||
fontStyle: "bold",
|
||||
},
|
||||
sampleSize: 5,
|
||||
autoSkipPadding: 50,
|
||||
maxRotation: 0,
|
||||
},
|
||||
categoryPercentage: undefined,
|
||||
barPercentage: undefined,
|
||||
|
@ -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<ConfigEntry[]>("GET", "config/config_entries/entry");
|
||||
@ -34,9 +33,9 @@ export const getConfigEntries = (hass: HomeAssistant) =>
|
||||
export const updateConfigEntry = (
|
||||
hass: HomeAssistant,
|
||||
configEntryId: string,
|
||||
updatedValues: Partial<ConfigEntryMutableParams>
|
||||
updatedValues: ConfigEntryMutableParams
|
||||
) =>
|
||||
hass.callWS<ConfigEntry>({
|
||||
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<DisableConfigEntryResult>({
|
||||
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<ConfigEntrySystemOptions>
|
||||
) =>
|
||||
hass.callWS<{
|
||||
require_restart: boolean;
|
||||
system_options: ConfigEntrySystemOptions;
|
||||
}>({
|
||||
type: "config_entries/system_options/update",
|
||||
entry_id: configEntryId,
|
||||
...params,
|
||||
});
|
||||
|
@ -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<void> {
|
||||
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<void> {
|
||||
this._submitting = true;
|
||||
const data: Parameters<typeof updateConfigEntrySystemOptions>[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 {
|
||||
|
@ -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%;
|
||||
}
|
||||
|
@ -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%;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ||
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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 {
|
||||
|
@ -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}",
|
||||
|
Loading…
x
Reference in New Issue
Block a user