Skip to content

Commit

Permalink
Show card preview inside section in card editor (#21065)
Browse files Browse the repository at this point in the history
* Show card inside section in card editor

* Replace edit mode by preview

* Add backward compatibility for custom cards

* Re-order props
  • Loading branch information
piitaya authored Jun 21, 2024
1 parent eb0579d commit f789464
Show file tree
Hide file tree
Showing 17 changed files with 101 additions and 45 deletions.
14 changes: 9 additions & 5 deletions src/panels/lovelace/cards/hui-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ declare global {
export class HuiCard extends ReactiveElement {
@property({ attribute: false }) public hass?: HomeAssistant;

@property({ type: Boolean }) public editMode = false;
@property({ type: Boolean }) public preview = false;

@property({ type: Boolean }) public isPanel = false;

Expand Down Expand Up @@ -89,7 +89,9 @@ export class HuiCard extends ReactiveElement {
private _createElement(config: LovelaceCardConfig) {
const element = createCardElement(config);
element.hass = this.hass;
element.editMode = this.editMode;
element.preview = this.preview;
// For backwards compatibility
(element as any).editMode = this.preview;
// Update element when the visibility of the card changes (e.g. conditional card or filter card)
element.addEventListener("card-visibility-changed", (ev: Event) => {
ev.stopPropagation();
Expand Down Expand Up @@ -135,9 +137,11 @@ export class HuiCard extends ReactiveElement {
this._buildElement(createErrorCardConfig(e.message, null));
}
}
if (changedProps.has("editMode")) {
if (changedProps.has("preview")) {
try {
this._element.editMode = this.editMode;
this._element.preview = this.preview;
// For backwards compatibility
(this._element as any).editMode = this.preview;
} catch (e: any) {
this._buildElement(createErrorCardConfig(e.message, null));
}
Expand Down Expand Up @@ -192,7 +196,7 @@ export class HuiCard extends ReactiveElement {

const visible =
forceVisible ||
this.editMode ||
this.preview ||
!this.config?.visibility ||
checkConditionsMet(this.config.visibility, this.hass);
this._setElementVisibility(visible);
Expand Down
4 changes: 2 additions & 2 deletions src/panels/lovelace/cards/hui-conditional-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ class HuiConditionalCard extends HuiConditionalBase implements LovelaceCard {
private _createCardElement(cardConfig: LovelaceCardConfig) {
const element = document.createElement("hui-card");
element.hass = this.hass;
element.editMode = this.editMode;
element.preview = this.preview;
element.config = cardConfig;
return element;
}

protected setVisibility(conditionMet: boolean): void {
const visible = this.editMode || conditionMet;
const visible = this.preview || conditionMet;
const previouslyHidden = this.hidden;
super.setVisibility(conditionMet);
if (previouslyHidden !== this.hidden) {
Expand Down
6 changes: 3 additions & 3 deletions src/panels/lovelace/cards/hui-entity-filter-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class HuiEntityFilterCard

@property({ type: Boolean }) public isPanel = false;

@property({ type: Boolean }) public editMode = false;
@property({ type: Boolean }) public preview = false;

@state() private _config?: EntityFilterCardConfig;

Expand Down Expand Up @@ -117,7 +117,7 @@ export class HuiEntityFilterCard
protected shouldUpdate(changedProps: PropertyValues): boolean {
if (this._element) {
this._element.hass = this.hass;
this._element.editMode = this.editMode;
this._element.preview = this.preview;
this._element.isPanel = this.isPanel;
}

Expand Down Expand Up @@ -247,7 +247,7 @@ export class HuiEntityFilterCard
private _createCardElement(cardConfig: LovelaceCardConfig) {
const element = document.createElement("hui-card");
element.hass = this.hass;
element.editMode = this.editMode;
element.preview = this.preview;
element.config = cardConfig;
return element;
}
Expand Down
2 changes: 1 addition & 1 deletion src/panels/lovelace/cards/hui-error-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ErrorCardConfig } from "./types";
export class HuiErrorCard extends LitElement implements LovelaceCard {
public hass?: HomeAssistant;

@property({ attribute: false }) public editMode = false;
@property({ attribute: false }) public preview = false;

@state() private _config?: ErrorCardConfig;

Expand Down
6 changes: 3 additions & 3 deletions src/panels/lovelace/cards/hui-markdown-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard {

@property({ attribute: false }) public hass?: HomeAssistant;

@property({ type: Boolean }) public editMode = false;
@property({ type: Boolean }) public preview = false;

@state() private _config?: MarkdownCardConfig;

Expand Down Expand Up @@ -163,12 +163,12 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard {
user: this.hass.user!.name,
},
strict: true,
report_errors: this.editMode,
report_errors: this.preview,
}
);
await this._unsubRenderTemplate;
} catch (e: any) {
if (this.editMode) {
if (this.preview) {
this._error = e.message;
this._errorLevel = undefined;
}
Expand Down
6 changes: 3 additions & 3 deletions src/panels/lovelace/cards/hui-stack-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>

@property({ attribute: false }) public hass?: HomeAssistant;

@property({ type: Boolean }) public editMode = false;
@property({ type: Boolean }) public preview = false;

@state() protected _cards?: HuiCard[];

Expand Down Expand Up @@ -58,7 +58,7 @@ export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
}
if (changedProperties.has("editMode")) {
this._cards.forEach((card) => {
card.editMode = this.editMode;
card.preview = this.preview;
});
}
}
Expand All @@ -67,7 +67,7 @@ export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
private _createCardElement(cardConfig: LovelaceCardConfig) {
const element = document.createElement("hui-card");
element.hass = this.hass;
element.editMode = this.editMode;
element.preview = this.preview;
element.config = cardConfig;
return element;
}
Expand Down
8 changes: 4 additions & 4 deletions src/panels/lovelace/components/hui-conditional-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ declare global {
export class HuiConditionalBase extends ReactiveElement {
@property({ attribute: false }) public hass?: HomeAssistant;

@property({ type: Boolean }) public editMode = false;
@property({ type: Boolean }) public preview = false;

@state() protected _config?: ConditionalCardConfig | ConditionalRowConfig;

Expand Down Expand Up @@ -116,7 +116,7 @@ export class HuiConditionalBase extends ReactiveElement {
changed.has("_element") ||
changed.has("_config") ||
changed.has("hass") ||
changed.has("editMode")
changed.has("preview")
) {
this._listenMediaQueries();
this._updateVisibility();
Expand All @@ -128,7 +128,7 @@ export class HuiConditionalBase extends ReactiveElement {
return;
}

this._element.editMode = this.editMode;
this._element.preview = this.preview;

const conditionMet = checkConditionsMet(
this._config!.conditions,
Expand All @@ -142,7 +142,7 @@ export class HuiConditionalBase extends ReactiveElement {
if (!this._element || !this.hass) {
return;
}
const visible = this.editMode || conditionMet;
const visible = this.preview || conditionMet;
if (this.hidden !== !visible) {
this.toggleAttribute("hidden", !visible);
this.style.setProperty("display", visible ? "" : "none");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class HuiDialogDeleteCard extends LitElement {
<hui-card
.hass=${this.hass}
.config=${this._cardConfig}
editMode
preview
></hui-card>
</div>
`
Expand Down
56 changes: 49 additions & 7 deletions src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
nothing,
} from "lit";
import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import type { HASSDomEvent } from "../../../../common/dom/fire_event";
import { fireEvent } from "../../../../common/dom/fire_event";
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
Expand All @@ -29,6 +30,7 @@ import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
import { haStyleDialog } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types";
import { showSaveSuccessToast } from "../../../../util/toast-saved-success";
import "../../sections/hui-section";
import { addCard, replaceCard } from "../config-util";
import { getCardDocumentationURL } from "../get-card-documentation-url";
import type { ConfigChangedEvent } from "../hui-element-editor";
Expand Down Expand Up @@ -245,12 +247,23 @@ export class HuiDialogEditCard
></hui-card-element-editor>
</div>
<div class="element-preview">
<hui-card
.hass=${this.hass}
.config=${this._cardConfig}
editMode
class=${this._error ? "blur" : ""}
></hui-card>
${this._isInSection
? html`
<hui-section
.hass=${this.hass}
.config=${this._cardConfigInSection(this._cardConfig)}
preview
class=${this._error ? "blur" : ""}
></hui-section>
`
: html`
<hui-card
.hass=${this.hass}
.config=${this._cardConfig}
preview
class=${this._error ? "blur" : ""}
></hui-card>
`}
${this._error
? html`
<ha-circular-progress
Expand Down Expand Up @@ -335,6 +348,22 @@ export class HuiDialogEditCard
this._cardEditorEl?.focusYamlEditor();
}

private get _isInSection() {
return this._params!.path.length === 2;
}

private _cardConfigInSection = memoizeOne(
(cardConfig?: LovelaceCardConfig) => {
const { cards, title, ...containerConfig } = this
._containerConfig as LovelaceSectionConfig;

return {
...containerConfig,
cards: cardConfig ? [cardConfig] : [],
};
}
);

private get _canSave(): boolean {
if (this._saving) {
return false;
Expand Down Expand Up @@ -454,9 +483,17 @@ export class HuiDialogEditCard
}
.content hui-card {
margin: 4px auto;
display: block;
padding: 4px;
margin: 0 auto;
max-width: 390px;
}
.content hui-section {
display: block;
padding: 4px;
margin: 0 auto;
max-width: var(--ha-view-sections-column-max-width, 500px);
}
.content .element-editor {
margin: 0 10px;
}
Expand All @@ -476,6 +513,11 @@ export class HuiDialogEditCard
margin: auto 0px;
max-width: 500px;
}
.content hui-section {
padding: 8px 10px;
margin: auto 0px;
max-width: var(--ha-view-sections-column-max-width, 500px);
}
}
.hidden {
display: none;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export class HuiDialogSuggestCard extends LitElement {
<hui-section
.hass=${this.hass}
.config=${this._sectionConfig}
preview
></hui-section>
</div>
`;
Expand All @@ -84,7 +85,11 @@ export class HuiDialogSuggestCard extends LitElement {
<div class="element-preview">
${this._cardConfig.map(
(cardConfig) => html`
<hui-card .hass=${this.hass} .config=${cardConfig}></hui-card>
<hui-card
.hass=${this.hass}
.config=${cardConfig}
preview
></hui-card>
`
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/panels/lovelace/entity-rows/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export type LovelaceRowConfig =

export interface LovelaceRow extends HTMLElement {
hass?: HomeAssistant;
editMode?: boolean;
preview?: boolean;
setConfig(config: LovelaceRowConfig);
}

Expand Down
10 changes: 7 additions & 3 deletions src/panels/lovelace/sections/hui-section.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export class HuiSection extends ReactiveElement {

@property({ attribute: false }) public lovelace?: Lovelace;

@property({ type: Boolean, reflect: true }) public preview = false;

@property({ type: Number }) public index!: number;

@property({ type: Number }) public viewIndex!: number;
Expand All @@ -56,7 +58,7 @@ export class HuiSection extends ReactiveElement {
private _createCardElement(cardConfig: LovelaceCardConfig) {
const element = document.createElement("hui-card");
element.hass = this.hass;
element.editMode = this.lovelace?.editMode || false;
element.preview = this.preview;
element.config = cardConfig;
element.addEventListener("card-updated", (ev: Event) => {
ev.stopPropagation();
Expand Down Expand Up @@ -118,8 +120,10 @@ export class HuiSection extends ReactiveElement {
}
if (changedProperties.has("lovelace")) {
this._layoutElement.lovelace = this.lovelace;
}
if (changedProperties.has("preview")) {
this._cards.forEach((element) => {
element.editMode = this.lovelace?.editMode || false;
element.preview = this.preview;
});
}
if (changedProperties.has("_cards")) {
Expand Down Expand Up @@ -205,7 +209,7 @@ export class HuiSection extends ReactiveElement {
}
const visible =
forceVisible ||
this.lovelace?.editMode ||
this.preview ||
!this.config.visibility ||
checkConditionsMet(this.config.visibility, this.hass);

Expand Down
2 changes: 1 addition & 1 deletion src/panels/lovelace/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export type LovelaceLayoutOptions = {
export interface LovelaceCard extends HTMLElement {
hass?: HomeAssistant;
isPanel?: boolean;
editMode?: boolean;
preview?: boolean;
getCardSize(): number | Promise<number>;
getLayoutOptions?(): LovelaceLayoutOptions;
setConfig(config: LovelaceCardConfig): void;
Expand Down
8 changes: 4 additions & 4 deletions src/panels/lovelace/views/hui-masonry-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,17 +248,17 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
});
}

private _addCardToColumn(columnEl, index, editMode) {
private _addCardToColumn(columnEl, index, preview) {
const card: HuiCard = this.cards[index];
if (!editMode || this.isStrategy) {
card.editMode = false;
if (!preview || this.isStrategy) {
card.preview = false;
columnEl.appendChild(card);
} else {
const wrapper = document.createElement("hui-card-options");
wrapper.hass = this.hass;
wrapper.lovelace = this.lovelace;
wrapper.path = [this.index!, index];
card.editMode = true;
card.preview = true;
wrapper.appendChild(card);
columnEl.appendChild(wrapper);
}
Expand Down
Loading

0 comments on commit f789464

Please sign in to comment.