diff --git a/pyproject.toml b/pyproject.toml index 2eec5c49cb..0a5a6fb847 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20250509.0" +version = "20250516.0" license = "Apache-2.0" license-files = ["LICENSE*"] description = "The Home Assistant frontend" diff --git a/src/components/entity/ha-entity-combo-box.ts b/src/components/entity/ha-entity-combo-box.ts index db18168c3a..5d31baa43b 100644 --- a/src/components/entity/ha-entity-combo-box.ts +++ b/src/components/entity/ha-entity-combo-box.ts @@ -178,7 +178,9 @@ export class HaEntityComboBox extends LitElement { : nothing} ${item.domain_name && !showEntityId ? html` -
${item.domain_name}
+
+ ${item.domain_name} +
` : nothing} @@ -408,7 +410,9 @@ export class HaEntityComboBox extends LitElement { protected render(): TemplateResult { return html` ; - } ->; + }; +}>; interface SystemHealthEventInitial { type: "initial"; diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index 68833ad0bf..f27ff5b428 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -9,50 +9,50 @@ import { mdiReload, mdiServerNetwork, } from "@mdi/js"; +import Fuse from "fuse.js"; import type { TemplateResult } from "lit"; import { css, html, LitElement, nothing } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { ifDefined } from "lit/directives/if-defined"; import { styleMap } from "lit/directives/style-map"; import memoizeOne from "memoize-one"; -import Fuse from "fuse.js"; import { canShowPage } from "../../common/config/can_show_page"; import { componentsWithService } from "../../common/config/components_with_service"; import { isComponentLoaded } from "../../common/config/is_component_loaded"; import { fireEvent } from "../../common/dom/fire_event"; +import { computeAreaName } from "../../common/entity/compute_area_name"; import { computeDeviceName, computeDeviceNameDisplay, } from "../../common/entity/compute_device_name"; +import { computeDomain } from "../../common/entity/compute_domain"; +import { computeEntityName } from "../../common/entity/compute_entity_name"; +import { computeStateName } from "../../common/entity/compute_state_name"; +import { getEntityContext } from "../../common/entity/context/get_entity_context"; import { navigate } from "../../common/navigate"; import { caseInsensitiveStringCompare } from "../../common/string/compare"; import type { ScorableTextItem } from "../../common/string/filter/sequence-matching"; +import { computeRTL } from "../../common/util/compute_rtl"; import { debounce } from "../../common/util/debounce"; import "../../components/ha-icon-button"; import "../../components/ha-label"; import "../../components/ha-list"; +import "../../components/ha-md-list-item"; import "../../components/ha-spinner"; import "../../components/ha-textfield"; import "../../components/ha-tip"; -import "../../components/ha-md-list-item"; import { fetchHassioAddonsInfo } from "../../data/hassio/addon"; import { domainToName } from "../../data/integration"; import { getPanelNameTranslationKey } from "../../data/panel"; import type { PageNavigation } from "../../layouts/hass-tabs-subpage"; import { configSections } from "../../panels/config/ha-panel-config"; +import { HaFuse } from "../../resources/fuse"; import { haStyleDialog, haStyleScrollbar } from "../../resources/styles"; import { loadVirtualizer } from "../../resources/virtualizer"; import type { HomeAssistant } from "../../types"; import { showConfirmationDialog } from "../generic/show-dialog-box"; import { showShortcutsDialog } from "../shortcuts/show-shortcuts-dialog"; import { QuickBarMode, type QuickBarParams } from "./show-dialog-quick-bar"; -import { getEntityContext } from "../../common/entity/context/get_entity_context"; -import { computeEntityName } from "../../common/entity/compute_entity_name"; -import { computeAreaName } from "../../common/entity/compute_area_name"; -import { computeRTL } from "../../common/util/compute_rtl"; -import { computeDomain } from "../../common/entity/compute_domain"; -import { computeStateName } from "../../common/entity/compute_state_name"; -import { HaFuse } from "../../resources/fuse"; interface QuickBarItem extends ScorableTextItem { primaryText: string; @@ -152,11 +152,6 @@ export class QuickBar extends LitElement { } } - protected firstUpdated(changedProps) { - super.firstUpdated(changedProps); - this.hass.loadBackendTranslation("title"); - } - private _getItems = memoizeOne( ( mode: QuickBarMode, @@ -304,7 +299,8 @@ export class QuickBar extends LitElement { } else if (this._mode === QuickBarMode.Device) { this._deviceItems = this._deviceItems || this._generateDeviceItems(); } else { - this._entityItems = this._entityItems || this._generateEntityItems(); + this._entityItems = + this._entityItems || (await this._generateEntityItems()); } } @@ -386,7 +382,7 @@ export class QuickBar extends LitElement { ` : nothing} ${item.translatedDomain && !showEntityId - ? html`
+ ? html`
${item.translatedDomain}
` : nothing} @@ -581,9 +577,11 @@ export class QuickBar extends LitElement { ); } - private _generateEntityItems(): EntityItem[] { + private async _generateEntityItems(): Promise { const isRTL = computeRTL(this.hass); + await this.hass.loadBackendTranslation("title"); + return Object.keys(this.hass.states) .map((entityId) => { const stateObj = this.hass.states[entityId]; @@ -1027,7 +1025,7 @@ export class QuickBar extends LitElement { font-size: var(--ha-font-size-xs); } - ha-md-list-item [slot="trailing-supporting-text"] { + ha-md-list-item .domain { font-size: var(--ha-font-size-s); font-weight: var(--ha-font-weight-normal); line-height: var(--ha-line-height-normal); diff --git a/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts b/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts index 1b2a0e88a0..a9f1a8d771 100644 --- a/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts +++ b/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts @@ -57,16 +57,22 @@ export class HaVoiceCommandDialog extends LitElement { public async showDialog( params: Required ): Promise { + await this._loadPipelines(); + const pipelinesIds = this._pipelines?.map((pipeline) => pipeline.id) || []; if ( params.pipeline_id === "preferred" || (params.pipeline_id === "last_used" && !this._pipelineId) ) { - await this._loadPipelines(); this._pipelineId = this._preferredPipeline; } else if (!["last_used", "preferred"].includes(params.pipeline_id)) { this._pipelineId = params.pipeline_id; } + // If the pipeline id is not in the list of pipelines, set it to preferred + if (this._pipelineId && !pipelinesIds.includes(this._pipelineId)) { + this._pipelineId = this._preferredPipeline; + } + this._startListening = params.start_listening; this._opened = true; } diff --git a/src/panels/config/automation/action/types/ha-automation-action-choose.ts b/src/panels/config/automation/action/types/ha-automation-action-choose.ts index 07498c4606..2c193cc024 100644 --- a/src/panels/config/automation/action/types/ha-automation-action-choose.ts +++ b/src/panels/config/automation/action/types/ha-automation-action-choose.ts @@ -18,6 +18,8 @@ export class HaChooseAction extends LitElement implements ActionElement { @property({ attribute: false }) public action!: ChooseAction; + @property({ type: Boolean }) public narrow = false; + @state() private _showDefault = false; public static get defaultConfig(): ChooseAction { @@ -35,6 +37,7 @@ export class HaChooseAction extends LitElement implements ActionElement { .disabled=${this.disabled} @value-changed=${this._optionsChanged} .hass=${this.hass} + .narrow=${this.narrow} > ${this._showDefault || action.default @@ -49,6 +52,7 @@ export class HaChooseAction extends LitElement implements ActionElement { .disabled=${this.disabled} @value-changed=${this._defaultChanged} .hass=${this.hass} + .narrow=${this.narrow} > ` : html` diff --git a/src/panels/config/automation/action/types/ha-automation-action-if.ts b/src/panels/config/automation/action/types/ha-automation-action-if.ts index 2d7b8f1ecf..3b1eb99120 100644 --- a/src/panels/config/automation/action/types/ha-automation-action-if.ts +++ b/src/panels/config/automation/action/types/ha-automation-action-if.ts @@ -18,6 +18,8 @@ export class HaIfAction extends LitElement implements ActionElement { @property({ attribute: false }) public action!: IfAction; + @property({ type: Boolean }) public narrow = false; + @state() private _showElse = false; public static get defaultConfig(): IfAction { @@ -41,6 +43,7 @@ export class HaIfAction extends LitElement implements ActionElement { .disabled=${this.disabled} @value-changed=${this._ifChanged} .hass=${this.hass} + .narrow=${this.narrow} >

@@ -53,6 +56,7 @@ export class HaIfAction extends LitElement implements ActionElement { .disabled=${this.disabled} @value-changed=${this._thenChanged} .hass=${this.hass} + .narrow=${this.narrow} > ${this._showElse || action.else ? html` @@ -66,6 +70,7 @@ export class HaIfAction extends LitElement implements ActionElement { .disabled=${this.disabled} @value-changed=${this._elseChanged} .hass=${this.hass} + .narrow=${this.narrow} > ` : html` diff --git a/src/panels/config/info/ha-config-info.ts b/src/panels/config/info/ha-config-info.ts index d58f4a858e..cb2b7fbf23 100644 --- a/src/panels/config/info/ha-config-info.ts +++ b/src/panels/config/info/ha-config-info.ts @@ -29,6 +29,7 @@ import { mdiHomeAssistant } from "../../../resources/home-assistant-logo-svg"; import { haStyle } from "../../../resources/styles"; import type { HomeAssistant, Route } from "../../../types"; import { documentationUrl } from "../../../util/documentation-url"; +import { subscribeSystemHealthInfo } from "../../../data/system_health"; const JS_TYPE = __BUILD__; const JS_VERSION = __VERSION__; @@ -99,6 +100,8 @@ class HaConfigInfo extends LitElement { @state() private _hassioInfo?: HassioInfo; + @state() private _installationMethod?: string; + protected render(): TemplateResult { const hass = this.hass; const customUiList: { name: string; url: string; version: string }[] = @@ -127,6 +130,14 @@ class HaConfigInfo extends LitElement {

Home Assistant

    +
  • + ${this.hass.localize( + `ui.panel.config.info.installation_method` + )} + ${this._installationMethod || "…"} +
  • Core ${hass.connection.haVersion} @@ -249,6 +260,13 @@ class HaConfigInfo extends LitElement { if (isComponentLoaded(this.hass, "hassio")) { this._loadSupervisorInfo(); } + + const unsubSystemHealth = subscribeSystemHealthInfo(this.hass, (info) => { + if (info?.homeassistant) { + this._installationMethod = info.homeassistant.info.installation_type; + unsubSystemHealth.then((unsub) => unsub()); + } + }); } private async _loadSupervisorInfo(): Promise { diff --git a/src/panels/config/repairs/dialog-system-information.ts b/src/panels/config/repairs/dialog-system-information.ts index b9666b0c57..a556d96ce9 100644 --- a/src/panels/config/repairs/dialog-system-information.ts +++ b/src/panels/config/repairs/dialog-system-information.ts @@ -301,7 +301,7 @@ class DialogSystemInformation extends LitElement { } else { const domains = Object.keys(this._systemInfo).sort(sortKeys); for (const domain of domains) { - const domainInfo = this._systemInfo[domain]; + const domainInfo = this._systemInfo[domain]!; const keys: TemplateResult[] = []; for (const key of Object.keys(domainInfo.info)) { @@ -387,7 +387,7 @@ class DialogSystemInformation extends LitElement { const domainParts: string[] = []; for (const domain of Object.keys(this._systemInfo!).sort(sortKeys)) { - const domainInfo = this._systemInfo![domain]; + const domainInfo = this._systemInfo![domain]!; let first = true; const parts = [ `${ diff --git a/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts index fc987b3300..708514d836 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts @@ -244,7 +244,10 @@ export class HuiEnergyDevicesGraphCard chartData.sort((a: any, b: any) => b.value[0] - a.value[0]); - chartData.length = this._config?.max_devices || chartData.length; + chartData.length = Math.min( + this._config?.max_devices || Infinity, + chartData.length + ); this._chartData = datasets; await this.updateComplete; diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts index e2e5aebd4e..ed1a507966 100644 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts @@ -110,11 +110,7 @@ export class HuiDialogEditCard } protected updated(changedProps: PropertyValues): void { - if ( - !this._cardConfig || - this._documentationURL !== undefined || - !changedProps.has("_cardConfig") - ) { + if (!this._cardConfig || !changedProps.has("_cardConfig")) { return; } diff --git a/src/panels/lovelace/editor/get-dashboard-documentation-url.ts b/src/panels/lovelace/editor/get-dashboard-documentation-url.ts index 658e1f2cec..c4e66db8aa 100644 --- a/src/panels/lovelace/editor/get-dashboard-documentation-url.ts +++ b/src/panels/lovelace/editor/get-dashboard-documentation-url.ts @@ -7,6 +7,23 @@ import { import type { HomeAssistant } from "../../../types"; import { documentationUrl } from "../../../util/documentation-url"; +const NON_STANDARD_URLS = { + "energy-date-selection": "energy/#energy-date-picker", + "energy-usage-graph": "energy/#energy-usage-graph", + "energy-solar-graph": "energy/#solar-production-graph", + "energy-gas-graph": "energy/#gas-consumption-graph", + "energy-water-graph": "energy/#water-consumption-graph", + "energy-distribution": "energy/#energy-distribution", + "energy-sources-table": "energy/#energy-sources-table", + "energy-grid-neutrality-gauge": "energy/#grid-neutrality-gauge", + "energy-solar-consumed-gauge": "energy/#solar-consumed-gauge", + "energy-carbon-consumed-gauge": "energy/#carbon-consumed-gauge", + "energy-self-sufficiency-gauge": "energy/#self-sufficiency-gauge", + "energy-devices-graph": "energy/#devices-energy-graph", + "energy-devices-detail-graph": "energy/#detail-devices-energy-graph", + "energy-sankey": "energy/#sankey-energy-graph", +}; + export const getCardDocumentationURL = ( hass: HomeAssistant, type: string @@ -15,7 +32,7 @@ export const getCardDocumentationURL = ( return getCustomCardEntry(stripCustomPrefix(type))?.documentationURL; } - return `${documentationUrl(hass, "/dashboards/")}${type}`; + return `${documentationUrl(hass, "/dashboards/")}${NON_STANDARD_URLS[type] || type}`; }; export const getBadgeDocumentationURL = ( diff --git a/src/translations/en.json b/src/translations/en.json index 11f047653f..daa4acfb7f 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3110,6 +3110,7 @@ }, "info": { "caption": "About", + "installation_method": "Installation method", "copy_menu": "Copy menu", "copy_raw": "Raw text", "copy_github": "For GitHub",