Compare commits

..

6 Commits

Author SHA1 Message Date
J. Nick Koston
23ba92e4ad avoid downloading the whole entity registry again as well 2023-02-24 18:29:30 -06:00
J. Nick Koston
c636eacc51 Merge branch 'energy_no_ids' into ii2 2023-02-24 17:34:27 -06:00
J. Nick Koston
f75d17e10c Avoid fetching all stats metadata when there are no entities
Fetch all the data at once since it is not dependant
2023-02-24 17:26:29 -06:00
J. Nick Koston
2c6acecb60 Merge branch 'dupe_calls' into ii2 2023-02-24 17:14:15 -06:00
J. Nick Koston
225a3c3f50 Avoid fetching all stats metadata when there are no entities
Fetch all the data at once since it is not dependant
2023-02-24 17:12:01 -06:00
J. Nick Koston
19c125f7be Fix duplicate fetch of stats metadata in more info 2023-02-24 16:51:18 -06:00
20 changed files with 235 additions and 410 deletions

View File

@@ -59,6 +59,7 @@
"prefer-destructuring": "off",
"no-restricted-globals": [2, "event"],
"prefer-promise-reject-errors": "off",
"no-unsafe-optional-chaining": "warn",
"import/prefer-default-export": "off",
"import/no-default-export": "off",
"import/no-unresolved": "off",

View File

@@ -2,7 +2,6 @@ const webpack = require("webpack");
const path = require("path");
const TerserPlugin = require("terser-webpack-plugin");
const { WebpackManifestPlugin } = require("webpack-manifest-plugin");
const CompressionWebpackPlugin = require("compression-webpack-plugin");
const log = require("fancy-log");
const WebpackBar = require("webpackbar");
const paths = require("./paths.js");
@@ -76,7 +75,6 @@ const createWebpackConfig = ({
chunkIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
},
plugins: [
new CompressionWebpackPlugin(),
!isStatsBuild && new WebpackBar({ fancy: !isProdBuild }),
new WebpackManifestPlugin({
// Only include the JS of entrypoints

View File

@@ -100,7 +100,6 @@
"app-datepicker": "^5.1.0",
"chart.js": "^3.3.2",
"comlink": "^4.4.1",
"compression-webpack-plugin": "^10.0.0",
"core-js": "^3.28.0",
"cropperjs": "^1.5.13",
"date-fns": "^2.29.3",
@@ -135,10 +134,10 @@
"tsparticles-preset-links": "^2.9.3",
"unfetch": "^5.0.0",
"vis-data": "^7.1.4",
"vis-network": "^9.1.4",
"vis-network": "^9.1.2",
"vue": "^2.7.14",
"vue2-daterange-picker": "^0.6.8",
"weekstart": "^2.0.0",
"weekstart": "^1.1.0",
"workbox-cacheable-response": "^6.5.4",
"workbox-core": "^6.5.4",
"workbox-expiration": "^6.5.4",
@@ -189,7 +188,7 @@
"babel-loader": "^9.1.2",
"chai": "^4.3.7",
"del": "^7.0.0",
"eslint": "^8.35.0",
"eslint": "^8.34.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^17.0.0",
"eslint-config-prettier": "^8.6.0",
@@ -233,7 +232,7 @@
"serve": "^11.3.2",
"sinon": "^15.0.1",
"source-map-url": "^0.4.1",
"systemjs": "^6.14.0",
"systemjs": "^6.13.0",
"tar": "^6.1.13",
"terser-webpack-plugin": "^5.3.6",
"ts-lit-plugin": "^1.2.1",

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
version = "20230224.0"
version = "20230223.0"
license = {text = "Apache-2.0"}
description = "The Home Assistant frontend"
readme = "README.md"

View File

@@ -1,6 +1,6 @@
import { css, html, LitElement, nothing } from "lit";
/* eslint-disable lit/prefer-static-styles */
import { html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { styleMap } from "lit/directives/style-map";
import { fireEvent } from "../common/dom/fire_event";
import type { HaFormSchema } from "../components/ha-form/types";
import { autocompleteLoginFields } from "../data/auth";
@@ -29,43 +29,35 @@ export class HaPasswordManagerPolyfill extends LitElement {
@property({ attribute: false }) public boundingRect?: DOMRect;
private _styleElement?: HTMLStyleElement;
public connectedCallback() {
super.connectedCallback();
this._styleElement = document.createElement("style");
this._styleElement.textContent = css`
.password-manager-polyfill {
position: absolute;
opacity: 0;
z-index: -1;
}
.password-manager-polyfill input {
width: 100%;
height: 62px;
padding: 0;
border: 0;
}
.password-manager-polyfill input[type="submit"] {
width: 0;
height: 0;
}
`.toString();
document.head.append(this._styleElement);
}
public disconnectedCallback() {
super.disconnectedCallback();
this._styleElement?.remove();
delete this._styleElement;
}
protected createRenderRoot() {
// Add under document body so the element isn't placed inside any shadow roots
return document.body;
}
protected render() {
private get styles() {
return `
.password-manager-polyfill {
position: absolute;
top: ${this.boundingRect?.y || 148}px;
left: calc(50% - ${(this.boundingRect?.width || 360) / 2}px);
width: ${this.boundingRect?.width || 360}px;
opacity: 0;
z-index: -1;
}
.password-manager-polyfill input {
width: 100%;
height: 62px;
padding: 0;
border: 0;
}
.password-manager-polyfill input[type="submit"] {
width: 0;
height: 0;
}
`;
}
protected render(): TemplateResult {
if (
this.step &&
this.step.type === "form" &&
@@ -75,11 +67,6 @@ export class HaPasswordManagerPolyfill extends LitElement {
return html`
<form
class="password-manager-polyfill"
style=${styleMap({
top: `${this.boundingRect?.y || 148}px`,
left: `calc(50% - ${(this.boundingRect?.width || 360) / 2}px)`,
width: `${this.boundingRect?.width || 360}px`,
})}
aria-hidden="true"
@submit=${this._handleSubmit}
>
@@ -87,13 +74,16 @@ export class HaPasswordManagerPolyfill extends LitElement {
this.render_input(input)
)}
<input type="submit" />
<style>
${this.styles}
</style>
</form>
`;
}
return nothing;
return html``;
}
private render_input(schema: HaFormSchema) {
private render_input(schema: HaFormSchema): TemplateResult | string {
const inputType = schema.name.includes("password") ? "password" : "text";
if (schema.type !== "string") {
return "";

View File

@@ -24,6 +24,7 @@ import {
mdiDatabase,
mdiEarHearing,
mdiEye,
mdiFan,
mdiFlash,
mdiFlower,
mdiFormatListBulleted,
@@ -90,6 +91,7 @@ export const FIXED_DOMAIN_ICONS = {
conversation: mdiMicrophoneMessage,
counter: mdiCounter,
demo: mdiHomeAssistant,
fan: mdiFan,
google_assistant: mdiGoogleAssistant,
group: mdiGoogleCirclesCommunities,
homeassistant: mdiHomeAssistant,

View File

@@ -15,8 +15,6 @@ import {
mdiCheckCircleOutline,
mdiClock,
mdiCloseCircleOutline,
mdiFan,
mdiFanOff,
mdiGestureTapButton,
mdiLanConnect,
mdiLanDisconnect,
@@ -110,9 +108,6 @@ export const domainIconWithoutDefault = (
}
return compareState === "not_home" ? mdiAccountArrowRight : mdiAccount;
case "fan":
return compareState === "off" ? mdiFanOff : mdiFan;
case "humidifier":
return compareState === "off" ? mdiAirHumidifierOff : mdiAirHumidifier;

View File

@@ -44,6 +44,7 @@ export class HaBar extends LitElement {
}
rect:last-child {
fill: var(--ha-bar-primary-color, var(--primary-color));
rx: var(--ha-bar-border-radius, 4px);
}
svg {
border-radius: var(--ha-bar-border-radius, 4px);

View File

@@ -62,7 +62,7 @@ class HaLabelBadge extends LitElement {
height: var(--ha-label-badge-size, 2.5em);
line-height: var(--ha-label-badge-size, 2.5em);
font-size: var(--ha-label-badge-font-size, 1.5em);
border-radius: var(--ha-label-badge-border-radius, 50%);
border-radius: 50%;
border: 0.1em solid var(--ha-label-badge-color, var(--primary-color));
color: var(--label-badge-text-color, rgb(76, 76, 76));

View File

@@ -30,30 +30,6 @@ export class HaListItem extends ListItemBase {
margin-inline-end: 0px !important;
direction: var(--direction);
}
:host([multiline-secondary]) {
height: auto;
}
:host([multiline-secondary]) .mdc-deprecated-list-item__text {
padding: 8px 0;
}
:host([multiline-secondary]) .mdc-deprecated-list-item__secondary-text {
text-overflow: initial;
white-space: normal;
overflow: auto;
display: inline-block;
margin-top: 10px;
}
:host([multiline-secondary]) .mdc-deprecated-list-item__primary-text {
margin-top: 10px;
}
:host([multiline-secondary])
.mdc-deprecated-list-item__secondary-text::before {
display: none;
}
:host([multiline-secondary])
.mdc-deprecated-list-item__primary-text::before {
display: none;
}
`,
];
}

View File

@@ -11,10 +11,8 @@ import {
} from "date-fns/esm";
import { Collection, getCollection } from "home-assistant-js-websocket";
import { groupBy } from "../common/util/group-by";
import { subscribeOne } from "../common/util/subscribe-one";
import { HomeAssistant } from "../types";
import { ConfigEntry, getConfigEntries } from "./config_entries";
import { subscribeEntityRegistry } from "./entity_registry";
import {
fetchStatistics,
getStatisticMetadata,
@@ -341,9 +339,8 @@ const getEnergyData = async (
end?: Date,
compare?: boolean
): Promise<EnergyData> => {
const [configEntries, entityRegistryEntries, info] = await Promise.all([
const [configEntries, info] = await Promise.all([
getConfigEntries(hass, { domain: "co2signal" }),
subscribeOne(hass.connection, subscribeEntityRegistry),
getEnergyInfo(hass),
]);
@@ -352,15 +349,15 @@ const getEnergyData = async (
: undefined;
let co2SignalEntity: string | undefined;
if (co2SignalConfigEntry) {
for (const entry of entityRegistryEntries) {
if (entry.config_entry_id !== co2SignalConfigEntry.entry_id) {
for (const entityId of Object.keys(hass.entities)) {
const entity = hass.entities[entityId];
if (entity.platform !== "co2signal") {
continue;
}
// The integration offers 2 entities. We want the % one.
const co2State = hass.states[entry.entity_id];
const co2State = hass.states[entityId];
if (!co2State || co2State.attributes.unit_of_measurement !== "%") {
continue;
}
@@ -405,34 +402,35 @@ const getEnergyData = async (
volume: lengthUnit === "km" ? "L" : "gal",
};
const stats = {
...(energyStatIds.length
? await fetchStatistics(
hass!,
startMinHour,
end,
energyStatIds,
period,
energyUnits,
["sum"]
)
: {}),
...(waterStatIds.length
? await fetchStatistics(
hass!,
startMinHour,
end,
waterStatIds,
period,
waterUnits,
["sum"]
)
: {}),
};
const _energyStats = energyStatIds.length
? fetchStatistics(
hass!,
startMinHour,
end,
energyStatIds,
period,
energyUnits,
["sum"]
)
: Promise.resolve({});
const _waterStats = waterStatIds.length
? await fetchStatistics(
hass!,
startMinHour,
end,
waterStatIds,
period,
waterUnits,
["sum"]
)
: Promise.resolve({});
let statsCompare;
let startCompare;
let endCompare;
let _energyStatsCompare = Promise.resolve({});
let _waterStatsCompare = Promise.resolve({});
if (compare) {
if (dayDifference > 27 && dayDifference < 32) {
// When comparing a month, we want to start at the begining of the month
@@ -443,38 +441,38 @@ const getEnergyData = async (
const compareStartMinHour = addHours(startCompare, -1);
endCompare = addMilliseconds(start, -1);
statsCompare = {
...(energyStatIds.length
? await fetchStatistics(
hass!,
compareStartMinHour,
endCompare,
energyStatIds,
period,
energyUnits,
["sum"]
)
: {}),
...(waterStatIds.length
? await fetchStatistics(
hass!,
compareStartMinHour,
endCompare,
waterStatIds,
period,
waterUnits,
["sum"]
)
: {}),
};
if (energyStatIds.length) {
_energyStatsCompare = fetchStatistics(
hass!,
compareStartMinHour,
endCompare,
energyStatIds,
period,
energyUnits,
["sum"]
);
}
if (waterStatIds.length) {
_waterStatsCompare = fetchStatistics(
hass!,
compareStartMinHour,
endCompare,
waterStatIds,
period,
waterUnits,
["sum"]
);
}
}
let fossilEnergyConsumption: FossilEnergyConsumption | undefined;
let fossilEnergyConsumptionCompare: FossilEnergyConsumption | undefined;
let _fossilEnergyConsumption:
| Promise<undefined>
| Promise<FossilEnergyConsumption> = Promise.resolve(undefined);
let _fossilEnergyConsumptionCompare:
| Promise<undefined>
| Promise<FossilEnergyConsumption> = Promise.resolve(undefined);
if (co2SignalEntity !== undefined) {
fossilEnergyConsumption = await getFossilEnergyConsumption(
_fossilEnergyConsumption = getFossilEnergyConsumption(
hass!,
start,
consumptionStatIDs,
@@ -483,7 +481,7 @@ const getEnergyData = async (
dayDifference > 35 ? "month" : dayDifference > 2 ? "day" : "hour"
);
if (compare) {
fossilEnergyConsumptionCompare = await getFossilEnergyConsumption(
_fossilEnergyConsumptionCompare = getFossilEnergyConsumption(
hass!,
startCompare,
consumptionStatIDs,
@@ -494,6 +492,37 @@ const getEnergyData = async (
}
}
const statsMetadata: Record<string, StatisticsMetaData> = {};
const _getStatisticMetadata: Promise<StatisticsMetaData[]> = allStatIDs.length
? getStatisticMetadata(hass, allStatIDs)
: Promise.resolve([]);
const [
energyStats,
waterStats,
energyStatsCompare,
waterStatsCompare,
statsMetadataArray,
fossilEnergyConsumption,
fossilEnergyConsumptionCompare,
] = await Promise.all([
_energyStats,
_waterStats,
_energyStatsCompare,
_waterStatsCompare,
_getStatisticMetadata,
_fossilEnergyConsumption,
_fossilEnergyConsumptionCompare,
]);
const stats = { ...energyStats, ...waterStats };
if (compare) {
statsCompare = { ...energyStatsCompare, ...waterStatsCompare };
}
if (allStatIDs.length) {
statsMetadataArray.forEach((x) => {
statsMetadata[x.statistic_id] = x;
});
}
Object.values(stats).forEach((stat) => {
// if the start of the first value is after the requested period, we have the first data point, and should add a zero point
if (stat.length && new Date(stat[0].start) > startMinHour) {
@@ -507,12 +536,6 @@ const getEnergyData = async (
}
});
const statsMetadataArray = await getStatisticMetadata(hass, allStatIDs);
const statsMetadata: Record<string, StatisticsMetaData> = {};
statsMetadataArray.forEach((x) => {
statsMetadata[x.statistic_id] = x;
});
const data: EnergyData = {
start,
end,

View File

@@ -10,13 +10,13 @@ export interface ThreadRouter {
}
export interface ThreadDataSet {
created: string;
dataset_id: string;
preferred: boolean;
source: string;
created;
dataset_id;
extended_pan_id;
network_name: string;
extended_pan_id?: string;
pan_id?: string;
pan_id;
preferred: boolean;
source;
}
export interface ThreadRouterDiscoveryEvent {
@@ -61,29 +61,3 @@ export const listThreadDataSets = (
hass.callWS({
type: "thread/list_datasets",
});
export const getThreadDataSetTLV = (
hass: HomeAssistant,
dataset_id: string
): Promise<{ tlv: string }> =>
hass.callWS({ type: "thread/get_dataset_tlv", dataset_id });
export const addThreadDataSet = (
hass: HomeAssistant,
source: string,
tlv: string
): Promise<void> =>
hass.callWS({
type: "thread/add_dataset_tlv",
source,
tlv,
});
export const removeThreadDataSet = (
hass: HomeAssistant,
dataset_id: string
): Promise<void> =>
hass.callWS({
type: "thread/delete_dataset",
dataset_id,
});

View File

@@ -7,7 +7,6 @@ import { fireEvent } from "../../common/dom/fire_event";
import { shouldHandleRequestSelectedEvent } from "../../common/mwc/handle-request-selected-event";
import "../../components/ha-circular-progress";
import { createCloseHeading } from "../../components/ha-dialog";
import "../../components/ha-expansion-panel";
import "../../components/ha-list-item";
import {
extractApiErrorMessage,
@@ -107,7 +106,6 @@ class DialogRestart extends LitElement {
<ha-list-item
graphic="avatar"
twoline
multiline-secondary
hasMeta
@request-selected=${this._reload}
>
@@ -130,7 +128,6 @@ class DialogRestart extends LitElement {
<ha-list-item
graphic="avatar"
twoline
multiline-secondary
hasMeta
@request-selected=${this._restart}
>
@@ -146,62 +143,57 @@ class DialogRestart extends LitElement {
)}
</span>
</ha-list-item>
${showRebootShutdown
? html`
<div class="divider"></div>
<p class="section">
${this.hass.localize(
"ui.dialogs.restart.advanced_options"
)}
</p>
<ha-list-item
graphic="avatar"
twoline
hasMeta
@request-selected=${this._hostReboot}
>
<div slot="graphic" class="icon-background reboot">
<ha-svg-icon .path=${mdiPowerCycle}></ha-svg-icon>
</div>
<span>
${this.hass.localize(
"ui.dialogs.restart.reboot.title"
)}
</span>
<span slot="secondary">
${this.hass.localize(
"ui.dialogs.restart.reboot.description"
)}
</span>
</ha-list-item>
<ha-list-item
graphic="avatar"
twoline
hasMeta
@request-selected=${this._hostShutdown}
>
<div slot="graphic" class="icon-background shutdown">
<ha-svg-icon .path=${mdiPower}></ha-svg-icon>
</div>
<span>
${this.hass.localize(
"ui.dialogs.restart.shutdown.title"
)}
</span>
<span slot="secondary">
${this.hass.localize(
"ui.dialogs.restart.shutdown.description"
)}
</span>
</ha-list-item>
`
: null}
</mwc-list>
${showRebootShutdown
? html`
<ha-expansion-panel
.header=${this.hass.localize(
"ui.dialogs.restart.advanced_options"
)}
>
<mwc-list>
<ha-list-item
graphic="avatar"
twoline
multiline-secondary
hasMeta
@request-selected=${this._hostReboot}
>
<div slot="graphic" class="icon-background reboot">
<ha-svg-icon .path=${mdiPowerCycle}></ha-svg-icon>
</div>
<span>
${this.hass.localize(
"ui.dialogs.restart.reboot.title"
)}
</span>
<span slot="secondary">
${this.hass.localize(
"ui.dialogs.restart.reboot.description"
)}
</span>
</ha-list-item>
<ha-list-item
graphic="avatar"
twoline
multiline-secondary
hasMeta
@request-selected=${this._hostShutdown}
>
<div slot="graphic" class="icon-background shutdown">
<ha-svg-icon .path=${mdiPower}></ha-svg-icon>
</div>
<span>
${this.hass.localize(
"ui.dialogs.restart.shutdown.title"
)}
</span>
<span slot="secondary">
${this.hass.localize(
"ui.dialogs.restart.shutdown.description"
)}
</span>
</ha-list-item>
</mwc-list>
</ha-expansion-panel>
`
: null}
`}
</ha-dialog>
`;
@@ -348,23 +340,6 @@ class DialogRestart extends LitElement {
ha-dialog {
--dialog-content-padding: 0;
}
@media all and (min-width: 550px) {
ha-dialog {
--mdc-dialog-min-width: 500px;
--mdc-dialog-max-width: 500px;
}
}
ha-expansion-panel {
border-top: 1px solid var(--divider-color);
margin-bottom: 10px;
box-shadow: none;
--expansion-panel-content-padding: 0;
--expansion-panel-summary-padding: 0
var(--mdc-list-side-padding, 20px);
--ha-card-border-radius: 0;
}
.icon-background {
border-radius: 50%;
color: #fff;

View File

@@ -288,8 +288,7 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
}
private precisionLabel(precision?: number, stateValue?: string) {
const stateValueNumber = Number(stateValue);
const value = !isNaN(stateValueNumber) ? stateValueNumber : 0;
const value = stateValue ?? 0;
return formatNumber(value, this.hass.locale, {
minimumFractionDigits: precision,
maximumFractionDigits: precision,

View File

@@ -278,7 +278,7 @@ class HaConfigHardware extends SubscribeMixin(LitElement) {
`
: ""}
<div class="content">
${boardName || isComponentLoaded(this.hass, "hassio")
${boardName
? html`
<ha-card outlined>
<div class="card-content">
@@ -293,9 +293,7 @@ class HaConfigHardware extends SubscribeMixin(LitElement) {
: ""}
<span class="primary-text">
${boardName ||
this.hass.localize(
"ui.panel.config.hardware.generic_hardware"
)}
this.hass.localize("ui.panel.config.hardware.board")}
</span>
${boardId
? html`

View File

@@ -1,10 +1,5 @@
import "@material/mwc-button";
import {
mdiDeleteOutline,
mdiDevices,
mdiDotsVertical,
mdiInformationOutline,
} from "@mdi/js";
import { mdiDevices, mdiDotsVertical, mdiInformationOutline } from "@mdi/js";
import { css, html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
@@ -16,19 +11,13 @@ import { getSignedPath } from "../../../../../data/auth";
import { getConfigEntryDiagnosticsDownloadUrl } from "../../../../../data/diagnostics";
import { getOTBRInfo } from "../../../../../data/otbr";
import {
addThreadDataSet,
listThreadDataSets,
removeThreadDataSet,
subscribeDiscoverThreadRouters,
ThreadDataSet,
ThreadRouter,
} from "../../../../../data/thread";
import { showConfigFlowDialog } from "../../../../../dialogs/config-flow/show-dialog-config-flow";
import {
showAlertDialog,
showConfirmationDialog,
showPromptDialog,
} from "../../../../../dialogs/generic/show-dialog-box";
import { showAlertDialog } from "../../../../../dialogs/generic/show-dialog-box";
import "../../../../../layouts/hass-subpage";
import { SubscribeMixin } from "../../../../../mixins/subscribe-mixin";
import { haStyle } from "../../../../../resources/styles";
@@ -77,11 +66,6 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
)}
</mwc-list-item>
</a>
<mwc-list-item @click=${this._addTLV}
>${this.hass.localize(
"ui.panel.config.thread.add_dataset_from_tlv"
)}</mwc-list-item
>
<mwc-list-item @click=${this._addOTBR}
>${this.hass.localize(
"ui.panel.config.thread.add_open_thread_border_router"
@@ -124,20 +108,11 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
return html`<ha-card>
<div class="card-header">
${network.name}${network.dataset
? html`<div>
<ha-icon-button
.networkDataset=${network.dataset}
.path=${mdiInformationOutline}
@click=${this._showDatasetInfo}
></ha-icon-button
>${!network.dataset.preferred && !network.routers?.length
? html`<ha-icon-button
.networkDataset=${network.dataset}
.path=${mdiDeleteOutline}
@click=${this._removeDataset}
></ha-icon-button>`
: ""}
</div>`
? html`<ha-icon-button
.networkDataset=${network.dataset}
.path=${mdiInformationOutline}
@click=${this._showDatasetInfo}
></ha-icon-button>`
: ""}
</div>
${network.routers?.length
@@ -179,10 +154,7 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
const dataset = (ev.currentTarget as any).networkDataset as ThreadDataSet;
if (isComponentLoaded(this.hass, "otbr")) {
const otbrInfo = await getOTBRInfo(this.hass);
if (
dataset.extended_pan_id &&
otbrInfo.active_dataset_tlvs?.includes(dataset.extended_pan_id)
) {
if (otbrInfo.active_dataset_tlvs.includes(dataset.extended_pan_id)) {
showAlertDialog(this, {
title: dataset.network_name,
text: html`Network name: ${dataset.network_name}<br />
@@ -295,57 +267,6 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
});
}
private async _addTLV() {
const tlv = await showPromptDialog(this, {
title: this.hass.localize("ui.panel.config.thread.add_dataset"),
inputLabel: this.hass.localize(
"ui.panel.config.thread.add_dataset_label"
),
confirmText: this.hass.localize(
"ui.panel.config.thread.add_dataset_button"
),
});
if (!tlv) {
return;
}
try {
await addThreadDataSet(this.hass, "manual", tlv);
} catch (err: any) {
showAlertDialog(this, {
title: "Error",
text: err.message || err,
});
}
this._refresh();
}
private async _removeDataset(ev: Event) {
const dataset = (ev.currentTarget as any).networkDataset as ThreadDataSet;
const confirm = await showConfirmationDialog(this, {
title: this.hass.localize(
"ui.panel.config.thread.confirm_delete_dataset",
{ name: dataset.network_name }
),
text: this.hass.localize(
"ui.panel.config.thread.confirm_delete_dataset_text"
),
destructive: true,
confirmText: this.hass.localize("ui.common.delete"),
});
if (!confirm) {
return;
}
try {
await removeThreadDataSet(this.hass, dataset.dataset_id);
} catch (err: any) {
showAlertDialog(this, {
title: "Error",
text: err.message || err,
});
}
this._refresh();
}
static styles = [
haStyle,
css`

View File

@@ -72,7 +72,7 @@ class DialogZHAReconfigureDevice extends LitElement {
this.hass,
this.hass.localize(`ui.dialogs.zha_reconfigure_device.heading`) +
": " +
(this._params.device.user_given_name || this._params.device.name)
(this._params?.device.user_given_name || this._params?.device.name)
)}
>
${!this._status

View File

@@ -183,7 +183,7 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
// new format
let segments = this._config!.segments;
if (segments) {
segments = [...segments].sort((a, b) => a.from - b.from);
segments = [...segments].sort((a, b) => a?.from - b?.from);
for (let i = 0; i < segments.length; i++) {
const segment = segments[i];

View File

@@ -1038,9 +1038,9 @@
"restart": {
"title": "Restart Home Assistant",
"description": "Interrupts all running automations and scripts.",
"confirm_title": "Restart Home Assistant?",
"confirm_title": "Restart?",
"confirm_description": "This will interrupt all running automations and scripts.",
"confirm_action": "Restart",
"confirm_action": "Restart Home Assistant",
"failed": "Failed to restart Home Assistant"
},
"reboot": {
@@ -1801,7 +1801,7 @@
"reboot_moved_link": "Go to system page.",
"processor": "Processor",
"memory": "Memory",
"generic_hardware": "Generic Hardware",
"board": "Board",
"documentation": "Documentation",
"configure": "Configure",
"documentation_description": "Find extra information about your device",
@@ -3288,12 +3288,6 @@
"my_network": "My network",
"no_preferred_network": "You don't have a preferred network yet.",
"add_open_thread_border_router": "Add an OpenThread border router",
"add_dataset_from_tlv": "Add dataset from TLV",
"add_dataset": "Add Thread dataset",
"add_dataset_label": "Operational dataset TLV",
"add_dataset_button": "Add dataset",
"confirm_delete_dataset": "Delete {name} dataset?",
"confirm_delete_dataset_text": "This network will be removed from Home Assistant.",
"no_border_routers": "No border routers found",
"border_routers": "{count} border {count, plural,\n one {router}\n other {routers}\n}",
"managed_by_home_assistant": "Managed by Home Assistant",

View File

@@ -1457,9 +1457,9 @@ __metadata:
languageName: node
linkType: hard
"@eslint/eslintrc@npm:^2.0.0":
version: 2.0.0
resolution: "@eslint/eslintrc@npm:2.0.0"
"@eslint/eslintrc@npm:^1.4.1":
version: 1.4.1
resolution: "@eslint/eslintrc@npm:1.4.1"
dependencies:
ajv: ^6.12.4
debug: ^4.3.2
@@ -1470,14 +1470,7 @@ __metadata:
js-yaml: ^4.1.0
minimatch: ^3.1.2
strip-json-comments: ^3.1.1
checksum: 31119c8ca06723d80384f18f5c78e0530d8e6306ad36379868650131a8b10dd7cffd7aff79a5deb3a2e9933660823052623d268532bae9538ded53d5b19a69a6
languageName: node
linkType: hard
"@eslint/js@npm:8.35.0":
version: 8.35.0
resolution: "@eslint/js@npm:8.35.0"
checksum: 6687ceff659a6d617e37823f809dc9c4b096535961a81acead27d26b1a51a4cf608a5e59d831ddd57f24f6f8bb99340a4a0e19f9c99b390fbb4b275f51ed5f5e
checksum: cd3e5a8683db604739938b1c1c8b77927dc04fce3e28e0c88e7f2cd4900b89466baf83dfbad76b2b9e4d2746abdd00dd3f9da544d3e311633d8693f327d04cd7
languageName: node
linkType: hard
@@ -6860,18 +6853,6 @@ __metadata:
languageName: node
linkType: hard
"compression-webpack-plugin@npm:^10.0.0":
version: 10.0.0
resolution: "compression-webpack-plugin@npm:10.0.0"
dependencies:
schema-utils: ^4.0.0
serialize-javascript: ^6.0.0
peerDependencies:
webpack: ^5.1.0
checksum: 2ac9079b7ab87141639c62ddbb2820a06f105198e27ef4c3860da3186bdbefc00d1e206969833ce7a4b7b26161ddbec7b8d20d30f9f9c1d494818b9b86f0d5cc
languageName: node
linkType: hard
"compression@npm:1.7.3":
version: 1.7.3
resolution: "compression@npm:1.7.3"
@@ -8092,12 +8073,11 @@ __metadata:
languageName: node
linkType: hard
"eslint@npm:^8.35.0":
version: 8.35.0
resolution: "eslint@npm:8.35.0"
"eslint@npm:^8.34.0":
version: 8.34.0
resolution: "eslint@npm:8.34.0"
dependencies:
"@eslint/eslintrc": ^2.0.0
"@eslint/js": 8.35.0
"@eslint/eslintrc": ^1.4.1
"@humanwhocodes/config-array": ^0.11.8
"@humanwhocodes/module-importer": ^1.0.1
"@nodelib/fs.walk": ^1.2.8
@@ -8111,7 +8091,7 @@ __metadata:
eslint-utils: ^3.0.0
eslint-visitor-keys: ^3.3.0
espree: ^9.4.0
esquery: ^1.4.2
esquery: ^1.4.0
esutils: ^2.0.2
fast-deep-equal: ^3.1.3
file-entry-cache: ^6.0.1
@@ -8138,7 +8118,7 @@ __metadata:
text-table: ^0.2.0
bin:
eslint: bin/eslint.js
checksum: 6212173691d90b1bc94dd3d640e1f210374b30c3905fc0a15e501cf71c6ca52aa3d80ea7a9a245adaaed26d6019169e01fb6881b3f2885b188d37069c749308c
checksum: 4e13e9eb05ac2248efbb6acae0b2325091235d5c47ba91a4775c7d6760778cbcd358a773ebd42f4629d2ad89e27c02f5d66eb1f737d75d9f5fc411454f83b2e5
languageName: node
linkType: hard
@@ -8163,12 +8143,12 @@ __metadata:
languageName: node
linkType: hard
"esquery@npm:^1.4.2":
version: 1.4.2
resolution: "esquery@npm:1.4.2"
"esquery@npm:^1.4.0":
version: 1.4.0
resolution: "esquery@npm:1.4.0"
dependencies:
estraverse: ^5.1.0
checksum: 2f4ad89c5aafaca61cc2c15e256190f0d6deb4791cae6552d3cb4b1eb8867958cdf27a56aaa3272ff17435e3eaa19ee0d4129fac336ca6373d7354d7b5da7966
checksum: a0807e17abd7fbe5fbd4fab673038d6d8a50675cdae6b04fbaa520c34581be0c5fa24582990e8acd8854f671dd291c78bb2efb9e0ed5b62f33bac4f9cf820210
languageName: node
linkType: hard
@@ -9638,7 +9618,6 @@ fsevents@~2.3.2:
chai: ^4.3.7
chart.js: ^3.3.2
comlink: ^4.4.1
compression-webpack-plugin: ^10.0.0
core-js: ^3.28.0
cropperjs: ^1.5.13
date-fns: ^2.29.3
@@ -9646,7 +9625,7 @@ fsevents@~2.3.2:
deep-clone-simple: ^1.1.1
deep-freeze: ^0.0.1
del: ^7.0.0
eslint: ^8.35.0
eslint: ^8.34.0
eslint-config-airbnb-base: ^15.0.0
eslint-config-airbnb-typescript: ^17.0.0
eslint-config-prettier: ^8.6.0
@@ -9713,7 +9692,7 @@ fsevents@~2.3.2:
sortablejs: ^1.15.0
source-map-url: ^0.4.1
superstruct: ^1.0.3
systemjs: ^6.14.0
systemjs: ^6.13.0
tar: ^6.1.13
terser-webpack-plugin: ^5.3.6
tinykeys: ^1.4.0
@@ -9725,7 +9704,7 @@ fsevents@~2.3.2:
vinyl-buffer: ^1.0.1
vinyl-source-stream: ^2.0.0
vis-data: ^7.1.4
vis-network: ^9.1.4
vis-network: ^9.1.2
vue: ^2.7.14
vue2-daterange-picker: ^0.6.8
webpack: =5.72.1
@@ -9733,7 +9712,7 @@ fsevents@~2.3.2:
webpack-dev-server: ^4.11.1
webpack-manifest-plugin: ^5.0.0
webpackbar: ^5.0.2
weekstart: ^2.0.0
weekstart: ^1.1.0
workbox-build: ^6.5.4
workbox-cacheable-response: ^6.5.4
workbox-core: ^6.5.4
@@ -15069,10 +15048,10 @@ fsevents@~2.3.2:
languageName: node
linkType: hard
"systemjs@npm:^6.14.0":
version: 6.14.0
resolution: "systemjs@npm:6.14.0"
checksum: df82c38a5f23012dfee693e97dacfc48eef787a80cc41bc3bd594567ba9441c6392978841c6555d88df7451a2e22c8df9fcbf9c88c78f9f9b9027393ac38d84b
"systemjs@npm:^6.13.0":
version: 6.13.0
resolution: "systemjs@npm:6.13.0"
checksum: df8d7374249778291f3a85278fdb3e1b9d81ac07767b0a7f9edeca0ee45d847c19bceb01522c817605e2908d32a4fcfed6bacd707bfb7bd577774ab900d3707d
languageName: node
linkType: hard
@@ -16086,18 +16065,18 @@ typescript@^3.8.3:
languageName: node
linkType: hard
"vis-network@npm:^9.1.4":
version: 9.1.4
resolution: "vis-network@npm:9.1.4"
"vis-network@npm:^9.1.2":
version: 9.1.2
resolution: "vis-network@npm:9.1.2"
peerDependencies:
"@egjs/hammerjs": ^2.0.0
component-emitter: ^1.3.0
keycharm: ^0.2.0 || ^0.3.0 || ^0.4.0
timsort: ^0.3.0
uuid: ^3.4.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
uuid: ^3.4.0 || ^7.0.0 || ^8.0.0
vis-data: ^7.0.0
vis-util: ^5.0.1
checksum: 1c3ce02d251bf04ce3284301d597ee2630ad2a76de6c168c78df4dccf8ec4f4d058d67a1d78d507b763ff909d04d0d1afadcb3c3daf664e5090720b25a00aa2f
checksum: 763bee104c9d69f6b229d10675f712f824568f28dd13540d35d0f1f1fc58fcb9dc27cc12da80f6e874076a7cb75793d168b49c3c7783f8cb06f57931d9edfe0e
languageName: node
linkType: hard
@@ -16440,10 +16419,10 @@ typescript@^3.8.3:
languageName: node
linkType: hard
"weekstart@npm:^2.0.0":
version: 2.0.0
resolution: "weekstart@npm:2.0.0"
checksum: 9a27d7fe30d847997d50006c814e68ad9b105858a43029b2312bf5757dd49839865a64ad28345d2dcb1b9f25b72f0de81e23d8db50362890b253486defff69e6
"weekstart@npm:^1.1.0":
version: 1.1.0
resolution: "weekstart@npm:1.1.0"
checksum: afce96e0b95809a30f00fa02b13a0927324d9f76b9c10ce6b3de9bbd5926615156f8a0526c63e2bd1cabdc8ec3da68b8df8d6608b6364ded11b5da300a8cfcb4
languageName: node
linkType: hard