mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Show card preview inside section in card editor (#21065)
* Show card inside section in card editor * Replace edit mode by preview * Add backward compatibility for custom cards * Re-order props
This commit is contained in:
parent
eb0579ddc5
commit
f78946447f
@ -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;
|
||||
|
||||
@ -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();
|
||||
@ -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));
|
||||
}
|
||||
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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[];
|
||||
|
||||
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
@ -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();
|
||||
@ -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,
|
||||
@ -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");
|
||||
|
@ -48,7 +48,7 @@ export class HuiDialogDeleteCard extends LitElement {
|
||||
<hui-card
|
||||
.hass=${this.hass}
|
||||
.config=${this._cardConfig}
|
||||
editMode
|
||||
preview
|
||||
></hui-card>
|
||||
</div>
|
||||
`
|
||||
|
@ -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";
|
||||
@ -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";
|
||||
@ -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
|
||||
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
|
@ -75,6 +75,7 @@ export class HuiDialogSuggestCard extends LitElement {
|
||||
<hui-section
|
||||
.hass=${this.hass}
|
||||
.config=${this._sectionConfig}
|
||||
preview
|
||||
></hui-section>
|
||||
</div>
|
||||
`;
|
||||
@ -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>
|
||||
|
@ -81,7 +81,7 @@ export type LovelaceRowConfig =
|
||||
|
||||
export interface LovelaceRow extends HTMLElement {
|
||||
hass?: HomeAssistant;
|
||||
editMode?: boolean;
|
||||
preview?: boolean;
|
||||
setConfig(config: LovelaceRowConfig);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -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();
|
||||
@ -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")) {
|
||||
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ export class PanelView extends LitElement implements LovelaceViewElement {
|
||||
card.isPanel = true;
|
||||
|
||||
if (this.isStrategy || !this.lovelace?.editMode) {
|
||||
card.editMode = false;
|
||||
card.preview = false;
|
||||
this._card = card;
|
||||
return;
|
||||
}
|
||||
@ -118,7 +118,7 @@ export class PanelView extends LitElement implements LovelaceViewElement {
|
||||
wrapper.lovelace = this.lovelace;
|
||||
wrapper.path = [this.index!, 0];
|
||||
wrapper.hidePosition = true;
|
||||
card.editMode = true;
|
||||
card.preview = true;
|
||||
wrapper.appendChild(card);
|
||||
this._card = wrapper;
|
||||
}
|
||||
|
@ -144,14 +144,14 @@ export class SideBarView extends LitElement implements LovelaceViewElement {
|
||||
const cardConfig = this._config?.cards?.[idx];
|
||||
let element: HuiCard | HuiCardOptions;
|
||||
if (this.isStrategy || !this.lovelace?.editMode) {
|
||||
card.editMode = false;
|
||||
card.preview = false;
|
||||
element = card;
|
||||
} else {
|
||||
element = document.createElement("hui-card-options");
|
||||
element.hass = this.hass;
|
||||
element.lovelace = this.lovelace;
|
||||
element.path = [this.index!, idx];
|
||||
card.editMode = true;
|
||||
card.preview = true;
|
||||
const movePositionButton = document.createElement("ha-icon-button");
|
||||
movePositionButton.slot = "buttons";
|
||||
const moveIcon = document.createElement("ha-svg-icon");
|
||||
|
@ -76,7 +76,7 @@ export class HUIView extends ReactiveElement {
|
||||
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
||||
const element = document.createElement("hui-card");
|
||||
element.hass = this.hass;
|
||||
element.editMode = this.lovelace.editMode;
|
||||
element.preview = this.lovelace.editMode;
|
||||
element.config = cardConfig;
|
||||
element.addEventListener("card-updated", (ev: Event) => {
|
||||
ev.stopPropagation();
|
||||
@ -109,6 +109,7 @@ export class HUIView extends ReactiveElement {
|
||||
element.lovelace = this.lovelace;
|
||||
element.config = sectionConfig;
|
||||
element.viewIndex = this.index;
|
||||
element.preview = this.lovelace.editMode;
|
||||
element.addEventListener(
|
||||
"ll-rebuild",
|
||||
(ev: Event) => {
|
||||
@ -214,7 +215,7 @@ export class HUIView extends ReactiveElement {
|
||||
}
|
||||
});
|
||||
this._cards.forEach((element) => {
|
||||
element.editMode = this.lovelace.editMode;
|
||||
element.preview = this.lovelace.editMode;
|
||||
});
|
||||
}
|
||||
if (changedProperties.has("_cards")) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user