From 962912c43ca77b0f12e35141bbe2fde6883a92fe Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 28 Feb 2024 21:51:21 +0100 Subject: [PATCH 01/35] Add allow changing type of empty views (#19912) --- src/panels/lovelace/editor/view-editor/hui-view-editor.ts | 8 ++++++-- src/translations/en.json | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/panels/lovelace/editor/view-editor/hui-view-editor.ts b/src/panels/lovelace/editor/view-editor/hui-view-editor.ts index d0c4f24d53..803cdea063 100644 --- a/src/panels/lovelace/editor/view-editor/hui-view-editor.ts +++ b/src/panels/lovelace/editor/view-editor/hui-view-editor.ts @@ -95,12 +95,16 @@ export class HuiViewEditor extends LitElement { : this._config.type || DEFAULT_VIEW_LAYOUT; } + private get _isEmpty(): boolean { + return !this._config.sections?.length && !this._config.cards?.length; + } + protected render() { if (!this.hass) { return nothing; } - const schema = this._schema(this.hass.localize, this._type, this.isNew); + const schema = this._schema(this.hass.localize, this._type, this._isEmpty); const data = { ...this._config, @@ -165,7 +169,7 @@ export class HuiViewEditor extends LitElement { "ui.panel.lovelace.editor.edit_view.subview_helper" ); case "type": - if (this.isNew) return undefined; + if (this._isEmpty) return undefined; return this._type === "sections" ? this.hass.localize( "ui.panel.lovelace.editor.edit_view.type_helper_others" diff --git a/src/translations/en.json b/src/translations/en.json index 24f63e86a3..c8c1b42c79 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -5112,7 +5112,7 @@ "select_users": "Select which users should see this view in the navigation" }, "type": "View type", - "type_helper_sections": "You can not change your view to use the 'sections' view type, because migration is not supported yet. Start from scratch with a new view if you want to experiment with the 'sections' view.", + "type_helper_sections": "You can not change your view to use the 'sections' view type because migration is not supported yet. Start from scratch with a new view if you want to experiment with the 'sections' view.", "type_helper_others": "You can not change your view to an other type because migration is not supported yet. Start from scratch with a new view if you want to use another view type.", "types": { From a34332b48dec3fef7d58c58d2295f23a5885f21e Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Thu, 29 Feb 2024 15:12:19 +0100 Subject: [PATCH 02/35] Fix section editing after disconnect/reconnect (#19917) * Fix section editing after disconnect/reconnect * Update src/components/ha-sortable.ts Co-authored-by: Bram Kragten --------- Co-authored-by: Bram Kragten --- src/components/ha-sortable.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/ha-sortable.ts b/src/components/ha-sortable.ts index 1c83eef950..fc885d71ea 100644 --- a/src/components/ha-sortable.ts +++ b/src/components/ha-sortable.ts @@ -82,6 +82,9 @@ export class HaSortable extends LitElement { public connectedCallback() { super.connectedCallback(); this._shouldBeDestroy = false; + if (this.hasUpdated) { + this.requestUpdate(); + } } protected createRenderRoot() { From ca7e257e9561e9b69f23136da6b534bcb93700e2 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 29 Feb 2024 16:44:43 +0100 Subject: [PATCH 03/35] Bumped version to 20240228.1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 15c83c13a4..a725ab6ed3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240228.0" +version = "20240228.1" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From 67d8765624efdb09c6e7a21103dd73a8bfc8be8f Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Fri, 1 Mar 2024 13:09:10 +0100 Subject: [PATCH 04/35] Add badges support to sections view (#19929) --- src/panels/lovelace/views/const.ts | 6 +----- src/panels/lovelace/views/hui-masonry-view.ts | 6 ------ src/panels/lovelace/views/hui-sections-view.ts | 13 ++++++++++++- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/panels/lovelace/views/const.ts b/src/panels/lovelace/views/const.ts index 5633f05bbc..fb68615fd8 100644 --- a/src/panels/lovelace/views/const.ts +++ b/src/panels/lovelace/views/const.ts @@ -2,8 +2,4 @@ export const DEFAULT_VIEW_LAYOUT = "masonry"; export const PANEL_VIEW_LAYOUT = "panel"; export const SIDEBAR_VIEW_LAYOUT = "sidebar"; export const SECTION_VIEW_LAYOUT = "sections"; -export const VIEWS_NO_BADGE_SUPPORT = [ - PANEL_VIEW_LAYOUT, - SIDEBAR_VIEW_LAYOUT, - SECTION_VIEW_LAYOUT, -]; +export const VIEWS_NO_BADGE_SUPPORT = [PANEL_VIEW_LAYOUT, SIDEBAR_VIEW_LAYOUT]; diff --git a/src/panels/lovelace/views/hui-masonry-view.ts b/src/panels/lovelace/views/hui-masonry-view.ts index bcc87214e3..c8e3047c2d 100644 --- a/src/panels/lovelace/views/hui-masonry-view.ts +++ b/src/panels/lovelace/views/hui-masonry-view.ts @@ -291,12 +291,6 @@ export class MasonryView extends LitElement implements LovelaceViewElement { padding-top: 4px; } - .badges { - margin: 8px 16px; - font-size: 85%; - text-align: center; - } - #columns { display: flex; flex-direction: row; diff --git a/src/panels/lovelace/views/hui-sections-view.ts b/src/panels/lovelace/views/hui-sections-view.ts index cbf5af8570..71c612808e 100644 --- a/src/panels/lovelace/views/hui-sections-view.ts +++ b/src/panels/lovelace/views/hui-sections-view.ts @@ -20,7 +20,7 @@ import { updateLovelaceContainer, } from "../editor/lovelace-path"; import { HuiSection } from "../sections/hui-section"; -import type { Lovelace } from "../types"; +import type { Lovelace, LovelaceBadge } from "../types"; @customElement("hui-sections-view") export class SectionsView extends LitElement implements LovelaceViewElement { @@ -34,6 +34,8 @@ export class SectionsView extends LitElement implements LovelaceViewElement { @property({ attribute: false }) public sections: HuiSection[] = []; + @property({ attribute: false }) public badges: LovelaceBadge[] = []; + @state() private _config?: LovelaceViewConfig; public setConfig(config: LovelaceViewConfig): void { @@ -57,6 +59,9 @@ export class SectionsView extends LitElement implements LovelaceViewElement { const editMode = this.lovelace.editMode; return html` + ${this.badges.length > 0 + ? html`
${this.badges}
` + : ""} Date: Fri, 1 Mar 2024 13:09:21 +0100 Subject: [PATCH 05/35] Use max column count instead of max width for section grid (#19932) --- .../lovelace/views/hui-sections-view.ts | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/panels/lovelace/views/hui-sections-view.ts b/src/panels/lovelace/views/hui-sections-view.ts index 71c612808e..2e2320fa54 100644 --- a/src/panels/lovelace/views/hui-sections-view.ts +++ b/src/panels/lovelace/views/hui-sections-view.ts @@ -73,8 +73,8 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
@@ -249,26 +249,28 @@ export class SectionsView extends LitElement implements LovelaceViewElement { } .container { + /* Inputs */ --grid-gap: 20px; - --grid-max-width: 1400px; - --grid-cell-max-width: 500px; - --grid-cell-min-width: 320px; + --grid-max-section-count: 4; + --grid-section-min-width: 320px; + + /* Calculated */ + --max-count: min(var(--section-count), var(--grid-max-section-count)); + --grid-max-width: calc( + (var(--max-count) + 1) * var(--grid-section-min-width) + + (var(--max-count) + 2) * var(--grid-gap) - 1px + ); + display: grid; grid-template-columns: repeat( auto-fit, - minmax(var(--grid-cell-min-width), 1fr) + minmax(var(--grid-section-min-width), 1fr) ); + grid-gap: 8px var(--grid-gap); justify-content: center; - gap: 8px var(--grid-gap); padding: var(--grid-gap); box-sizing: border-box; - max-width: min( - calc( - var(--cell-count) * (var(--grid-cell-max-width) + var(--grid-gap)) + - var(--grid-gap) - ), - var(--grid-max-width) - ); + max-width: var(--grid-max-width); margin: 0 auto; } From de8b0ba8c5e6b49a9d283cb16dce50bdbee3084d Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Fri, 1 Mar 2024 15:31:25 +0100 Subject: [PATCH 06/35] Transform helper to warning for edit view type (#19934) --- .../view-editor/hui-dialog-edit-view.ts | 34 ++++++++++++++++++- .../editor/view-editor/hui-view-editor.ts | 22 ++---------- src/translations/en.json | 4 +-- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts b/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts index 038680b049..a4ba863a12 100644 --- a/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts +++ b/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts @@ -57,6 +57,8 @@ import { EditViewDialogParams } from "./show-edit-view-dialog"; export class HuiDialogEditView extends LitElement { @property({ attribute: false }) public hass?: HomeAssistant; + @state() private _currentType?: string; + @state() private _params?: EditViewDialogParams; @state() private _config?: LovelaceViewConfig; @@ -111,6 +113,7 @@ export class HuiDialogEditView extends LitElement { this._badges = []; return; } + this._currentType = view.type; const { badges, ...viewConfig } = view; this._config = viewConfig; this._badges = badges ? processEditorEntities(badges) : []; @@ -211,6 +214,15 @@ export class HuiDialogEditView extends LitElement { } } + const isEmpty = + !this._config?.cards?.length && !this._config?.sections?.length; + + const isCompatibleViewType = + isEmpty || + (this._currentType === SECTION_VIEW_LAYOUT + ? this._config?.type === SECTION_VIEW_LAYOUT + : this._config?.type !== SECTION_VIEW_LAYOUT); + return html` ` : nothing} + ${!isCompatibleViewType + ? html` + + ${this._config?.type === SECTION_VIEW_LAYOUT + ? this.hass!.localize( + "ui.panel.lovelace.editor.edit_view.type_warning_sections" + ) + : this.hass!.localize( + "ui.panel.lovelace.editor.edit_view.type_warning_others" + )} + + ` + : nothing} ${this._saving @@ -554,6 +582,10 @@ export class HuiDialogEditView extends LitElement { margin: 12px 16px; flex-wrap: wrap; } + .incompatible { + display: block; + margin-top: 16px; + } @media all and (min-width: 600px) { ha-dialog { diff --git a/src/panels/lovelace/editor/view-editor/hui-view-editor.ts b/src/panels/lovelace/editor/view-editor/hui-view-editor.ts index 803cdea063..b22dc61d68 100644 --- a/src/panels/lovelace/editor/view-editor/hui-view-editor.ts +++ b/src/panels/lovelace/editor/view-editor/hui-view-editor.ts @@ -37,7 +37,7 @@ export class HuiViewEditor extends LitElement { private _suggestedPath = false; private _schema = memoizeOne( - (localize: LocalizeFunc, currentType: string, isNew: boolean) => + (localize: LocalizeFunc) => [ { name: "title", selector: { text: {} } }, { @@ -64,11 +64,6 @@ export class HuiViewEditor extends LitElement { label: localize( `ui.panel.lovelace.editor.edit_view.types.${type}` ), - disabled: - !isNew && - (currentType === SECTION_VIEW_LAYOUT - ? type !== SECTION_VIEW_LAYOUT - : type === SECTION_VIEW_LAYOUT), })), }, }, @@ -95,16 +90,12 @@ export class HuiViewEditor extends LitElement { : this._config.type || DEFAULT_VIEW_LAYOUT; } - private get _isEmpty(): boolean { - return !this._config.sections?.length && !this._config.cards?.length; - } - protected render() { if (!this.hass) { return nothing; } - const schema = this._schema(this.hass.localize, this._type, this._isEmpty); + const schema = this._schema(this.hass.localize); const data = { ...this._config, @@ -168,15 +159,6 @@ export class HuiViewEditor extends LitElement { return this.hass.localize( "ui.panel.lovelace.editor.edit_view.subview_helper" ); - case "type": - if (this._isEmpty) return undefined; - return this._type === "sections" - ? this.hass.localize( - "ui.panel.lovelace.editor.edit_view.type_helper_others" - ) - : this.hass.localize( - "ui.panel.lovelace.editor.edit_view.type_helper_sections" - ); default: return undefined; } diff --git a/src/translations/en.json b/src/translations/en.json index c8c1b42c79..9b52c4299b 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -5112,8 +5112,8 @@ "select_users": "Select which users should see this view in the navigation" }, "type": "View type", - "type_helper_sections": "You can not change your view to use the 'sections' view type because migration is not supported yet. Start from scratch with a new view if you want to experiment with the 'sections' view.", - "type_helper_others": "You can not change your view to an other type because migration is not supported yet. Start from scratch with a new view if you want to use another view type.", + "type_warning_sections": "You can not change your view to use the 'sections' view type because migration is not supported yet. Start from scratch with a new view if you want to experiment with the 'sections' view.", + "type_warning_others": "You can not change your view to an other type because migration is not supported yet. Start from scratch with a new view if you want to use another view type.", "types": { "masonry": "Masonry (default)", From 69dbcec678b02513af896b59c08a50c21ffaec9b Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Fri, 1 Mar 2024 16:15:03 +0100 Subject: [PATCH 07/35] Bumped version to 20240301.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a725ab6ed3..c15f5c2579 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240228.1" +version = "20240301.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From e350ba47261250743fbe08ae88dd485f631028f3 Mon Sep 17 00:00:00 2001 From: Jeremy Noesen Date: Mon, 4 Mar 2024 08:45:54 -0600 Subject: [PATCH 08/35] Update cast launch screen colors (#19754) --- cast/src/receiver/layout/hc-launch-screen.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cast/src/receiver/layout/hc-launch-screen.ts b/cast/src/receiver/layout/hc-launch-screen.ts index ba70fb7452..b2fe7d7e95 100644 --- a/cast/src/receiver/layout/hc-launch-screen.ts +++ b/cast/src/receiver/layout/hc-launch-screen.ts @@ -28,7 +28,7 @@ class HcLaunchScreen extends LitElement { :host { display: block; height: 100vh; - background-color: white; + background-color: #f2f4f9; font-size: 24px; } .container { @@ -43,6 +43,9 @@ class HcLaunchScreen extends LitElement { max-width: 80%; object-fit: cover; } + .status { + color: #1d2126; + } `; } } From 8cedaae645ae6a0b37a01635787a987927ba3a7f Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Mon, 4 Mar 2024 09:02:32 -0500 Subject: [PATCH 09/35] Support max_devices for energy-devices-detail-graph (#19936) * Support max_devices for energy-devices-detail-graph * responsive ui editor --- .../hui-energy-devices-detail-graph-card.ts | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts index 5bd0e8ce33..1d585f2d57 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts @@ -96,7 +96,10 @@ export class HuiEnergyDevicesDetailGraphCard } protected willUpdate(changedProps: PropertyValues) { - if (changedProps.has("_hiddenStats") && this._data) { + if ( + (changedProps.has("_hiddenStats") || changedProps.has("_config")) && + this._data + ) { this._processStatistics(); } } @@ -217,17 +220,17 @@ export class HuiEnergyDevicesDetailGraphCard const datasets: ChartDataset<"bar", ScatterDataPoint[]>[] = []; const datasetExtras: ChartDatasetExtra[] = []; - datasets.push( - ...this._processDataSet( + const { data: processedData, dataExtras: processedDataExtras } = + this._processDataSet( data, energyData.statsMetadata, energyData.prefs.device_consumption, sorted_devices - ) - ); + ); - const items = datasets.length; - datasetExtras.push(...Array(items).fill({})); + datasets.push(...processedData); + + datasetExtras.push(...processedDataExtras); if (compareData) { // Add empty dataset to align the bars @@ -247,18 +250,19 @@ export class HuiEnergyDevicesDetailGraphCard show_legend: false, }); - datasets.push( - ...this._processDataSet( - compareData, - energyData.statsMetadata, - energyData.prefs.device_consumption, - sorted_devices, - true - ) - ); - datasetExtras.push( - ...Array(items).fill({ show_legend: false }) + const { + data: processedCompareData, + dataExtras: processedCompareDataExtras, + } = this._processDataSet( + compareData, + energyData.statsMetadata, + energyData.prefs.device_consumption, + sorted_devices, + true ); + + datasets.push(...processedCompareData); + datasetExtras.push(...processedCompareDataExtras); } this._start = energyData.start; @@ -281,6 +285,7 @@ export class HuiEnergyDevicesDetailGraphCard compare = false ) { const data: ChartDataset<"bar", ScatterDataPoint[]>[] = []; + const dataExtras: ChartDatasetExtra[] = []; devices.forEach((source, idx) => { const color = getColorByIndex(idx); @@ -317,23 +322,30 @@ export class HuiEnergyDevicesDetailGraphCard } } + const order = sorted_devices.indexOf(source.stat_consumption); + const itemExceedsMax = !!( + this._config?.max_devices && order >= this._config.max_devices + ); + data.push({ label: getStatisticLabel( this.hass, source.stat_consumption, statisticsMetaData[source.stat_consumption] ), - hidden: this._hiddenStats.has(source.stat_consumption), + hidden: + this._hiddenStats.has(source.stat_consumption) || itemExceedsMax, borderColor: compare ? color + "7F" : color, backgroundColor: compare ? color + "32" : color + "7F", data: consumptionData, - order: 1 + sorted_devices.indexOf(source.stat_consumption), + order: 1 + order, stack: "devices", pointStyle: compare ? false : "circle", xAxisID: compare ? "xAxisCompare" : undefined, }); + dataExtras.push({ show_legend: !compare && !itemExceedsMax }); }); - return data; + return { data, dataExtras }; } static get styles(): CSSResultGroup { From 84e6f2fc4f585c2c027241cb6dd23b589afd746f Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Mon, 4 Mar 2024 09:44:17 -0500 Subject: [PATCH 10/35] Fix a bug in energy batteryToGrid calculation (#19958) --- .../lovelace/cards/energy/hui-energy-distribution-card.ts | 2 +- .../cards/energy/hui-energy-self-sufficiency-gauge-card.ts | 2 +- .../lovelace/cards/energy/hui-energy-usage-graph-card.ts | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/panels/lovelace/cards/energy/hui-energy-distribution-card.ts b/src/panels/lovelace/cards/energy/hui-energy-distribution-card.ts index 3a75287d23..534775bc5f 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-distribution-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-distribution-card.ts @@ -177,7 +177,7 @@ class HuiEnergyDistrubutionCard if (hasBattery) { batteryFromGrid = solarConsumption * -1; if (batteryFromGrid > totalFromGrid) { - batteryToGrid = Math.min(0, batteryFromGrid - totalFromGrid); + batteryToGrid = batteryFromGrid - totalFromGrid; batteryFromGrid = totalFromGrid; } } diff --git a/src/panels/lovelace/cards/energy/hui-energy-self-sufficiency-gauge-card.ts b/src/panels/lovelace/cards/energy/hui-energy-self-sufficiency-gauge-card.ts index e39450c4ff..1b5a1bb8b0 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-self-sufficiency-gauge-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-self-sufficiency-gauge-card.ts @@ -150,7 +150,7 @@ class HuiEnergySelfSufficiencyGaugeCard if (hasBattery) { batteryFromGrid = solarConsumption * -1; if (batteryFromGrid > totalFromGrid) { - batteryToGrid = Math.min(0, batteryFromGrid - totalFromGrid); + batteryToGrid = batteryFromGrid - totalFromGrid; batteryFromGrid = totalFromGrid; } } diff --git a/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts index 7b7c45db80..4cdd7eb1b0 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts @@ -434,10 +434,8 @@ export class HuiEnergyUsageGraphCard if (summedData.to_battery) { grid_to_battery[start] = used_solar[start] * -1; if (grid_to_battery[start] > (summedData.from_grid?.[start] || 0)) { - battery_to_grid[start] = Math.min( - 0, - grid_to_battery[start] - (summedData.from_grid?.[start] || 0) - ); + battery_to_grid[start] = + grid_to_battery[start] - (summedData.from_grid?.[start] || 0); grid_to_battery[start] = summedData.from_grid?.[start]; } } From c5c4253760fd36e7a82f9778a1601d7a4f540e57 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 4 Mar 2024 15:22:22 +0100 Subject: [PATCH 11/35] Expose dialog to custom card helpers (#19969) --- src/data/lock.ts | 4 ++-- src/dialogs/enter-code/show-enter-code-dialog.ts | 2 +- .../more-info/controls/more-info-alarm_control_panel.ts | 4 ++-- .../lovelace/card-features/hui-alarm-modes-card-feature.ts | 4 ++-- src/panels/lovelace/custom-card-helpers.ts | 6 ++++++ .../ha-state-control-alarm_control_panel-modes.ts | 4 ++-- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/data/lock.ts b/src/data/lock.ts index 6630ef0989..7d155369f4 100644 --- a/src/data/lock.ts +++ b/src/data/lock.ts @@ -3,7 +3,7 @@ import { HassEntityBase, } from "home-assistant-js-websocket"; import { getExtendedEntityRegistryEntry } from "./entity_registry"; -import { showEnterCodeDialogDialog } from "../dialogs/enter-code/show-enter-code-dialog"; +import { showEnterCodeDialog } from "../dialogs/enter-code/show-enter-code-dialog"; import { HomeAssistant } from "../types"; export const FORMAT_TEXT = "text"; @@ -38,7 +38,7 @@ export const callProtectedLockService = async ( const defaultCode = lockRegistryEntry?.options?.lock?.default_code; if (stateObj!.attributes.code_format && !defaultCode) { - const response = await showEnterCodeDialogDialog(element, { + const response = await showEnterCodeDialog(element, { codeFormat: "text", codePattern: stateObj!.attributes.code_format, title: hass.localize(`ui.card.lock.${service}`), diff --git a/src/dialogs/enter-code/show-enter-code-dialog.ts b/src/dialogs/enter-code/show-enter-code-dialog.ts index 6356c20364..84006ea06f 100644 --- a/src/dialogs/enter-code/show-enter-code-dialog.ts +++ b/src/dialogs/enter-code/show-enter-code-dialog.ts @@ -10,7 +10,7 @@ export interface EnterCodeDialogParams { cancel?: () => void; } -export const showEnterCodeDialogDialog = ( +export const showEnterCodeDialog = ( element: HTMLElement, dialogParams: EnterCodeDialogParams ) => diff --git a/src/dialogs/more-info/controls/more-info-alarm_control_panel.ts b/src/dialogs/more-info/controls/more-info-alarm_control_panel.ts index bfc39a2ddc..312c0f2c0d 100644 --- a/src/dialogs/more-info/controls/more-info-alarm_control_panel.ts +++ b/src/dialogs/more-info/controls/more-info-alarm_control_panel.ts @@ -8,7 +8,7 @@ import "../../../components/ha-state-icon"; import { AlarmControlPanelEntity } from "../../../data/alarm_control_panel"; import "../../../state-control/alarm_control_panel/ha-state-control-alarm_control_panel-modes"; import type { HomeAssistant } from "../../../types"; -import { showEnterCodeDialogDialog } from "../../enter-code/show-enter-code-dialog"; +import { showEnterCodeDialog } from "../../enter-code/show-enter-code-dialog"; import "../components/ha-more-info-state-header"; import { moreInfoControlStyle } from "../components/more-info-control-style"; @@ -22,7 +22,7 @@ class MoreInfoAlarmControlPanel extends LitElement { let code: string | undefined; if (this.stateObj!.attributes.code_format) { - const response = await showEnterCodeDialogDialog(this, { + const response = await showEnterCodeDialog(this, { codeFormat: this.stateObj!.attributes.code_format, title: this.hass.localize("ui.card.alarm_control_panel.disarm"), submitText: this.hass.localize("ui.card.alarm_control_panel.disarm"), diff --git a/src/panels/lovelace/card-features/hui-alarm-modes-card-feature.ts b/src/panels/lovelace/card-features/hui-alarm-modes-card-feature.ts index b04318e46f..818b1e66a4 100644 --- a/src/panels/lovelace/card-features/hui-alarm-modes-card-feature.ts +++ b/src/panels/lovelace/card-features/hui-alarm-modes-card-feature.ts @@ -21,7 +21,7 @@ import { UNAVAILABLE } from "../../../data/entity"; import { HomeAssistant } from "../../../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { AlarmModesCardFeatureConfig } from "./types"; -import { showEnterCodeDialogDialog } from "../../../dialogs/enter-code/show-enter-code-dialog"; +import { showEnterCodeDialog } from "../../../dialogs/enter-code/show-enter-code-dialog"; export const supportsAlarmModesCardFeature = (stateObj: HassEntity) => { const domain = computeDomain(stateObj.entity_id); @@ -131,7 +131,7 @@ class HuiAlarmModeCardFeature ) { const disarm = mode === "disarmed"; - const response = await showEnterCodeDialogDialog(this, { + const response = await showEnterCodeDialog(this, { codeFormat: this.stateObj!.attributes.code_format, title: this.hass!.localize( `ui.card.alarm_control_panel.${disarm ? "disarm" : "arm"}` diff --git a/src/panels/lovelace/custom-card-helpers.ts b/src/panels/lovelace/custom-card-helpers.ts index 3c4508ca0b..5cf34343aa 100644 --- a/src/panels/lovelace/custom-card-helpers.ts +++ b/src/panels/lovelace/custom-card-helpers.ts @@ -1,3 +1,9 @@ +export { showEnterCodeDialog } from "../../dialogs/enter-code/show-enter-code-dialog"; +export { + showAlertDialog, + showConfirmationDialog, + showPromptDialog, +} from "../../dialogs/generic/show-dialog-box"; export { importMoreInfoControl } from "../../dialogs/more-info/state_more_info_control"; export { createBadgeElement } from "./create-element/create-badge-element"; export { createCardElement } from "./create-element/create-card-element"; diff --git a/src/state-control/alarm_control_panel/ha-state-control-alarm_control_panel-modes.ts b/src/state-control/alarm_control_panel/ha-state-control-alarm_control_panel-modes.ts index 1e9b53a277..647795f46a 100644 --- a/src/state-control/alarm_control_panel/ha-state-control-alarm_control_panel-modes.ts +++ b/src/state-control/alarm_control_panel/ha-state-control-alarm_control_panel-modes.ts @@ -13,7 +13,7 @@ import { AlarmMode, } from "../../data/alarm_control_panel"; import { UNAVAILABLE } from "../../data/entity"; -import { showEnterCodeDialogDialog } from "../../dialogs/enter-code/show-enter-code-dialog"; +import { showEnterCodeDialog } from "../../dialogs/enter-code/show-enter-code-dialog"; import { HomeAssistant } from "../../types"; @customElement("ha-state-control-alarm_control_panel-modes") @@ -56,7 +56,7 @@ export class HaStateControlAlarmControlPanelModes extends LitElement { ) { const disarm = mode === "disarmed"; - const response = await showEnterCodeDialogDialog(this, { + const response = await showEnterCodeDialog(this, { codeFormat: this.stateObj!.attributes.code_format, title: this.hass!.localize( `ui.card.alarm_control_panel.${disarm ? "disarm" : "arm"}` From 56c681bcf87f61b3c90a9c6bb0f60e0e4f985c4c Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 4 Mar 2024 15:04:20 +0100 Subject: [PATCH 12/35] Make migration warning alert sticky at the top for views (#19970) --- .../view-editor/hui-dialog-edit-view.ts | 45 ++++++++----------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts b/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts index a4ba863a12..4d67c4dbf6 100644 --- a/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts +++ b/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts @@ -57,8 +57,6 @@ import { EditViewDialogParams } from "./show-edit-view-dialog"; export class HuiDialogEditView extends LitElement { @property({ attribute: false }) public hass?: HomeAssistant; - @state() private _currentType?: string; - @state() private _params?: EditViewDialogParams; @state() private _config?: LovelaceViewConfig; @@ -113,7 +111,6 @@ export class HuiDialogEditView extends LitElement { this._badges = []; return; } - this._currentType = view.type; const { badges, ...viewConfig } = view; this._config = viewConfig; this._badges = badges ? processEditorEntities(badges) : []; @@ -214,14 +211,12 @@ export class HuiDialogEditView extends LitElement { } } - const isEmpty = - !this._config?.cards?.length && !this._config?.sections?.length; - const isCompatibleViewType = - isEmpty || - (this._currentType === SECTION_VIEW_LAYOUT - ? this._config?.type === SECTION_VIEW_LAYOUT - : this._config?.type !== SECTION_VIEW_LAYOUT); + this._config?.type === SECTION_VIEW_LAYOUT + ? this._config?.type === SECTION_VIEW_LAYOUT && + !this._config?.cards?.length + : this._config?.type !== SECTION_VIEW_LAYOUT && + !this._config?.sections?.length; return html` + ${!isCompatibleViewType + ? html` + + ${this._config?.type === SECTION_VIEW_LAYOUT + ? this.hass!.localize( + "ui.panel.lovelace.editor.edit_view.type_warning_sections" + ) + : this.hass!.localize( + "ui.panel.lovelace.editor.edit_view.type_warning_others" + )} + + ` + : nothing} ${!this._yamlMode ? html` ` : nothing} - ${!isCompatibleViewType - ? html` - - ${this._config?.type === SECTION_VIEW_LAYOUT - ? this.hass!.localize( - "ui.panel.lovelace.editor.edit_view.type_warning_sections" - ) - : this.hass!.localize( - "ui.panel.lovelace.editor.edit_view.type_warning_others" - )} - - ` - : nothing} Date: Mon, 4 Mar 2024 15:28:58 +0100 Subject: [PATCH 13/35] Fix badges not saved in view editor (#19971) --- .../view-editor/hui-dialog-edit-view.ts | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts b/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts index 4d67c4dbf6..498a7890dc 100644 --- a/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts +++ b/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts @@ -23,7 +23,6 @@ import "../../../../components/ha-dialog"; import "../../../../components/ha-dialog-header"; import "../../../../components/ha-yaml-editor"; import type { HaYamlEditor } from "../../../../components/ha-yaml-editor"; -import { LovelaceBadgeConfig } from "../../../../data/lovelace/config/badge"; import { LovelaceViewConfig, isStrategyView, @@ -61,8 +60,6 @@ export class HuiDialogEditView extends LitElement { @state() private _config?: LovelaceViewConfig; - @state() private _badges?: LovelaceBadgeConfig[]; - @state() private _saving = false; @state() private _curTab?: string; @@ -88,7 +85,6 @@ export class HuiDialogEditView extends LitElement { if (this._yamlMode && changedProperties.has("_yamlMode")) { const viewConfig = { ...this._config, - badges: this._badges, }; this._editor?.setValue(viewConfig); } @@ -99,7 +95,6 @@ export class HuiDialogEditView extends LitElement { if (this._params.viewIndex === undefined) { this._config = {}; - this._badges = []; this._dirty = false; return; } @@ -108,19 +103,15 @@ export class HuiDialogEditView extends LitElement { if (isStrategyView(view)) { const { strategy, ...viewConfig } = view; this._config = viewConfig; - this._badges = []; return; } - const { badges, ...viewConfig } = view; - this._config = viewConfig; - this._badges = badges ? processEditorEntities(badges) : []; + this._config = view; } public closeDialog(): void { this._curTabIndex = 0; this._params = undefined; this._config = {}; - this._badges = []; this._yamlMode = false; this._dirty = false; fireEvent(this, "dialog-closed", { dialog: this.localName }); @@ -166,7 +157,7 @@ export class HuiDialogEditView extends LitElement { break; case "tab-badges": content = html` - ${this._badges?.length + ${this._config?.badges?.length ? html` ${VIEWS_NO_BADGE_SUPPORT.includes(this._type) ? html` @@ -178,7 +169,7 @@ export class HuiDialogEditView extends LitElement { ` : nothing}
- ${this._badges.map( + ${this._config.badges.map( (badgeConfig) => html` `; @@ -420,9 +411,9 @@ export class HuiDialogEditView extends LitElement { } this._saving = true; - const viewConf: LovelaceViewConfig = { + + const viewConf = { ...this._config, - badges: this._badges, }; if (viewConf.type === SECTION_VIEW_LAYOUT && !viewConf.sections?.length) { @@ -487,10 +478,13 @@ export class HuiDialogEditView extends LitElement { } private _badgesChanged(ev: EntitiesEditorEvent): void { - if (!this._badges || !this.hass || !ev.detail || !ev.detail.entities) { + if (!this.hass || !ev.detail || !ev.detail.entities) { return; } - this._badges = processEditorEntities(ev.detail.entities); + this._config = { + ...this._config, + badges: processEditorEntities(ev.detail.entities), + }; this._dirty = true; } @@ -501,7 +495,6 @@ export class HuiDialogEditView extends LitElement { } const { badges, ...config } = ev.detail.value; this._config = config; - this._badges = badges; this._dirty = true; } From 68fbadf21b415b79f8aaaad7b8b719eb50f04ebf Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 4 Mar 2024 15:04:45 +0100 Subject: [PATCH 14/35] Fix masonry badges not centered (#19972) --- src/panels/lovelace/views/hui-masonry-view.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/panels/lovelace/views/hui-masonry-view.ts b/src/panels/lovelace/views/hui-masonry-view.ts index c8e3047c2d..bcc87214e3 100644 --- a/src/panels/lovelace/views/hui-masonry-view.ts +++ b/src/panels/lovelace/views/hui-masonry-view.ts @@ -291,6 +291,12 @@ export class MasonryView extends LitElement implements LovelaceViewElement { padding-top: 4px; } + .badges { + margin: 8px 16px; + font-size: 85%; + text-align: center; + } + #columns { display: flex; flex-direction: row; From 0ed483ba51751adba883729bb39a2fbe2a54b97c Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 4 Mar 2024 15:31:49 +0100 Subject: [PATCH 15/35] Do not reserve space for condition card in grid section (#19973) * Do not reserve space for condition card in grid section * Update src/panels/lovelace/sections/hui-grid-section.ts Co-authored-by: Bram Kragten --------- Co-authored-by: Bram Kragten --- src/panels/lovelace/sections/hui-grid-section.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/panels/lovelace/sections/hui-grid-section.ts b/src/panels/lovelace/sections/hui-grid-section.ts index b63e9fac8f..7484faf70f 100644 --- a/src/panels/lovelace/sections/hui-grid-section.ts +++ b/src/panels/lovelace/sections/hui-grid-section.ts @@ -215,6 +215,14 @@ export class GridSection extends LitElement implements LovelaceSectionElement { grid-column: span var(--column-size, 4); } + .card:has(> *) { + display: block; + } + + .card:has(> *[hidden]) { + display: none; + } + .add { outline: none; grid-row: span var(--row-size, 1); From d248de92e5e96020aff4a5c8986085ff5bfdb435 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 4 Mar 2024 15:50:40 +0100 Subject: [PATCH 16/35] Clean generated config for tile in sections (#19974) * Do not include show_entity_picture false in tile card config * Update src/panels/lovelace/common/generate-lovelace-config.ts Co-authored-by: Bram Kragten --------- Co-authored-by: Bram Kragten --- src/panels/lovelace/common/generate-lovelace-config.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/panels/lovelace/common/generate-lovelace-config.ts b/src/panels/lovelace/common/generate-lovelace-config.ts index c609f66dbd..8af49cabdc 100644 --- a/src/panels/lovelace/common/generate-lovelace-config.ts +++ b/src/panels/lovelace/common/generate-lovelace-config.ts @@ -112,9 +112,9 @@ export const computeSection = ( ({ type: "tile", entity, - show_entity_picture: ["person", "camera", "image"].includes( - computeDomain(entity) - ), + show_entity_picture: + ["person", "camera", "image"].includes(computeDomain(entity)) || + undefined, }) as TileCardConfig ), ...sectionOptions, From a9f453ea367f45591b544decbe612a54a9521db6 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 4 Mar 2024 15:22:04 +0100 Subject: [PATCH 17/35] Add sections dashboard to demo dashboard (#19976) --- demo/src/configs/demo-configs.ts | 1 + demo/src/configs/sections/entities.ts | 482 ++++++++++++++++++ demo/src/configs/sections/index.ts | 12 + demo/src/configs/sections/lovelace.ts | 280 ++++++++++ .../lovelace/sections/hui-grid-section.ts | 1 + 5 files changed, 776 insertions(+) create mode 100644 demo/src/configs/sections/entities.ts create mode 100644 demo/src/configs/sections/index.ts create mode 100644 demo/src/configs/sections/lovelace.ts diff --git a/demo/src/configs/demo-configs.ts b/demo/src/configs/demo-configs.ts index 07dca811f7..dacddf0944 100644 --- a/demo/src/configs/demo-configs.ts +++ b/demo/src/configs/demo-configs.ts @@ -4,6 +4,7 @@ import { energyEntities } from "../stubs/entities"; import { DemoConfig } from "./types"; export const demoConfigs: Array<() => Promise> = [ + () => import("./sections").then((mod) => mod.demoSections), () => import("./arsaboo").then((mod) => mod.demoArsaboo), () => import("./teachingbirds").then((mod) => mod.demoTeachingbirds), () => import("./kernehed").then((mod) => mod.demoKernehed), diff --git a/demo/src/configs/sections/entities.ts b/demo/src/configs/sections/entities.ts new file mode 100644 index 0000000000..ffb7389503 --- /dev/null +++ b/demo/src/configs/sections/entities.ts @@ -0,0 +1,482 @@ +import { convertEntities } from "../../../../src/fake_data/entity"; +import { DemoConfig } from "../types"; + +export const demoEntitiesSections: DemoConfig["entities"] = () => + convertEntities({ + "cover.living_room_garden_shutter": { + entity_id: "cover.living_room_garden_shutter", + state: "open", + attributes: { + current_position: 100, + device_class: "shutter", + friendly_name: "Living room garden shutter", + supported_features: 15, + }, + }, + "cover.living_room_graveyard_shutter": { + entity_id: "cover.living_room_graveyard_shutter", + state: "open", + attributes: { + current_position: 100, + device_class: "shutter", + friendly_name: "Living room graveyard shutter", + supported_features: 15, + }, + }, + "cover.living_room_left_shutter": { + entity_id: "cover.living_room_left_shutter", + state: "open", + attributes: { + current_position: 100, + device_class: "shutter", + friendly_name: "Living room left shutter", + supported_features: 15, + }, + }, + "cover.living_room_right_shutter": { + entity_id: "cover.living_room_right_shutter", + state: "open", + attributes: { + current_position: 100, + device_class: "shutter", + friendly_name: "Living room right shutter", + supported_features: 15, + }, + }, + "light.floor_lamp": { + entity_id: "light.floor_lamp", + state: "on", + attributes: { + min_color_temp_kelvin: 2000, + max_color_temp_kelvin: 6535, + min_mireds: 153, + max_mireds: 500, + supported_color_modes: ["color_temp", "xy"], + color_mode: "color_temp", + brightness: 178, + color_temp_kelvin: 2583, + color_temp: 387, + hs_color: [28.664, 69.597], + rgb_color: [255, 162, 77], + xy_color: [0.538, 0.389], + icon: "mdi:floor-lamp", + friendly_name: "Floor lamp", + supported_features: 44, + }, + }, + "light.living_room_spotlights": { + entity_id: "light.living_room_spotlights", + state: "on", + attributes: { + supported_color_modes: ["brightness"], + color_mode: "brightness", + brightness: 126, + icon: "mdi:ceiling-light-multiple", + friendly_name: "Living room spotlights", + supported_features: 32, + }, + }, + "light.bar_lamp": { + entity_id: "light.bar_lamp", + state: "on", + attributes: { + min_color_temp_kelvin: 2202, + max_color_temp_kelvin: 4504, + min_mireds: 222, + max_mireds: 454, + effect_list: ["None", "candle"], + supported_color_modes: ["color_temp"], + effect: null, + color_mode: null, + brightness: null, + color_temp_kelvin: null, + color_temp: null, + hs_color: null, + rgb_color: null, + xy_color: null, + mode: "normal", + dynamics: "none", + icon: "mdi:lightbulb-variant", + friendly_name: "Bar lamp", + supported_features: 44, + }, + }, + "sensor.living_room_temperature": { + entity_id: "sensor.living_room_temperature", + state: "22.8", + attributes: { + state_class: "measurement", + unit_of_measurement: "°C", + device_class: "temperature", + friendly_name: "Living room Temperature", + }, + }, + "media_player.living_room_nest_mini": { + entity_id: "media_player.living_room_nest_mini", + state: "off", + attributes: { + device_class: "speaker", + friendly_name: "Living room Nest Mini", + supported_features: 152461, + }, + }, + "cover.kitchen_shutter": { + entity_id: "cover.kitchen_shutter", + state: "open", + attributes: { + current_position: 100, + device_class: "shutter", + friendly_name: "Kitchen shutter ", + supported_features: 15, + }, + }, + "light.kitchen_spotlights": { + entity_id: "light.kitchen_spotlights", + state: "off", + attributes: { + supported_color_modes: ["brightness"], + color_mode: null, + brightness: null, + icon: "mdi:ceiling-light-multiple", + friendly_name: "Kitchen spotlights ", + supported_features: 32, + }, + }, + "light.worktop_spotlights": { + entity_id: "light.worktop_spotlights", + state: "off", + attributes: { + supported_color_modes: ["brightness"], + color_mode: null, + brightness: null, + icon: "mdi:ceiling-light-multiple", + friendly_name: "Worktop spotlights ", + supported_features: 32, + }, + }, + "binary_sensor.fridge_door": { + entity_id: "binary_sensor.fridge_door", + state: "off", + attributes: { + device_class: "door", + icon: "mdi:fridge", + friendly_name: "Fridge door", + }, + }, + "media_player.kitchen_nest_audio": { + entity_id: "media_player.kitchen_nest_audio", + state: "on", + attributes: { + device_class: "speaker", + friendly_name: "Kitchen Nest Audio", + supported_features: 152461, + }, + }, + "binary_sensor.tesla_wall_connector_vehicle_connected": { + entity_id: "binary_sensor.tesla_wall_connector_vehicle_connected", + state: "off", + attributes: { + device_class: "plug", + friendly_name: "Wall Connector Vehicle connected", + }, + }, + "sensor.tesla_wall_connector_session_energy": { + entity_id: "sensor.tesla_wall_connector_session_energy", + state: "16.3", + attributes: { + state_class: "total_increasing", + unit_of_measurement: "kWh", + device_class: "energy", + friendly_name: "Tesla Wall Connector Session energy", + }, + }, + "sensor.electric_meter_power": { + entity_id: "sensor.electric_meter_power", + state: "797.86", + attributes: { + state_class: "measurement", + unit_of_measurement: "W", + device_class: "power", + icon: "mdi:meter-electric", + friendly_name: "Electric meter Power", + }, + }, + "sensor.eletric_meter_voltage": { + entity_id: "sensor.eletric_meter_voltage", + state: "232.19", + attributes: { + state_class: "measurement", + unit_of_measurement: "V", + device_class: "voltage", + friendly_name: "Electric meter voltage", + }, + }, + "sensor.electricity_maps_grid_fossil_fuel_percentage": { + entity_id: "sensor.electricity_maps_grid_fossil_fuel_percentage", + state: "9.84", + attributes: { + state_class: "measurement", + country_code: "FR", + unit_of_measurement: "%", + attribution: "Data provided by Electricity Maps", + icon: "mdi:barrel", + friendly_name: "Electricity Maps Grid fossil fuel percentage", + }, + }, + "sensor.electricity_maps_co2_intensity": { + entity_id: "sensor.electricity_maps_co2_intensity", + state: "62.0", + attributes: { + state_class: "measurement", + country_code: "FR", + unit_of_measurement: "gCO2eq/kWh", + attribution: "Data provided by Electricity Maps", + friendly_name: "Electricity Maps CO2 intensity", + }, + }, + "sun.sun": { + entity_id: "sun.sun", + state: "above_horizon", + attributes: { + next_dawn: "2024-03-05T05:50:21.964405+00:00", + next_dusk: "2024-03-04T18:08:54.311334+00:00", + next_midnight: "2024-03-05T00:00:00+00:00", + next_noon: "2024-03-05T12:00:05+00:00", + next_rising: "2024-03-05T06:23:42.739159+00:00", + next_setting: "2024-03-04T17:35:26.271171+00:00", + elevation: 30.38, + azimuth: 204.42, + rising: false, + friendly_name: "Sun", + }, + }, + "sensor.moon_phase": { + entity_id: "sensor.moon_phase", + state: "waning_crescent", + attributes: { + options: [ + "new_moon", + "waxing_crescent", + "first_quarter", + "waxing_gibbous", + "full_moon", + "waning_gibbous", + "last_quarter", + "waning_crescent", + ], + device_class: "enum", + icon: "mdi:moon-waning-crescent", + friendly_name: "Moon Phase", + }, + }, + "climate.ground_floor": { + entity_id: "climate.ground_floor", + state: "heat", + attributes: { + hvac_modes: ["auto", "heat", "off"], + min_temp: 7, + max_temp: 35, + preset_modes: [ + "comfort", + "away", + "eco", + "frost_protection", + "external", + "home", + ], + current_temperature: 20.8, + temperature: 21, + preset_mode: "comfort", + icon: "mdi:home-floor-0", + friendly_name: "Ground floor Thermostat", + supported_features: 401, + }, + }, + "climate.first_floor": { + entity_id: "climate.first_floor", + state: "heat", + attributes: { + hvac_modes: ["auto", "heat", "off"], + min_temp: 7, + max_temp: 35, + preset_modes: [ + "comfort", + "away", + "eco", + "frost_protection", + "external", + "home", + ], + current_temperature: 21.7, + temperature: 21, + preset_mode: "comfort", + icon: "mdi:home-floor-1", + friendly_name: "First floor Thermostat", + supported_features: 401, + }, + }, + "cover.study_shutter": { + entity_id: "cover.study_shutter", + state: "open", + attributes: { + current_position: 100, + device_class: "shutter", + friendly_name: "Study shutter", + supported_features: 15, + }, + }, + "light.study_spotlights": { + entity_id: "light.study_spotlights", + state: "off", + attributes: { + supported_color_modes: ["brightness"], + color_mode: null, + brightness: null, + icon: "mdi:ceiling-light-multiple", + friendly_name: "Study spotlights", + supported_features: 32, + }, + }, + "media_player.study_nest_hub": { + entity_id: "media_player.study_nest_hub", + state: "off", + attributes: { + friendly_name: "Study Nest Hub", + supported_features: 152461, + }, + }, + "sensor.standing_desk_height": { + entity_id: "sensor.standing_desk_height", + state: "72", + attributes: { + unit_of_measurement: "cm", + icon: "mdi:tape-measure", + friendly_name: "Standing desk Height", + }, + }, + "light.outdoor_light": { + entity_id: "light.outdoor_light", + state: "on", + attributes: { + supported_color_modes: ["brightness"], + color_mode: null, + brightness: 255, + icon: "mdi:outdoor-lamp", + friendly_name: "Outdoor light", + supported_features: 32, + }, + }, + "light.flood_light": { + entity_id: "light.flood_light", + state: "off", + attributes: { + effect_list: ["None", "candle"], + supported_color_modes: ["brightness"], + effect: null, + color_mode: null, + brightness: null, + mode: "normal", + dynamics: "none", + icon: "mdi:light-flood-down", + friendly_name: "Flood light", + supported_features: 44, + }, + }, + "sensor.outdoor_motion_sensor_temperature": { + entity_id: "sensor.outdoor_motion_sensor_temperature", + state: "10.2", + attributes: { + state_class: "measurement", + unit_of_measurement: "°C", + device_class: "temperature", + friendly_name: "Outdoor motion sensor Temperature", + }, + }, + "binary_sensor.outdoor_motion_sensor_motion": { + entity_id: "binary_sensor.outdoor_motion_sensor_motion", + state: "off", + attributes: { + device_class: "motion", + friendly_name: "Outdoor motion sensor Motion", + }, + }, + "sensor.outdoor_motion_sensor_illuminance": { + entity_id: "sensor.outdoor_motion_sensor_illuminance", + state: "555", + attributes: { + state_class: "measurement", + light_level: 27444, + unit_of_measurement: "lx", + device_class: "illuminance", + friendly_name: "Outdoor motion sensor Illuminance", + }, + }, + "automation.home_assistant_auto_update": { + entity_id: "automation.home_assistant_auto_update", + state: "off", + attributes: { + id: "1700669321947", + last_triggered: "2024-02-29T18:02:05.343139+00:00", + mode: "queued", + current: 0, + max: 50, + icon: "mdi:auto-mode", + friendly_name: "Home Assistant Auto-update", + }, + }, + "update.home_assistant_operating_system_update": { + entity_id: "update.home_assistant_operating_system_update", + state: "off", + attributes: { + auto_update: false, + installed_version: "12.1", + in_progress: false, + latest_version: "12.1", + release_summary: null, + release_url: + "https://github.com/home-assistant/operating-system/commits/dev", + skipped_version: null, + title: "Home Assistant Operating System", + entity_picture: + "https://brands.home-assistant.io/homeassistant/icon.png", + friendly_name: "Home Assistant Operating System Update", + supported_features: 3, + }, + }, + "update.home_assistant_supervisor_update": { + entity_id: "update.home_assistant_supervisor_update", + state: "off", + attributes: { + auto_update: true, + installed_version: "2024.02.2", + in_progress: false, + latest_version: "2024.02.2", + release_summary: null, + release_url: + "https://github.com/home-assistant/supervisor/commits/main", + skipped_version: null, + title: "Home Assistant Supervisor", + entity_picture: "https://brands.home-assistant.io/hassio/icon.png", + friendly_name: "Home Assistant Supervisor Update", + supported_features: 1, + }, + }, + "update.home_assistant_core_update": { + entity_id: "update.home_assistant_supervisor_update", + state: "off", + attributes: { + auto_update: false, + installed_version: "2024.4.0", + in_progress: false, + latest_version: "2024.4.0", + release_summary: null, + release_url: "https://github.com/home-assistant/core/commits/dev", + skipped_version: null, + title: "Home Assistant Core", + entity_picture: + "https://brands.home-assistant.io/homeassistant/icon.png", + friendly_name: "Home Assistant Core Update", + supported_features: 11, + }, + }, + }); diff --git a/demo/src/configs/sections/index.ts b/demo/src/configs/sections/index.ts new file mode 100644 index 0000000000..39bc7419b8 --- /dev/null +++ b/demo/src/configs/sections/index.ts @@ -0,0 +1,12 @@ +import { DemoConfig } from "../types"; +import { demoEntitiesSections } from "./entities"; +import { demoLovelaceSections } from "./lovelace"; + +export const demoSections: DemoConfig = { + authorName: "Home Assistant", + authorUrl: "https://github.com/home-assistant/frontend/", + name: "Home Demo", + lovelace: demoLovelaceSections, + entities: demoEntitiesSections, + theme: () => ({}), +}; diff --git a/demo/src/configs/sections/lovelace.ts b/demo/src/configs/sections/lovelace.ts new file mode 100644 index 0000000000..197a434a2a --- /dev/null +++ b/demo/src/configs/sections/lovelace.ts @@ -0,0 +1,280 @@ +import { DemoConfig } from "../types"; + +export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({ + title: "Home Assistant Demo", + views: [ + { + type: "sections", + title: "Demo", + path: "home", + icon: "mdi:home-assistant", + sections: [ + { + title: "Welcome 👋", + cards: [{ type: "custom:ha-demo-card" }], + }, + { + cards: [ + { + type: "tile", + entity: "cover.living_room_garden_shutter", + name: "Garden", + }, + { + type: "tile", + entity: "cover.living_room_graveyard_shutter", + name: "Rear", + }, + { + type: "tile", + entity: "cover.living_room_left_shutter", + name: "Left", + }, + { + type: "tile", + entity: "cover.living_room_right_shutter", + name: "Right", + }, + { + type: "tile", + entity: "light.floor_lamp", + }, + { + type: "tile", + entity: "light.living_room_spotlights", + name: "Spotlights", + features: [ + { + type: "light-brightness", + }, + ], + }, + { + type: "tile", + entity: "light.bar_lamp", + }, + { + graph: "line", + type: "sensor", + entity: "sensor.living_room_temperature", + detail: 1, + name: "Temperature", + }, + { + type: "tile", + entity: "media_player.living_room_nest_mini", + name: "Nest Mini", + }, + ], + title: "🛋️ Living room ", + }, + { + type: "grid", + cards: [ + { + type: "tile", + entity: "cover.kitchen_shutter", + name: "Shutter", + }, + { + type: "tile", + entity: "light.kitchen_spotlights", + name: "Spotlights", + features: [ + { + type: "light-brightness", + }, + ], + }, + { + type: "tile", + entity: "light.worktop_spotlights", + name: "Worktop", + }, + { + type: "tile", + entity: "binary_sensor.fridge_door", + name: "Fridge", + }, + { + type: "tile", + entity: "media_player.kitchen_nest_audio", + name: "Nest Audio", + }, + ], + title: "👩‍🍳 Kitchen", + }, + { + type: "grid", + cards: [ + { + type: "tile", + entity: "binary_sensor.tesla_wall_connector_vehicle_connected", + name: "EV", + icon: "mdi:car", + }, + { + type: "tile", + entity: "sensor.tesla_wall_connector_session_energy", + name: "EV last charge", + color: "green", + }, + { + type: "tile", + entity: "sensor.electric_meter_power", + color: "deep-orange", + name: "Home power", + }, + { + type: "tile", + entity: "sensor.eletric_meter_voltage", + name: "Voltage", + color: "deep-orange", + }, + { + type: "tile", + entity: "sensor.electricity_maps_grid_fossil_fuel_percentage", + name: "Fossil fuel", + color: "brown", + }, + { + type: "tile", + entity: "sensor.electricity_maps_co2_intensity", + name: "CO2 Intensity", + color: "dark-grey", + }, + ], + title: "⚡️ Energy", + }, + { + type: "grid", + cards: [ + { + type: "tile", + entity: "sun.sun", + }, + { + type: "tile", + entity: "sensor.moon_phase", + color: "indigo", + name: "Moon", + }, + { + features: [ + { + type: "target-temperature", + }, + ], + type: "tile", + entity: "climate.ground_floor", + state_content: ["preset_mode", "current_temperature"], + }, + { + features: [ + { + type: "target-temperature", + }, + ], + type: "tile", + entity: "climate.first_floor", + state_content: ["preset_mode", "current_temperature"], + }, + ], + title: "🌤️ Climate", + }, + { + type: "grid", + cards: [ + { + type: "tile", + entity: "cover.study_shutter", + name: "Shutter", + }, + { + type: "tile", + entity: "light.study_spotlights", + name: "Spotlights", + }, + { + type: "tile", + entity: "media_player.study_nest_hub", + name: "Nest Hub", + }, + { + type: "tile", + entity: "sensor.standing_desk_height", + name: "Desk", + color: "brown", + icon: "mdi:desk", + }, + ], + title: "🧑‍💻 Study", + }, + { + type: "grid", + cards: [ + { + type: "tile", + entity: "light.outdoor_light", + name: "Door light", + }, + { + type: "tile", + entity: "light.flood_light", + }, + { + graph: "line", + type: "sensor", + entity: "sensor.outdoor_motion_sensor_temperature", + detail: 1, + name: "Temperature", + }, + { + type: "tile", + entity: "binary_sensor.outdoor_motion_sensor_motion", + name: "Motion", + color: "blue", + }, + { + type: "tile", + entity: "sensor.outdoor_motion_sensor_illuminance", + color: "amber", + name: "Illuminance", + }, + ], + title: "🌳 Outdoor", + }, + { + type: "grid", + cards: [ + { + type: "tile", + entity: "automation.home_assistant_auto_update", + name: "Auto-update", + color: "green", + }, + { + type: "tile", + entity: "update.home_assistant_operating_system_update", + name: "OS", + icon: "mdi:home-assistant", + }, + { + type: "tile", + entity: "update.home_assistant_supervisor_update", + icon: "mdi:home-assistant", + name: "Supervisor", + }, + { + type: "tile", + entity: "update.home_assistant_core_update", + name: "Core", + icon: "mdi:home-assistant", + }, + ], + title: "🎉 Updates", + }, + ], + }, + ], +}); diff --git a/src/panels/lovelace/sections/hui-grid-section.ts b/src/panels/lovelace/sections/hui-grid-section.ts index 7484faf70f..83467239ac 100644 --- a/src/panels/lovelace/sections/hui-grid-section.ts +++ b/src/panels/lovelace/sections/hui-grid-section.ts @@ -96,6 +96,7 @@ export class GridSection extends LitElement implements LovelaceSectionElement { (_cardConfig, idx) => { const card = this.cards![idx]; (card as any).editMode = editMode; + (card as any).lovelace = this.lovelace; const size = card && (card as any).getGridSize?.(); return html`
Date: Mon, 4 Mar 2024 15:30:31 +0100 Subject: [PATCH 18/35] Don't suggest to pick another card for sections (#19977) --- .../card-editor/hui-dialog-suggest-card.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts index 80e517d5ce..89b2dac01c 100644 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts @@ -131,11 +131,15 @@ export class HuiDialogSuggestCard extends LitElement { ${!this._params.yaml ? html` - ${this.hass!.localize( - "ui.panel.lovelace.editor.suggest_card.create_own" - )} + ${!(this._sectionConfig && this._viewSupportsSection) + ? html` + + ${this.hass!.localize( + "ui.panel.lovelace.editor.suggest_card.create_own" + )} + + ` + : nothing} ` - : ""} + : nothing} `; } From aac00a5e78c6955da8d90d3fbbaa5e08732e7091 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 4 Mar 2024 16:33:31 +0100 Subject: [PATCH 19/35] Change wording from add section to create section (#19978) * Rename add section to create section * update function name --- src/panels/lovelace/views/hui-sections-view.ts | 14 +++++++------- src/translations/en.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/panels/lovelace/views/hui-sections-view.ts b/src/panels/lovelace/views/hui-sections-view.ts index 2e2320fa54..54a50829ec 100644 --- a/src/panels/lovelace/views/hui-sections-view.ts +++ b/src/panels/lovelace/views/hui-sections-view.ts @@ -119,13 +119,13 @@ export class SectionsView extends LitElement implements LovelaceViewElement { ${editMode ? html`