diff --git a/cast/src/receiver/layout/hc-main.ts b/cast/src/receiver/layout/hc-main.ts index c729b14556..e21225d543 100644 --- a/cast/src/receiver/layout/hc-main.ts +++ b/cast/src/receiver/layout/hc-main.ts @@ -36,6 +36,7 @@ import { HassElement } from "../../../../src/state/hass-element"; import { castContext } from "../cast_context"; import "./hc-launch-screen"; import { getPanelTitleFromUrlPath } from "../../../../src/data/panel"; +import { checkLovelaceConfig } from "../../../../src/panels/lovelace/common/check-lovelace-config"; const DEFAULT_CONFIG: LovelaceDashboardStrategyConfig = { strategy: { @@ -365,7 +366,9 @@ export class HcMain extends HassElement { this._urlPath || "lovelace" ); castContext.setApplicationState(title || ""); - this._lovelaceConfig = lovelaceConfig; + this._lovelaceConfig = checkLovelaceConfig( + lovelaceConfig + ) as LovelaceConfig; } private _handleShowDemo(_msg: ShowDemoMessage) { diff --git a/src/data/lovelace/config/section.ts b/src/data/lovelace/config/section.ts index d9f1065530..ad2c66e2aa 100644 --- a/src/data/lovelace/config/section.ts +++ b/src/data/lovelace/config/section.ts @@ -3,10 +3,13 @@ import type { LovelaceCardConfig } from "./card"; import type { LovelaceStrategyConfig } from "./strategy"; export interface LovelaceBaseSectionConfig { - title?: string; visibility?: Condition[]; column_span?: number; row_span?: number; + /** + * @deprecated Use heading card instead. + */ + title?: string; } export interface LovelaceSectionConfig extends LovelaceBaseSectionConfig { diff --git a/src/panels/lovelace/common/check-lovelace-config.ts b/src/panels/lovelace/common/check-lovelace-config.ts new file mode 100644 index 0000000000..a084906ec7 --- /dev/null +++ b/src/panels/lovelace/common/check-lovelace-config.ts @@ -0,0 +1,68 @@ +import { + isStrategySection, + LovelaceSectionRawConfig, +} from "../../../data/lovelace/config/section"; +import { + isStrategyDashboard, + LovelaceRawConfig, +} from "../../../data/lovelace/config/types"; +import { + isStrategyView, + LovelaceViewRawConfig, +} from "../../../data/lovelace/config/view"; + +export const checkLovelaceConfig = ( + config: LovelaceRawConfig +): LovelaceRawConfig => { + if (isStrategyDashboard(config)) { + return config; + } + + const updatedConfig = { ...config }; + + if (updatedConfig.views) { + updatedConfig.views = updatedConfig.views.map(checkViewConfig); + } + + return updatedConfig; +}; + +export const checkViewConfig = ( + view: LovelaceViewRawConfig +): LovelaceViewRawConfig => { + if (isStrategyView(view)) { + return view; + } + + const updatedView = { ...view }; + + // Remove empty badges + if (updatedView.badges && !updatedView.badges.every(Boolean)) { + updatedView.badges = updatedView.badges!.filter(Boolean); + } + + // Migrate sections + if (updatedView.sections) { + updatedView.sections = updatedView.sections!.map(checkSectionConfig); + } + + return updatedView; +}; + +export const checkSectionConfig = ( + section: LovelaceSectionRawConfig +): LovelaceSectionRawConfig => { + const updatedSection = { ...section }; + + // Move title to a heading card + if (section.title) { + // Only add card if it's not a strategy section + if (!isStrategySection(updatedSection)) { + const card = { type: "heading", heading: updatedSection.title }; + updatedSection.cards = [card, ...(updatedSection.cards || [])]; + } + + delete updatedSection.title; + } + return updatedSection; +}; diff --git a/src/panels/lovelace/editor/section-editor/hui-section-settings-editor.ts b/src/panels/lovelace/editor/section-editor/hui-section-settings-editor.ts index d7a9a96749..dcc922c3e8 100644 --- a/src/panels/lovelace/editor/section-editor/hui-section-settings-editor.ts +++ b/src/panels/lovelace/editor/section-editor/hui-section-settings-editor.ts @@ -11,7 +11,6 @@ import { LovelaceViewConfig } from "../../../../data/lovelace/config/view"; import { HomeAssistant } from "../../../../types"; type SettingsData = { - title: string; column_span?: number; }; @@ -26,10 +25,6 @@ export class HuiDialogEditSection extends LitElement { private _schema = memoizeOne( (maxColumns: number) => [ - { - name: "title", - selector: { text: {} }, - }, { name: "column_span", selector: { @@ -45,7 +40,6 @@ export class HuiDialogEditSection extends LitElement { render() { const data: SettingsData = { - title: this.config.title || "", column_span: this.config.column_span || 1, }; @@ -83,14 +77,9 @@ export class HuiDialogEditSection extends LitElement { const newConfig: LovelaceSectionRawConfig = { ...this.config, - title: newData.title, column_span: newData.column_span, }; - if (!newConfig.title) { - delete newConfig.title; - } - fireEvent(this, "value-changed", { value: newConfig }); } } diff --git a/src/panels/lovelace/ha-panel-lovelace.ts b/src/panels/lovelace/ha-panel-lovelace.ts index a69f8ef6a4..7d8e53cf09 100644 --- a/src/panels/lovelace/ha-panel-lovelace.ts +++ b/src/panels/lovelace/ha-panel-lovelace.ts @@ -19,10 +19,6 @@ import { LovelaceRawConfig, saveConfig, } from "../../data/lovelace/config/types"; -import { - isStrategyView, - LovelaceViewConfig, -} from "../../data/lovelace/config/view"; import { fetchResources } from "../../data/lovelace/resource"; import { WindowWithPreloads } from "../../data/preloads"; import "../../layouts/hass-error-screen"; @@ -30,6 +26,7 @@ import "../../layouts/hass-loading-screen"; import { HomeAssistant, PanelInfo, Route } from "../../types"; import { showToast } from "../../util/toast"; import { loadLovelaceResources } from "./common/load-resources"; +import { checkLovelaceConfig } from "./common/check-lovelace-config"; import { showSaveDialog } from "./editor/show-save-config-dialog"; import "./hui-root"; import { generateLovelaceDashboardStrategy } from "./strategies/get-strategy"; @@ -321,26 +318,8 @@ export class LovelacePanel extends LitElement { } private _checkLovelaceConfig(config: LovelaceRawConfig) { - // Somehow there can be badges with value null, we remove those - if (isStrategyDashboard(config)) { - return config; - } - let checkedConfig = !Object.isFrozen(config) ? config : undefined; - config.views.forEach((view, index) => { - if (isStrategyView(view)) { - return; - } - if (view.badges && !view.badges.every(Boolean)) { - checkedConfig = checkedConfig || { - ...config, - views: [...config.views], - }; - const updatedView = { ...view } as LovelaceViewConfig; - updatedView.badges = view.badges.filter(Boolean); - checkedConfig.views[index] = updatedView; - } - }); - return checkedConfig ? deepFreeze(checkedConfig) : config; + const checkedConfig = checkLovelaceConfig(config); + return deepFreeze(checkedConfig); } private _setLovelaceConfig( diff --git a/src/panels/lovelace/views/hui-sections-view.ts b/src/panels/lovelace/views/hui-sections-view.ts index c327679c3c..4e3c7e23bd 100644 --- a/src/panels/lovelace/views/hui-sections-view.ts +++ b/src/panels/lovelace/views/hui-sections-view.ts @@ -1,5 +1,5 @@ import { ResizeController } from "@lit-labs/observers/resize-controller"; -import { mdiArrowAll, mdiDelete, mdiPencil, mdiViewGridPlus } from "@mdi/js"; +import { mdiDelete, mdiDrag, mdiPencil, mdiViewGridPlus } from "@mdi/js"; import { CSSResultGroup, LitElement, @@ -182,26 +182,16 @@ export class SectionsView extends LitElement implements LovelaceViewElement { })} > ${ - sectionConfig?.title || this.lovelace?.editMode + this.lovelace?.editMode ? html`