diff --git a/src/panels/lovelace/components/hui-card-edit-mode.ts b/src/panels/lovelace/components/hui-card-edit-mode.ts index ff22edd0c5..8d88907260 100644 --- a/src/panels/lovelace/components/hui-card-edit-mode.ts +++ b/src/panels/lovelace/components/hui-card-edit-mode.ts @@ -23,8 +23,10 @@ import type { LovelaceCardConfig } from "../../../data/lovelace/config/card"; import { haStyle } from "../../../resources/styles"; import type { HomeAssistant } from "../../../types"; import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog"; +import { addCard } from "../editor/config-util"; import type { LovelaceCardPath } from "../editor/lovelace-path"; import { + findLovelaceContainer, findLovelaceItems, getLovelaceContainerPath, parseLovelaceCardPath, @@ -253,14 +255,24 @@ export class HuiCardEditMode extends LitElement { } private _duplicateCard(): void { - const { cardIndex } = parseLovelaceCardPath(this.path!); + const { cardIndex, sectionIndex } = parseLovelaceCardPath(this.path!); const containerPath = getLovelaceContainerPath(this.path!); + const sectionConfig = + sectionIndex !== undefined + ? findLovelaceContainer(this.lovelace!.config, containerPath) + : undefined; + const cardConfig = this._cards![cardIndex]; + showEditCardDialog(this, { lovelaceConfig: this.lovelace!.config, - saveConfig: this.lovelace!.saveConfig, - path: containerPath, + saveCardConfig: async (config) => { + const newConfig = addCard(this.lovelace!.config, containerPath, config); + await this.lovelace!.saveConfig(newConfig); + }, cardConfig, + sectionConfig, + isNew: true, }); } diff --git a/src/panels/lovelace/components/hui-card-options.ts b/src/panels/lovelace/components/hui-card-options.ts index d27c21d9ca..b74d609f96 100644 --- a/src/panels/lovelace/components/hui-card-options.ts +++ b/src/panels/lovelace/components/hui-card-options.ts @@ -278,9 +278,12 @@ export class HuiCardOptions extends LitElement { const cardConfig = this._cards![cardIndex]; showEditCardDialog(this, { lovelaceConfig: this.lovelace!.config, - saveConfig: this.lovelace!.saveConfig, - path: containerPath, + saveCardConfig: async (config) => { + const newConfig = addCard(this.lovelace!.config, containerPath, config); + await this.lovelace!.saveConfig(newConfig); + }, cardConfig, + isNew: true, }); } diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts index dcc3e49167..403bc7c31e 100644 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts @@ -3,10 +3,10 @@ import "@material/mwc-tab/mwc-tab"; import { mdiClose } from "@mdi/js"; import type { CSSResultGroup } from "lit"; import { css, html, LitElement, nothing } from "lit"; -import { ifDefined } from "lit/directives/if-defined"; import { customElement, property, state } from "lit/decorators"; import { cache } from "lit/directives/cache"; import { classMap } from "lit/directives/class-map"; +import { ifDefined } from "lit/directives/if-defined"; import memoize from "memoize-one"; import { fireEvent } from "../../../../common/dom/fire_event"; import { computeDomain } from "../../../../common/entity/compute_domain"; @@ -24,6 +24,7 @@ import { computeCards, computeSection, } from "../../common/generate-lovelace-config"; +import { addCard } from "../config-util"; import { findLovelaceContainer, parseLovelaceContainerPath, @@ -241,11 +242,24 @@ export class HuiCreateDialogCard } } + const lovelaceConfig = this._params!.lovelaceConfig; + const containerPath = this._params!.path; + const saveConfig = this._params!.saveConfig; + + const sectionConfig = + containerPath.length === 2 + ? findLovelaceContainer(lovelaceConfig, containerPath) + : undefined; + showEditCardDialog(this, { - lovelaceConfig: this._params!.lovelaceConfig, - saveConfig: this._params!.saveConfig, - path: this._params!.path, + lovelaceConfig, + saveCardConfig: async (newCardConfig) => { + const newConfig = addCard(lovelaceConfig, containerPath, newCardConfig); + await saveConfig(newConfig); + }, cardConfig: config, + sectionConfig, + isNew: true, }); this.closeDialog(); 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 e0720420f2..a1fc6de482 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 @@ -13,7 +13,6 @@ import "../../../../components/ha-dialog-header"; import "../../../../components/ha-icon-button"; import type { LovelaceCardConfig } from "../../../../data/lovelace/config/card"; import type { LovelaceSectionConfig } from "../../../../data/lovelace/config/section"; -import type { LovelaceViewConfig } from "../../../../data/lovelace/config/view"; import { getCustomCardEntry, isCustomType, @@ -23,13 +22,12 @@ import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog- import type { HassDialog } from "../../../../dialogs/make-dialog-manager"; import { haStyleDialog } from "../../../../resources/styles"; import type { HomeAssistant } from "../../../../types"; +import { showToast } from "../../../../util/toast"; import { showSaveSuccessToast } from "../../../../util/toast-saved-success"; import "../../cards/hui-card"; import "../../sections/hui-section"; -import { addCard, replaceCard } from "../config-util"; import { getCardDocumentationURL } from "../get-dashboard-documentation-url"; import type { ConfigChangedEvent } from "../hui-element-editor"; -import { findLovelaceContainer } from "../lovelace-path"; import type { GUIModeChangedEvent } from "../types"; import "./hui-card-element-editor"; import type { HuiCardElementEditor } from "./hui-card-element-editor"; @@ -59,9 +57,7 @@ export class HuiDialogEditCard @state() private _cardConfig?: LovelaceCardConfig; - @state() private _containerConfig!: - | LovelaceViewConfig - | LovelaceSectionConfig; + @state() private _sectionConfig?: LovelaceSectionConfig; @state() private _saving = false; @@ -85,23 +81,10 @@ export class HuiDialogEditCard this._GUImode = true; this._guiModeAvailable = true; - const containerConfig = findLovelaceContainer( - params.lovelaceConfig, - params.path - ); + this._sectionConfig = this._params.sectionConfig; - if ("strategy" in containerConfig) { - throw new Error("Can't edit strategy"); - } - - this._containerConfig = containerConfig; - - if ("cardConfig" in params) { - this._cardConfig = params.cardConfig; - this._dirty = true; - } else { - this._cardConfig = this._containerConfig.cards?.[params.cardIndex]; - } + this._cardConfig = params.cardConfig; + this._dirty = Boolean(this._params.isNew); this.large = false; if (this._cardConfig && !Object.isFrozen(this._cardConfig)) { @@ -156,12 +139,12 @@ export class HuiDialogEditCard }; protected render() { - if (!this._params) { + if (!this._params || !this._cardConfig) { return nothing; } let heading: string; - if (this._cardConfig && this._cardConfig.type) { + if (this._cardConfig.type) { let cardName: string | undefined; if (isCustomType(this._cardConfig.type)) { // prettier-ignore @@ -181,13 +164,6 @@ export class HuiDialogEditCard "ui.panel.lovelace.editor.edit_card.typed_header", { type: cardName } ); - } else if (!this._cardConfig) { - heading = this._containerConfig.title - ? this.hass!.localize( - "ui.panel.lovelace.editor.edit_card.pick_card_view_title", - { name: this._containerConfig.title } - ) - : this.hass!.localize("ui.panel.lovelace.editor.edit_card.pick_card"); } else { heading = this.hass!.localize( "ui.panel.lovelace.editor.edit_card.header" @@ -230,10 +206,8 @@ export class HuiDialogEditCard
- ${this._isInSection + ${this._sectionConfig ? html` { + (cardConfig: LovelaceCardConfig) => { const { cards, title, ...containerConfig } = this - ._containerConfig as LovelaceSectionConfig; + ._sectionConfig as LovelaceSectionConfig; return { ...containerConfig, @@ -411,20 +381,18 @@ export class HuiDialogEditCard return; } this._saving = true; - const path = this._params!.path; - await this._params!.saveConfig( - "cardConfig" in this._params! - ? addCard(this._params!.lovelaceConfig, path, this._cardConfig!) - : replaceCard( - this._params!.lovelaceConfig, - [...path, this._params!.cardIndex], - this._cardConfig! - ) - ); - this._saving = false; - this._dirty = false; - showSaveSuccessToast(this, this.hass); - this.closeDialog(); + try { + await this._params!.saveCardConfig(this._cardConfig!); + this._saving = false; + this._dirty = false; + showSaveSuccessToast(this, this.hass); + this.closeDialog(); + } catch (err: any) { + showToast(this, { + message: err.message, + }); + this._saving = false; + } } static get styles(): CSSResultGroup { diff --git a/src/panels/lovelace/editor/card-editor/show-edit-card-dialog.ts b/src/panels/lovelace/editor/card-editor/show-edit-card-dialog.ts index a1da36b660..ae3930ba55 100644 --- a/src/panels/lovelace/editor/card-editor/show-edit-card-dialog.ts +++ b/src/panels/lovelace/editor/card-editor/show-edit-card-dialog.ts @@ -1,20 +1,15 @@ import { fireEvent } from "../../../../common/dom/fire_event"; import type { LovelaceCardConfig } from "../../../../data/lovelace/config/card"; +import type { LovelaceSectionConfig } from "../../../../data/lovelace/config/section"; import type { LovelaceConfig } from "../../../../data/lovelace/config/types"; -import type { LovelaceContainerPath } from "../lovelace-path"; -export type EditCardDialogParams = { +export interface EditCardDialogParams { lovelaceConfig: LovelaceConfig; - saveConfig: (config: LovelaceConfig) => void; - path: LovelaceContainerPath; -} & ( - | { - cardIndex: number; - } - | { - cardConfig: LovelaceCardConfig; - } -); + saveCardConfig: (config: LovelaceCardConfig) => void; + cardConfig: LovelaceCardConfig; + sectionConfig?: LovelaceSectionConfig; + isNew?: boolean; +} export const importEditCardDialog = () => import("./hui-dialog-edit-card"); diff --git a/src/panels/lovelace/sections/hui-section.ts b/src/panels/lovelace/sections/hui-section.ts index c9aa927aed..5155e996ea 100644 --- a/src/panels/lovelace/sections/hui-section.ts +++ b/src/panels/lovelace/sections/hui-section.ts @@ -21,6 +21,7 @@ import { import { createSectionElement } from "../create-element/create-section-element"; import { showCreateCardDialog } from "../editor/card-editor/show-create-card-dialog"; import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog"; +import { replaceCard } from "../editor/config-util"; import { performDeleteCard } from "../editor/delete-card"; import { parseLovelaceCardPath } from "../editor/lovelace-path"; import { generateLovelaceSectionStrategy } from "../strategies/get-strategy"; @@ -253,11 +254,23 @@ export class HuiSection extends ReactiveElement { ev.stopPropagation(); if (!this.lovelace) return; const { cardIndex } = parseLovelaceCardPath(ev.detail.path); + const sectionConfig = this.config; + if (isStrategySection(sectionConfig)) { + return; + } + const cardConfig = sectionConfig.cards![cardIndex]; showEditCardDialog(this, { lovelaceConfig: this.lovelace.config, - saveConfig: this.lovelace.saveConfig, - path: [this.viewIndex, this.index], - cardIndex, + saveCardConfig: async (newCardConfig) => { + const newConfig = replaceCard( + this.lovelace!.config, + [this.viewIndex, this.index, cardIndex], + newCardConfig + ); + await this.lovelace!.saveConfig(newConfig); + }, + sectionConfig, + cardConfig, }); }); this._layoutElement.addEventListener("ll-delete-card", (ev) => { diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index 7111c20d01..f862915c86 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -21,6 +21,7 @@ import { showCreateBadgeDialog } from "../editor/badge-editor/show-create-badge- import { showEditBadgeDialog } from "../editor/badge-editor/show-edit-badge-dialog"; import { showCreateCardDialog } from "../editor/card-editor/show-create-card-dialog"; import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog"; +import { replaceCard } from "../editor/config-util"; import { type DeleteBadgeParams, performDeleteBadge, @@ -270,11 +271,22 @@ export class HUIView extends ReactiveElement { }); this._layoutElement.addEventListener("ll-edit-card", (ev) => { const { cardIndex } = parseLovelaceCardPath(ev.detail.path); + const viewConfig = this.lovelace!.config.views[this.index]; + if (isStrategyView(viewConfig)) { + return; + } + const cardConfig = viewConfig.cards![cardIndex]; showEditCardDialog(this, { lovelaceConfig: this.lovelace.config, - saveConfig: this.lovelace.saveConfig, - path: [this.index], - cardIndex, + saveCardConfig: async (newCardConfig) => { + const newConfig = replaceCard( + this.lovelace!.config, + [this.index, cardIndex], + newCardConfig + ); + await this.lovelace.saveConfig(newConfig); + }, + cardConfig, }); }); this._layoutElement.addEventListener("ll-delete-card", (ev) => {