mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 01:06:35 +00:00
Move card loading logic into hui-card (#21018)
* Move card rebuild to hui-card * Use hui card in stack card * add once to event * Do not use state * Use hui card in conditional card * Use editMode instead of lovelace in hui card * Fix edit mode * Use hui-card in card dialog and panel todo * Fix edit mode * Fix types * Migrate entity filter card * Update demo card * Fix UI view * Allow edit mode attribute * Remove unused condition * Remove unused section preview code * Remove useless check for config
This commit is contained in:
parent
a497f42f73
commit
433c00b73a
@ -1,8 +1,9 @@
|
|||||||
import "@material/mwc-button";
|
|
||||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { until } from "lit/directives/until";
|
import { until } from "lit/directives/until";
|
||||||
|
import { fireEvent } from "../../../src/common/dom/fire_event";
|
||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
|
import "../../../src/components/ha-button";
|
||||||
import "../../../src/components/ha-circular-progress";
|
import "../../../src/components/ha-circular-progress";
|
||||||
import { LovelaceCardConfig } from "../../../src/data/lovelace/config/card";
|
import { LovelaceCardConfig } from "../../../src/data/lovelace/config/card";
|
||||||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||||
@ -11,7 +12,6 @@ import {
|
|||||||
demoConfigs,
|
demoConfigs,
|
||||||
selectedDemoConfig,
|
selectedDemoConfig,
|
||||||
selectedDemoConfigIndex,
|
selectedDemoConfigIndex,
|
||||||
setDemoConfig,
|
|
||||||
} from "../configs/demo-configs";
|
} from "../configs/demo-configs";
|
||||||
|
|
||||||
@customElement("ha-demo-card")
|
@customElement("ha-demo-card")
|
||||||
@ -64,9 +64,9 @@ export class HADemoCard extends LitElement implements LovelaceCard {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mwc-button @click=${this._nextConfig} .disabled=${this._switching}>
|
<ha-button @click=${this._nextConfig} .disabled=${this._switching}>
|
||||||
${this.hass.localize("ui.panel.page-demo.cards.demo.next_demo")}
|
${this.hass.localize("ui.panel.page-demo.cards.demo.next_demo")}
|
||||||
</mwc-button>
|
</ha-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<p class="small-hidden">
|
<p class="small-hidden">
|
||||||
@ -87,9 +87,9 @@ export class HADemoCard extends LitElement implements LovelaceCard {
|
|||||||
</div>
|
</div>
|
||||||
<div class="actions small-hidden">
|
<div class="actions small-hidden">
|
||||||
<a href="https://www.home-assistant.io" target="_blank">
|
<a href="https://www.home-assistant.io" target="_blank">
|
||||||
<mwc-button>
|
<ha-button>
|
||||||
${this.hass.localize("ui.panel.page-demo.cards.demo.learn_more")}
|
${this.hass.localize("ui.panel.page-demo.cards.demo.learn_more")}
|
||||||
</mwc-button>
|
</ha-button>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
@ -113,13 +113,7 @@ export class HADemoCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
private async _updateConfig(index: number) {
|
private async _updateConfig(index: number) {
|
||||||
this._switching = true;
|
this._switching = true;
|
||||||
try {
|
fireEvent(this, "set-demo-config" as any, { index });
|
||||||
await setDemoConfig(this.hass, this.lovelace!, index);
|
|
||||||
} catch (err: any) {
|
|
||||||
alert("Failed to switch config :-(");
|
|
||||||
} finally {
|
|
||||||
this._switching = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
@ -149,7 +143,7 @@ export class HADemoCard extends LitElement implements LovelaceCard {
|
|||||||
height: 60px;
|
height: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.picker mwc-button {
|
.picker ha-button {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import type { LocalizeFunc } from "../../../src/common/translations/localize";
|
import type { LocalizeFunc } from "../../../src/common/translations/localize";
|
||||||
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||||
import { selectedDemoConfig } from "../configs/demo-configs";
|
import {
|
||||||
|
selectedDemoConfig,
|
||||||
|
selectedDemoConfigIndex,
|
||||||
|
setDemoConfig,
|
||||||
|
} from "../configs/demo-configs";
|
||||||
import "../custom-cards/cast-demo-row";
|
import "../custom-cards/cast-demo-row";
|
||||||
import "../custom-cards/ha-demo-card";
|
import "../custom-cards/ha-demo-card";
|
||||||
import type { HADemoCard } from "../custom-cards/ha-demo-card";
|
|
||||||
|
|
||||||
export const mockLovelace = (
|
export const mockLovelace = (
|
||||||
hass: MockHomeAssistant,
|
hass: MockHomeAssistant,
|
||||||
@ -19,17 +22,22 @@ export const mockLovelace = (
|
|||||||
hass.mockWS("lovelace/resources", () => Promise.resolve([]));
|
hass.mockWS("lovelace/resources", () => Promise.resolve([]));
|
||||||
};
|
};
|
||||||
|
|
||||||
customElements.whenDefined("hui-card").then(() => {
|
customElements.whenDefined("hui-root").then(() => {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const HUIView = customElements.get("hui-card");
|
const HUIRoot = customElements.get("hui-root")!;
|
||||||
// Patch HUI-VIEW to make the lovelace object available to the demo card
|
|
||||||
const oldCreateCard = HUIView!.prototype.createElement;
|
|
||||||
|
|
||||||
HUIView!.prototype.createElement = function (config) {
|
const oldFirstUpdated = HUIRoot.prototype.firstUpdated;
|
||||||
const el = oldCreateCard.call(this, config);
|
|
||||||
if (config.type === "custom:ha-demo-card") {
|
HUIRoot.prototype.firstUpdated = function (changedProperties) {
|
||||||
(el as HADemoCard).lovelace = this.lovelace;
|
oldFirstUpdated.call(this, changedProperties);
|
||||||
|
this.addEventListener("set-demo-config", async (ev) => {
|
||||||
|
const index = (ev as CustomEvent).detail.index;
|
||||||
|
try {
|
||||||
|
await setDemoConfig(this.hass, this.lovelace!, index);
|
||||||
|
} catch (err: any) {
|
||||||
|
setDemoConfig(this.hass, this.lovelace!, selectedDemoConfigIndex);
|
||||||
|
alert("Failed to switch config :-(");
|
||||||
}
|
}
|
||||||
return el;
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import { load } from "js-yaml";
|
import { load } from "js-yaml";
|
||||||
import { html, css, LitElement, PropertyValues } from "lit";
|
import { LitElement, PropertyValueMap, css, html, nothing } from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
import { createCardElement } from "../../../src/panels/lovelace/create-element/create-card-element";
|
import memoizeOne from "memoize-one";
|
||||||
|
import "../../../src/panels/lovelace/cards/hui-card";
|
||||||
|
import type { HuiCard } from "../../../src/panels/lovelace/cards/hui-card";
|
||||||
import { HomeAssistant } from "../../../src/types";
|
import { HomeAssistant } from "../../../src/types";
|
||||||
|
|
||||||
export interface DemoCardConfig {
|
export interface DemoCardConfig {
|
||||||
@ -19,7 +21,12 @@ class DemoCard extends LitElement {
|
|||||||
|
|
||||||
@state() private _size?: number;
|
@state() private _size?: number;
|
||||||
|
|
||||||
@query("#card") private _card!: HTMLElement;
|
@query("hui-card", false) private _card?: HuiCard;
|
||||||
|
|
||||||
|
private _config = memoizeOne((config: string) => {
|
||||||
|
const c = (load(config) as any)[0];
|
||||||
|
return c;
|
||||||
|
});
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
@ -30,63 +37,32 @@ class DemoCard extends LitElement {
|
|||||||
: ""}
|
: ""}
|
||||||
</h2>
|
</h2>
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<div id="card"></div>
|
<hui-card
|
||||||
${this.showConfig ? html`<pre>${this.config.config.trim()}</pre>` : ""}
|
.config=${this._config(this.config.config)}
|
||||||
|
.hass=${this.hass}
|
||||||
|
@card-updated=${this._cardUpdated}
|
||||||
|
></hui-card>
|
||||||
|
${this.showConfig
|
||||||
|
? html`<pre>${this.config.config.trim()}</pre>`
|
||||||
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
updated(changedProps: PropertyValues) {
|
private async _cardUpdated(ev) {
|
||||||
super.updated(changedProps);
|
|
||||||
|
|
||||||
if (changedProps.has("config")) {
|
|
||||||
const card = this._card;
|
|
||||||
while (card.lastChild) {
|
|
||||||
card.removeChild(card.lastChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
const el = this._createCardElement((load(this.config.config) as any)[0]);
|
|
||||||
card.appendChild(el);
|
|
||||||
this._getSize(el);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changedProps.has("hass")) {
|
|
||||||
const card = this._card.lastChild;
|
|
||||||
if (card) {
|
|
||||||
(card as any).hass = this.hass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async _getSize(el) {
|
|
||||||
await customElements.whenDefined(el.localName);
|
|
||||||
|
|
||||||
if (!("getCardSize" in el)) {
|
|
||||||
this._size = undefined;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._size = await el.getCardSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
_createCardElement(cardConfig) {
|
|
||||||
const element = createCardElement(cardConfig);
|
|
||||||
if (this.hass) {
|
|
||||||
element.hass = this.hass;
|
|
||||||
}
|
|
||||||
element.addEventListener(
|
|
||||||
"ll-rebuild",
|
|
||||||
(ev) => {
|
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this._rebuildCard(element, cardConfig);
|
this._updateSize();
|
||||||
},
|
|
||||||
{ once: true }
|
|
||||||
);
|
|
||||||
return element;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_rebuildCard(cardElToReplace, config) {
|
private async _updateSize() {
|
||||||
const newCardEl = this._createCardElement(config);
|
this._size = await this._card?.getCardSize();
|
||||||
cardElToReplace.parentElement.replaceChild(newCardEl, cardElToReplace);
|
}
|
||||||
|
|
||||||
|
protected update(
|
||||||
|
_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>
|
||||||
|
): void {
|
||||||
|
super.update(_changedProperties);
|
||||||
|
this._updateSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = css`
|
static styles = css`
|
||||||
@ -101,7 +77,7 @@ class DemoCard extends LitElement {
|
|||||||
font-size: 0.5em;
|
font-size: 0.5em;
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
}
|
}
|
||||||
#card {
|
hui-card {
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { PropertyValues, ReactiveElement } from "lit";
|
import { PropertyValueMap, PropertyValues, ReactiveElement } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { MediaQueriesListener } from "../../../common/dom/media_query";
|
import { MediaQueriesListener } from "../../../common/dom/media_query";
|
||||||
import "../../../components/ha-svg-icon";
|
import "../../../components/ha-svg-icon";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||||
@ -10,23 +11,41 @@ import {
|
|||||||
checkConditionsMet,
|
checkConditionsMet,
|
||||||
} from "../common/validate-condition";
|
} from "../common/validate-condition";
|
||||||
import { createCardElement } from "../create-element/create-card-element";
|
import { createCardElement } from "../create-element/create-card-element";
|
||||||
import type { Lovelace, LovelaceCard, LovelaceLayoutOptions } from "../types";
|
import { createErrorCardConfig } from "../create-element/create-element-base";
|
||||||
|
import type { LovelaceCard, LovelaceLayoutOptions } from "../types";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
"card-visibility-changed": { value: boolean };
|
"card-visibility-changed": { value: boolean };
|
||||||
|
"card-updated": undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@customElement("hui-card")
|
@customElement("hui-card")
|
||||||
export class HuiCard extends ReactiveElement {
|
export class HuiCard extends ReactiveElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public lovelace?: Lovelace;
|
@property({ type: Boolean }) public editMode = false;
|
||||||
|
|
||||||
@property({ attribute: false }) public isPanel = false;
|
@property({ type: Boolean }) public isPanel = false;
|
||||||
|
|
||||||
@state() public _config?: LovelaceCardConfig;
|
set config(config: LovelaceCardConfig | undefined) {
|
||||||
|
if (!config) return;
|
||||||
|
if (config.type !== this._config?.type) {
|
||||||
|
this._buildElement(config);
|
||||||
|
} else if (config !== this.config) {
|
||||||
|
this._element?.setConfig(config);
|
||||||
|
fireEvent(this, "card-updated");
|
||||||
|
}
|
||||||
|
this._config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
public get config() {
|
||||||
|
return this._config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _config?: LovelaceCardConfig;
|
||||||
|
|
||||||
private _element?: LovelaceCard;
|
private _element?: LovelaceCard;
|
||||||
|
|
||||||
@ -44,7 +63,7 @@ export class HuiCard extends ReactiveElement {
|
|||||||
public connectedCallback() {
|
public connectedCallback() {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
this._listenMediaQueries();
|
this._listenMediaQueries();
|
||||||
this._updateElement();
|
this._updateVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getCardSize(): number | Promise<number> {
|
public getCardSize(): number | Promise<number> {
|
||||||
@ -56,7 +75,7 @@ export class HuiCard extends ReactiveElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getLayoutOptions(): LovelaceLayoutOptions {
|
public getLayoutOptions(): LovelaceLayoutOptions {
|
||||||
const configOptions = this._config?.layout_options ?? {};
|
const configOptions = this.config?.layout_options ?? {};
|
||||||
if (this._element) {
|
if (this._element) {
|
||||||
const cardOptions = this._element.getLayoutOptions?.() ?? {};
|
const cardOptions = this._element.getLayoutOptions?.() ?? {};
|
||||||
return {
|
return {
|
||||||
@ -67,51 +86,76 @@ export class HuiCard extends ReactiveElement {
|
|||||||
return configOptions;
|
return configOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public to make demo happy
|
private _createElement(config: LovelaceCardConfig) {
|
||||||
public createElement(config: LovelaceCardConfig) {
|
const element = createCardElement(config);
|
||||||
const element = createCardElement(config) as LovelaceCard;
|
|
||||||
element.hass = this.hass;
|
element.hass = this.hass;
|
||||||
element.editMode = this.lovelace?.editMode;
|
element.editMode = this.editMode;
|
||||||
// Update element when the visibility of the card changes (e.g. conditional card or filter card)
|
// Update element when the visibility of the card changes (e.g. conditional card or filter card)
|
||||||
element.addEventListener("card-visibility-changed", (ev) => {
|
element.addEventListener("card-visibility-changed", (ev: Event) => {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this._updateElement();
|
this._updateVisibility();
|
||||||
});
|
});
|
||||||
|
element.addEventListener(
|
||||||
|
"ll-upgrade",
|
||||||
|
(ev: Event) => {
|
||||||
|
ev.stopPropagation();
|
||||||
|
fireEvent(this, "card-updated");
|
||||||
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
|
element.addEventListener(
|
||||||
|
"ll-rebuild",
|
||||||
|
(ev: Event) => {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this._buildElement(config);
|
||||||
|
fireEvent(this, "card-updated");
|
||||||
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(config: LovelaceCardConfig): void {
|
private _buildElement(config: LovelaceCardConfig) {
|
||||||
if (this._config === config) {
|
this._element = this._createElement(config);
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._config = config;
|
|
||||||
this._element = this.createElement(config);
|
|
||||||
|
|
||||||
while (this.lastChild) {
|
while (this.lastChild) {
|
||||||
this.removeChild(this.lastChild);
|
this.removeChild(this.lastChild);
|
||||||
}
|
}
|
||||||
this.appendChild(this._element!);
|
this._updateVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected update(changedProperties: PropertyValues<typeof this>) {
|
protected update(changedProps: PropertyValues<typeof this>) {
|
||||||
super.update(changedProperties);
|
super.update(changedProps);
|
||||||
|
|
||||||
if (this._element) {
|
if (this._element) {
|
||||||
if (changedProperties.has("hass")) {
|
if (changedProps.has("hass")) {
|
||||||
|
try {
|
||||||
this._element.hass = this.hass;
|
this._element.hass = this.hass;
|
||||||
|
} catch (e: any) {
|
||||||
|
this._buildElement(createErrorCardConfig(e.message, null));
|
||||||
}
|
}
|
||||||
if (changedProperties.has("lovelace")) {
|
|
||||||
this._element.editMode = this.lovelace?.editMode;
|
|
||||||
}
|
}
|
||||||
if (changedProperties.has("hass") || changedProperties.has("lovelace")) {
|
if (changedProps.has("editMode")) {
|
||||||
this._updateElement();
|
try {
|
||||||
|
this._element.editMode = this.editMode;
|
||||||
|
} catch (e: any) {
|
||||||
|
this._buildElement(createErrorCardConfig(e.message, null));
|
||||||
}
|
}
|
||||||
if (changedProperties.has("isPanel")) {
|
}
|
||||||
|
if (changedProps.has("isPanel")) {
|
||||||
this._element.isPanel = this.isPanel;
|
this._element.isPanel = this.isPanel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected willUpdate(
|
||||||
|
changedProps: PropertyValueMap<any> | Map<PropertyKey, unknown>
|
||||||
|
): void {
|
||||||
|
if (changedProps.has("hass") || changedProps.has("lovelace")) {
|
||||||
|
this._updateVisibility();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _clearMediaQueries() {
|
private _clearMediaQueries() {
|
||||||
this._listeners.forEach((unsub) => unsub());
|
this._listeners.forEach((unsub) => unsub());
|
||||||
this._listeners = [];
|
this._listeners = [];
|
||||||
@ -119,42 +163,50 @@ export class HuiCard extends ReactiveElement {
|
|||||||
|
|
||||||
private _listenMediaQueries() {
|
private _listenMediaQueries() {
|
||||||
this._clearMediaQueries();
|
this._clearMediaQueries();
|
||||||
if (!this._config?.visibility) {
|
if (!this.config?.visibility) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const conditions = this._config.visibility;
|
const conditions = this.config.visibility;
|
||||||
const hasOnlyMediaQuery =
|
const hasOnlyMediaQuery =
|
||||||
conditions.length === 1 &&
|
conditions.length === 1 &&
|
||||||
conditions[0].condition === "screen" &&
|
conditions[0].condition === "screen" &&
|
||||||
!!conditions[0].media_query;
|
!!conditions[0].media_query;
|
||||||
|
|
||||||
this._listeners = attachConditionMediaQueriesListeners(
|
this._listeners = attachConditionMediaQueriesListeners(
|
||||||
this._config.visibility,
|
this.config.visibility,
|
||||||
(matches) => {
|
(matches) => {
|
||||||
this._updateElement(hasOnlyMediaQuery && matches);
|
this._updateVisibility(hasOnlyMediaQuery && matches);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _updateElement(forceVisible?: boolean) {
|
private _updateVisibility(forceVisible?: boolean) {
|
||||||
if (!this._element) {
|
if (!this._element || !this.hass) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._element.hidden) {
|
if (this._element.hidden) {
|
||||||
this.style.setProperty("display", "none");
|
this._setElementVisibility(false);
|
||||||
this.toggleAttribute("hidden", true);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const visible =
|
const visible =
|
||||||
forceVisible ||
|
forceVisible ||
|
||||||
this.lovelace?.editMode ||
|
this.editMode ||
|
||||||
!this._config?.visibility ||
|
!this.config?.visibility ||
|
||||||
checkConditionsMet(this._config.visibility, this.hass);
|
checkConditionsMet(this.config.visibility, this.hass);
|
||||||
|
this._setElementVisibility(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setElementVisibility(visible: boolean) {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
if (this.hidden !== !visible) {
|
||||||
this.style.setProperty("display", visible ? "" : "none");
|
this.style.setProperty("display", visible ? "" : "none");
|
||||||
this.toggleAttribute("hidden", !visible);
|
this.toggleAttribute("hidden", !visible);
|
||||||
|
fireEvent(this, "card-visibility-changed", { value: visible });
|
||||||
|
}
|
||||||
|
|
||||||
if (!visible && this._element.parentElement) {
|
if (!visible && this._element.parentElement) {
|
||||||
this.removeChild(this._element);
|
this.removeChild(this._element);
|
||||||
} else if (visible && !this._element.parentElement) {
|
} else if (visible && !this._element.parentElement) {
|
||||||
|
@ -3,7 +3,6 @@ import { fireEvent } from "../../../common/dom/fire_event";
|
|||||||
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||||
import { computeCardSize } from "../common/compute-card-size";
|
import { computeCardSize } from "../common/compute-card-size";
|
||||||
import { HuiConditionalBase } from "../components/hui-conditional-base";
|
import { HuiConditionalBase } from "../components/hui-conditional-base";
|
||||||
import { createCardElement } from "../create-element/create-card-element";
|
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
import { ConditionalCardConfig } from "./types";
|
import { ConditionalCardConfig } from "./types";
|
||||||
|
|
||||||
@ -38,28 +37,13 @@ class HuiConditionalCard extends HuiConditionalBase implements LovelaceCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
||||||
const element = createCardElement(cardConfig) as LovelaceCard;
|
const element = document.createElement("hui-card");
|
||||||
if (this.hass) {
|
|
||||||
element.hass = this.hass;
|
element.hass = this.hass;
|
||||||
}
|
element.editMode = this.editMode;
|
||||||
element.addEventListener(
|
element.config = cardConfig;
|
||||||
"ll-rebuild",
|
|
||||||
(ev) => {
|
|
||||||
ev.stopPropagation();
|
|
||||||
this._rebuildCard(cardConfig);
|
|
||||||
},
|
|
||||||
{ once: true }
|
|
||||||
);
|
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _rebuildCard(config: LovelaceCardConfig): void {
|
|
||||||
this._element = this._createCardElement(config);
|
|
||||||
if (this.lastChild) {
|
|
||||||
this.replaceChild(this._element, this.lastChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected setVisibility(conditionMet: boolean): void {
|
protected setVisibility(conditionMet: boolean): void {
|
||||||
const visible = this.editMode || conditionMet;
|
const visible = this.editMode || conditionMet;
|
||||||
const previouslyHidden = this.hidden;
|
const previouslyHidden = this.hidden;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { PropertyValues, ReactiveElement } from "lit";
|
import { PropertyValues, ReactiveElement } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { computeCardSize } from "../common/compute-card-size";
|
import { computeCardSize } from "../common/compute-card-size";
|
||||||
@ -11,11 +12,10 @@ import {
|
|||||||
checkConditionsMet,
|
checkConditionsMet,
|
||||||
extractConditionEntityIds,
|
extractConditionEntityIds,
|
||||||
} from "../common/validate-condition";
|
} from "../common/validate-condition";
|
||||||
import { createCardElement } from "../create-element/create-card-element";
|
|
||||||
import { EntityFilterEntityConfig } from "../entity-rows/types";
|
import { EntityFilterEntityConfig } from "../entity-rows/types";
|
||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
|
import { HuiCard } from "./hui-card";
|
||||||
import { EntityFilterCardConfig } from "./types";
|
import { EntityFilterCardConfig } from "./types";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
|
||||||
|
|
||||||
@customElement("hui-entity-filter-card")
|
@customElement("hui-entity-filter-card")
|
||||||
export class HuiEntityFilterCard
|
export class HuiEntityFilterCard
|
||||||
@ -59,7 +59,7 @@ export class HuiEntityFilterCard
|
|||||||
|
|
||||||
@state() private _config?: EntityFilterCardConfig;
|
@state() private _config?: EntityFilterCardConfig;
|
||||||
|
|
||||||
private _element?: LovelaceCard;
|
private _element?: HuiCard;
|
||||||
|
|
||||||
private _configEntities?: EntityFilterEntityConfig[];
|
private _configEntities?: EntityFilterEntityConfig[];
|
||||||
|
|
||||||
@ -173,12 +173,12 @@ export class HuiEntityFilterCard
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.lastChild) {
|
if (!this.lastChild) {
|
||||||
this._element.setConfig({
|
this._element.config = {
|
||||||
...this._baseCardConfig!,
|
...this._baseCardConfig!,
|
||||||
entities: entitiesList,
|
entities: entitiesList,
|
||||||
});
|
};
|
||||||
this._oldEntities = entitiesList;
|
this._oldEntities = entitiesList;
|
||||||
} else if (this._element.tagName !== "HUI-ERROR-CARD") {
|
} else {
|
||||||
const isSame =
|
const isSame =
|
||||||
this._oldEntities &&
|
this._oldEntities &&
|
||||||
entitiesList.length === this._oldEntities.length &&
|
entitiesList.length === this._oldEntities.length &&
|
||||||
@ -186,10 +186,10 @@ export class HuiEntityFilterCard
|
|||||||
|
|
||||||
if (!isSame) {
|
if (!isSame) {
|
||||||
this._oldEntities = entitiesList;
|
this._oldEntities = entitiesList;
|
||||||
this._element.setConfig({
|
this._element.config = {
|
||||||
...this._baseCardConfig!,
|
...this._baseCardConfig!,
|
||||||
entities: entitiesList,
|
entities: entitiesList,
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,33 +245,12 @@ export class HuiEntityFilterCard
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
||||||
const element = createCardElement(cardConfig) as LovelaceCard;
|
const element = document.createElement("hui-card");
|
||||||
if (this.hass) {
|
|
||||||
element.hass = this.hass;
|
element.hass = this.hass;
|
||||||
}
|
|
||||||
element.isPanel = this.isPanel;
|
|
||||||
element.editMode = this.editMode;
|
element.editMode = this.editMode;
|
||||||
element.addEventListener(
|
element.config = cardConfig;
|
||||||
"ll-rebuild",
|
|
||||||
(ev) => {
|
|
||||||
ev.stopPropagation();
|
|
||||||
this._rebuildCard(element, cardConfig);
|
|
||||||
},
|
|
||||||
{ once: true }
|
|
||||||
);
|
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _rebuildCard(
|
|
||||||
cardElToReplace: LovelaceCard,
|
|
||||||
config: LovelaceCardConfig
|
|
||||||
): void {
|
|
||||||
const newCardEl = this._createCardElement(config);
|
|
||||||
if (cardElToReplace.parentElement) {
|
|
||||||
cardElToReplace.parentElement!.replaceChild(newCardEl, cardElToReplace);
|
|
||||||
}
|
|
||||||
this._element = newCardEl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { dump } from "js-yaml";
|
import { dump } from "js-yaml";
|
||||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import "../../../components/ha-alert";
|
import "../../../components/ha-alert";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
@ -10,6 +10,8 @@ import { ErrorCardConfig } from "./types";
|
|||||||
export class HuiErrorCard extends LitElement implements LovelaceCard {
|
export class HuiErrorCard extends LitElement implements LovelaceCard {
|
||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ attribute: false }) public editMode = false;
|
||||||
|
|
||||||
@state() private _config?: ErrorCardConfig;
|
@state() private _config?: ErrorCardConfig;
|
||||||
|
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
|
@ -1,19 +1,12 @@
|
|||||||
import {
|
import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
|
||||||
css,
|
|
||||||
CSSResultGroup,
|
|
||||||
html,
|
|
||||||
LitElement,
|
|
||||||
PropertyValues,
|
|
||||||
nothing,
|
|
||||||
} from "lit";
|
|
||||||
import { property, state } from "lit/decorators";
|
import { property, state } from "lit/decorators";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { createCardElement } from "../create-element/create-card-element";
|
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
|
import "./hui-card";
|
||||||
|
import type { HuiCard } from "./hui-card";
|
||||||
import { StackCardConfig } from "./types";
|
import { StackCardConfig } from "./types";
|
||||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
|
||||||
|
|
||||||
export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
|
export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
|
||||||
extends LitElement
|
extends LitElement
|
||||||
@ -32,7 +25,7 @@ export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
|
|||||||
|
|
||||||
@property({ type: Boolean }) public editMode = false;
|
@property({ type: Boolean }) public editMode = false;
|
||||||
|
|
||||||
@state() protected _cards?: LovelaceCard[];
|
@state() protected _cards?: HuiCard[];
|
||||||
|
|
||||||
@state() protected _config?: T;
|
@state() protected _config?: T;
|
||||||
|
|
||||||
@ -49,28 +42,34 @@ export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
|
|||||||
}
|
}
|
||||||
this._config = config;
|
this._config = config;
|
||||||
this._cards = config.cards.map((card) => {
|
this._cards = config.cards.map((card) => {
|
||||||
const element = this._createCardElement(card) as LovelaceCard;
|
const element = this._createCardElement(card);
|
||||||
return element;
|
return element;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues) {
|
protected update(changedProperties) {
|
||||||
super.updated(changedProps);
|
super.update(changedProperties);
|
||||||
if (
|
|
||||||
!this._cards ||
|
if (this._cards) {
|
||||||
(!changedProps.has("hass") && !changedProps.has("editMode"))
|
if (changedProperties.has("hass")) {
|
||||||
) {
|
this._cards.forEach((card) => {
|
||||||
return;
|
card.hass = this.hass;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (changedProperties.has("editMode")) {
|
||||||
|
this._cards.forEach((card) => {
|
||||||
|
card.editMode = this.editMode;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const element of this._cards) {
|
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
||||||
if (this.hass) {
|
const element = document.createElement("hui-card");
|
||||||
element.hass = this.hass;
|
element.hass = this.hass;
|
||||||
}
|
|
||||||
if (this.editMode !== undefined) {
|
|
||||||
element.editMode = this.editMode;
|
element.editMode = this.editMode;
|
||||||
}
|
element.config = cardConfig;
|
||||||
}
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
@ -110,34 +109,4 @@ export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
|
||||||
const element = createCardElement(cardConfig) as LovelaceCard;
|
|
||||||
if (this.hass) {
|
|
||||||
element.hass = this.hass;
|
|
||||||
}
|
|
||||||
element.addEventListener(
|
|
||||||
"ll-rebuild",
|
|
||||||
(ev) => {
|
|
||||||
ev.stopPropagation();
|
|
||||||
this._rebuildCard(element, cardConfig);
|
|
||||||
fireEvent(this, "ll-rebuild");
|
|
||||||
},
|
|
||||||
{ once: true }
|
|
||||||
);
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _rebuildCard(
|
|
||||||
cardElToReplace: LovelaceCard,
|
|
||||||
config: LovelaceCardConfig
|
|
||||||
): void {
|
|
||||||
const newCardEl = this._createCardElement(config);
|
|
||||||
if (cardElToReplace.parentElement) {
|
|
||||||
cardElToReplace.parentElement.replaceChild(newCardEl, cardElToReplace);
|
|
||||||
}
|
|
||||||
this._cards = this._cards!.map((curCardEl) =>
|
|
||||||
curCardEl === cardElToReplace ? newCardEl : curCardEl
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { customElement, property, state } from "lit/decorators";
|
|||||||
import { MediaQueriesListener } from "../../../common/dom/media_query";
|
import { MediaQueriesListener } from "../../../common/dom/media_query";
|
||||||
import { deepEqual } from "../../../common/util/deep-equal";
|
import { deepEqual } from "../../../common/util/deep-equal";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { HuiCard } from "../cards/hui-card";
|
||||||
import { ConditionalCardConfig } from "../cards/types";
|
import { ConditionalCardConfig } from "../cards/types";
|
||||||
import {
|
import {
|
||||||
Condition,
|
Condition,
|
||||||
@ -12,7 +13,6 @@ import {
|
|||||||
validateConditionalConfig,
|
validateConditionalConfig,
|
||||||
} from "../common/validate-condition";
|
} from "../common/validate-condition";
|
||||||
import { ConditionalRowConfig, LovelaceRow } from "../entity-rows/types";
|
import { ConditionalRowConfig, LovelaceRow } from "../entity-rows/types";
|
||||||
import { LovelaceCard } from "../types";
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
@ -28,7 +28,7 @@ export class HuiConditionalBase extends ReactiveElement {
|
|||||||
|
|
||||||
@state() protected _config?: ConditionalCardConfig | ConditionalRowConfig;
|
@state() protected _config?: ConditionalCardConfig | ConditionalRowConfig;
|
||||||
|
|
||||||
protected _element?: LovelaceCard | LovelaceRow;
|
protected _element?: HuiCard | LovelaceRow;
|
||||||
|
|
||||||
private _listeners: MediaQueriesListener[] = [];
|
private _listeners: MediaQueriesListener[] = [];
|
||||||
|
|
||||||
|
@ -152,6 +152,7 @@ const _lazyCreate = <T extends keyof CreateElementConfigTypes>(
|
|||||||
customElements.whenDefined(tag).then(() => {
|
customElements.whenDefined(tag).then(() => {
|
||||||
try {
|
try {
|
||||||
customElements.upgrade(element);
|
customElements.upgrade(element);
|
||||||
|
fireEvent(element, "ll-upgrade");
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
element.setConfig(config);
|
element.setConfig(config);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
import { PropertyValues, ReactiveElement } from "lit";
|
|
||||||
import { property } from "lit/decorators";
|
|
||||||
import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
|
|
||||||
import { HomeAssistant } from "../../../../types";
|
|
||||||
import { createCardElement } from "../../create-element/create-card-element";
|
|
||||||
import { createErrorCardConfig } from "../../create-element/create-element-base";
|
|
||||||
import { LovelaceCard } from "../../types";
|
|
||||||
|
|
||||||
export class HuiCardPreview extends ReactiveElement {
|
|
||||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public config?: LovelaceCardConfig;
|
|
||||||
|
|
||||||
private _element?: LovelaceCard;
|
|
||||||
|
|
||||||
private get _error() {
|
|
||||||
return this._element?.tagName === "HUI-ERROR-CARD";
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.addEventListener("ll-rebuild", () => {
|
|
||||||
this._cleanup();
|
|
||||||
if (this.config) {
|
|
||||||
this._createCard(this.config);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected createRenderRoot() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected update(changedProperties: PropertyValues) {
|
|
||||||
super.update(changedProperties);
|
|
||||||
|
|
||||||
if (changedProperties.has("config")) {
|
|
||||||
const oldConfig = changedProperties.get("config") as
|
|
||||||
| undefined
|
|
||||||
| LovelaceCardConfig;
|
|
||||||
|
|
||||||
if (!this.config) {
|
|
||||||
this._cleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.config.type) {
|
|
||||||
this._createCard(
|
|
||||||
createErrorCardConfig("No card type found", this.config)
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._element) {
|
|
||||||
this._createCard(this.config);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// in case the element was an error element we always want to recreate it
|
|
||||||
if (!this._error && oldConfig && this.config.type === oldConfig.type) {
|
|
||||||
try {
|
|
||||||
this._element.setConfig(this.config);
|
|
||||||
} catch (err: any) {
|
|
||||||
this._createCard(createErrorCardConfig(err.message, this.config));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this._createCard(this.config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changedProperties.has("hass")) {
|
|
||||||
if (this._element) {
|
|
||||||
this._element.hass = this.hass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _createCard(configValue: LovelaceCardConfig): void {
|
|
||||||
this._cleanup();
|
|
||||||
this._element = createCardElement(configValue);
|
|
||||||
|
|
||||||
this._element.editMode = true;
|
|
||||||
|
|
||||||
if (this.hass) {
|
|
||||||
this._element!.hass = this.hass;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.appendChild(this._element!);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _cleanup() {
|
|
||||||
if (!this._element) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.removeChild(this._element);
|
|
||||||
this._element = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"hui-card-preview": HuiCardPreview;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define("hui-card-preview", HuiCardPreview);
|
|
@ -5,7 +5,7 @@ import { fireEvent } from "../../../../common/dom/fire_event";
|
|||||||
import type { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
|
import type { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
|
||||||
import { haStyleDialog } from "../../../../resources/styles";
|
import { haStyleDialog } from "../../../../resources/styles";
|
||||||
import type { HomeAssistant } from "../../../../types";
|
import type { HomeAssistant } from "../../../../types";
|
||||||
import "./hui-card-preview";
|
import "../../cards/hui-card";
|
||||||
import type { DeleteCardDialogParams } from "./show-delete-card-dialog";
|
import type { DeleteCardDialogParams } from "./show-delete-card-dialog";
|
||||||
|
|
||||||
@customElement("hui-dialog-delete-card")
|
@customElement("hui-dialog-delete-card")
|
||||||
@ -45,10 +45,11 @@ export class HuiDialogDeleteCard extends LitElement {
|
|||||||
${this._cardConfig
|
${this._cardConfig
|
||||||
? html`
|
? html`
|
||||||
<div class="element-preview">
|
<div class="element-preview">
|
||||||
<hui-card-preview
|
<hui-card
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.config=${this._cardConfig}
|
.config=${this._cardConfig}
|
||||||
></hui-card-preview>
|
editMode
|
||||||
|
></hui-card>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@ -74,7 +75,7 @@ export class HuiDialogDeleteCard extends LitElement {
|
|||||||
.element-preview {
|
.element-preview {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
hui-card-preview {
|
hui-card {
|
||||||
margin: 4px auto;
|
margin: 4px auto;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -36,7 +36,7 @@ import { findLovelaceContainer } from "../lovelace-path";
|
|||||||
import type { GUIModeChangedEvent } from "../types";
|
import type { GUIModeChangedEvent } from "../types";
|
||||||
import "./hui-card-element-editor";
|
import "./hui-card-element-editor";
|
||||||
import type { HuiCardElementEditor } from "./hui-card-element-editor";
|
import type { HuiCardElementEditor } from "./hui-card-element-editor";
|
||||||
import "./hui-card-preview";
|
import "../../cards/hui-card";
|
||||||
import type { EditCardDialogParams } from "./show-edit-card-dialog";
|
import type { EditCardDialogParams } from "./show-edit-card-dialog";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@ -245,11 +245,12 @@ export class HuiDialogEditCard
|
|||||||
></hui-card-element-editor>
|
></hui-card-element-editor>
|
||||||
</div>
|
</div>
|
||||||
<div class="element-preview">
|
<div class="element-preview">
|
||||||
<hui-card-preview
|
<hui-card
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.config=${this._cardConfig}
|
.config=${this._cardConfig}
|
||||||
|
editMode
|
||||||
class=${this._error ? "blur" : ""}
|
class=${this._error ? "blur" : ""}
|
||||||
></hui-card-preview>
|
></hui-card>
|
||||||
${this._error
|
${this._error
|
||||||
? html`
|
? html`
|
||||||
<ha-circular-progress
|
<ha-circular-progress
|
||||||
@ -452,7 +453,7 @@ export class HuiDialogEditCard
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content hui-card-preview {
|
.content hui-card {
|
||||||
margin: 4px auto;
|
margin: 4px auto;
|
||||||
max-width: 390px;
|
max-width: 390px;
|
||||||
}
|
}
|
||||||
@ -470,7 +471,7 @@ export class HuiDialogEditCard
|
|||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
.content hui-card-preview {
|
.content hui-card {
|
||||||
padding: 8px 10px;
|
padding: 8px 10px;
|
||||||
margin: auto 0px;
|
margin: auto 0px;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
@ -498,7 +499,7 @@ export class HuiDialogEditCard
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
hui-card-preview {
|
hui-card {
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -18,7 +18,7 @@ import {
|
|||||||
LovelaceContainerPath,
|
LovelaceContainerPath,
|
||||||
parseLovelaceContainerPath,
|
parseLovelaceContainerPath,
|
||||||
} from "../lovelace-path";
|
} from "../lovelace-path";
|
||||||
import "./hui-card-preview";
|
import "../../cards/hui-card";
|
||||||
import { showCreateCardDialog } from "./show-create-card-dialog";
|
import { showCreateCardDialog } from "./show-create-card-dialog";
|
||||||
import { SuggestCardDialogParams } from "./show-suggest-card-dialog";
|
import { SuggestCardDialogParams } from "./show-suggest-card-dialog";
|
||||||
|
|
||||||
@ -84,10 +84,7 @@ export class HuiDialogSuggestCard extends LitElement {
|
|||||||
<div class="element-preview">
|
<div class="element-preview">
|
||||||
${this._cardConfig.map(
|
${this._cardConfig.map(
|
||||||
(cardConfig) => html`
|
(cardConfig) => html`
|
||||||
<hui-card-preview
|
<hui-card .hass=${this.hass} .config=${cardConfig}></hui-card>
|
||||||
.hass=${this.hass}
|
|
||||||
.config=${cardConfig}
|
|
||||||
></hui-card-preview>
|
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -191,7 +188,7 @@ export class HuiDialogSuggestCard extends LitElement {
|
|||||||
.element-preview {
|
.element-preview {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
hui-card-preview,
|
hui-card,
|
||||||
hui-section {
|
hui-section {
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
margin: 4px auto;
|
margin: 4px auto;
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
import { PropertyValues, ReactiveElement } from "lit";
|
|
||||||
import { customElement, property } from "lit/decorators";
|
|
||||||
import { LovelaceSectionElement } from "../../../../data/lovelace";
|
|
||||||
import { LovelaceSectionConfig } from "../../../../data/lovelace/config/section";
|
|
||||||
import { HomeAssistant } from "../../../../types";
|
|
||||||
import { createSectionElement } from "../../create-element/create-section-element";
|
|
||||||
import { createErrorSectionConfig } from "../../sections/hui-error-section";
|
|
||||||
import { LovelaceConfig } from "../../../../data/lovelace/config/types";
|
|
||||||
|
|
||||||
@customElement("hui-section-preview")
|
|
||||||
export class HuiSectionPreview extends ReactiveElement {
|
|
||||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public lovelace?: LovelaceConfig;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public config?: LovelaceSectionConfig;
|
|
||||||
|
|
||||||
private _element?: LovelaceSectionElement;
|
|
||||||
|
|
||||||
private get _error() {
|
|
||||||
return this._element?.tagName === "HUI-ERROR-SECTION";
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.addEventListener("ll-rebuild", () => {
|
|
||||||
this._cleanup();
|
|
||||||
if (this.config) {
|
|
||||||
this._createSection(this.config);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected createRenderRoot() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected update(changedProperties: PropertyValues) {
|
|
||||||
super.update(changedProperties);
|
|
||||||
|
|
||||||
if (changedProperties.has("config")) {
|
|
||||||
const oldConfig = changedProperties.get("config") as
|
|
||||||
| undefined
|
|
||||||
| LovelaceSectionConfig;
|
|
||||||
|
|
||||||
if (!this.config) {
|
|
||||||
this._cleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.config.type) {
|
|
||||||
this._createSection(createErrorSectionConfig("No section type found"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._element) {
|
|
||||||
this._createSection(this.config);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// in case the element was an error element we always want to recreate it
|
|
||||||
if (!this._error && oldConfig && this.config.type === oldConfig.type) {
|
|
||||||
try {
|
|
||||||
this._element.setConfig(this.config);
|
|
||||||
} catch (err: any) {
|
|
||||||
this._createSection(createErrorSectionConfig(err.message));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this._createSection(this.config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changedProperties.has("hass")) {
|
|
||||||
if (this._element) {
|
|
||||||
this._element.hass = this.hass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _createSection(configValue: LovelaceSectionConfig): void {
|
|
||||||
this._cleanup();
|
|
||||||
this._element = createSectionElement(configValue) as LovelaceSectionElement;
|
|
||||||
|
|
||||||
if (this.hass) {
|
|
||||||
this._element!.hass = this.hass;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.appendChild(this._element!);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _cleanup() {
|
|
||||||
if (!this._element) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.removeChild(this._element);
|
|
||||||
this._element = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"hui-section-preview": HuiSectionPreview;
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,10 +11,10 @@ import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
|||||||
import type { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
|
import type { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
|
import { HuiCard } from "../cards/hui-card";
|
||||||
import "../components/hui-card-edit-mode";
|
import "../components/hui-card-edit-mode";
|
||||||
import { moveCard } from "../editor/config-util";
|
import { moveCard } from "../editor/config-util";
|
||||||
import type { Lovelace } from "../types";
|
import type { Lovelace } from "../types";
|
||||||
import { HuiCard } from "../cards/hui-card";
|
|
||||||
|
|
||||||
const CARD_SORTABLE_OPTIONS: HaSortableOptions = {
|
const CARD_SORTABLE_OPTIONS: HaSortableOptions = {
|
||||||
delay: 100,
|
delay: 100,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { PropertyValues, ReactiveElement } from "lit";
|
import { PropertyValues, ReactiveElement } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { MediaQueriesListener } from "../../../common/dom/media_query";
|
import { MediaQueriesListener } from "../../../common/dom/media_query";
|
||||||
import "../../../components/ha-svg-icon";
|
import "../../../components/ha-svg-icon";
|
||||||
import type { LovelaceSectionElement } from "../../../data/lovelace";
|
import type { LovelaceSectionElement } from "../../../data/lovelace";
|
||||||
@ -16,7 +17,6 @@ import {
|
|||||||
attachConditionMediaQueriesListeners,
|
attachConditionMediaQueriesListeners,
|
||||||
checkConditionsMet,
|
checkConditionsMet,
|
||||||
} from "../common/validate-condition";
|
} from "../common/validate-condition";
|
||||||
import { createErrorCardConfig } from "../create-element/create-element-base";
|
|
||||||
import { createSectionElement } from "../create-element/create-section-element";
|
import { createSectionElement } from "../create-element/create-section-element";
|
||||||
import { showCreateCardDialog } from "../editor/card-editor/show-create-card-dialog";
|
import { showCreateCardDialog } from "../editor/card-editor/show-create-card-dialog";
|
||||||
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
||||||
@ -26,7 +26,6 @@ import { parseLovelaceCardPath } from "../editor/lovelace-path";
|
|||||||
import { generateLovelaceSectionStrategy } from "../strategies/get-strategy";
|
import { generateLovelaceSectionStrategy } from "../strategies/get-strategy";
|
||||||
import type { Lovelace } from "../types";
|
import type { Lovelace } from "../types";
|
||||||
import { DEFAULT_SECTION_LAYOUT } from "./const";
|
import { DEFAULT_SECTION_LAYOUT } from "./const";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
@ -54,23 +53,15 @@ export class HuiSection extends ReactiveElement {
|
|||||||
|
|
||||||
private _listeners: MediaQueriesListener[] = [];
|
private _listeners: MediaQueriesListener[] = [];
|
||||||
|
|
||||||
// Public to make demo happy
|
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
||||||
public createCardElement(cardConfig: LovelaceCardConfig) {
|
|
||||||
const element = document.createElement("hui-card");
|
const element = document.createElement("hui-card");
|
||||||
element.hass = this.hass;
|
element.hass = this.hass;
|
||||||
element.lovelace = this.lovelace;
|
element.editMode = this.lovelace?.editMode || false;
|
||||||
element.setConfig(cardConfig);
|
element.config = cardConfig;
|
||||||
element.addEventListener(
|
element.addEventListener("card-updated", (ev: Event) => {
|
||||||
"ll-rebuild",
|
|
||||||
(ev: Event) => {
|
|
||||||
// In edit mode let it go to hui-root and rebuild whole section.
|
|
||||||
if (!this.lovelace!.editMode) {
|
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this._rebuildCard(element, cardConfig);
|
this._cards = [...this._cards];
|
||||||
}
|
});
|
||||||
},
|
|
||||||
{ once: true }
|
|
||||||
);
|
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,22 +112,14 @@ export class HuiSection extends ReactiveElement {
|
|||||||
// Config has not changed. Just props
|
// Config has not changed. Just props
|
||||||
if (changedProperties.has("hass")) {
|
if (changedProperties.has("hass")) {
|
||||||
this._cards.forEach((element) => {
|
this._cards.forEach((element) => {
|
||||||
try {
|
|
||||||
element.hass = this.hass;
|
element.hass = this.hass;
|
||||||
} catch (e: any) {
|
|
||||||
this._rebuildCard(element, createErrorCardConfig(e.message, null));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
this._layoutElement.hass = this.hass;
|
this._layoutElement.hass = this.hass;
|
||||||
}
|
}
|
||||||
if (changedProperties.has("lovelace")) {
|
if (changedProperties.has("lovelace")) {
|
||||||
this._layoutElement.lovelace = this.lovelace;
|
this._layoutElement.lovelace = this.lovelace;
|
||||||
this._cards.forEach((element) => {
|
this._cards.forEach((element) => {
|
||||||
try {
|
element.editMode = this.lovelace?.editMode || false;
|
||||||
element.lovelace = this.lovelace;
|
|
||||||
} catch (e: any) {
|
|
||||||
this._rebuildCard(element, createErrorCardConfig(e.message, null));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (changedProperties.has("_cards")) {
|
if (changedProperties.has("_cards")) {
|
||||||
@ -283,22 +266,8 @@ export class HuiSection extends ReactiveElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._cards = config.cards.map((cardConfig) => {
|
this._cards = config.cards.map((cardConfig) =>
|
||||||
const element = this.createCardElement(cardConfig);
|
this._createCardElement(cardConfig)
|
||||||
return element;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private _rebuildCard(
|
|
||||||
cardElToReplace: HuiCard,
|
|
||||||
config: LovelaceCardConfig
|
|
||||||
): void {
|
|
||||||
const newCardEl = this.createCardElement(config);
|
|
||||||
if (cardElToReplace.parentElement) {
|
|
||||||
cardElToReplace.parentElement!.replaceChild(newCardEl, cardElToReplace);
|
|
||||||
}
|
|
||||||
this._cards = this._cards!.map((curCardEl) =>
|
|
||||||
curCardEl === cardElToReplace ? newCardEl : curCardEl
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ declare global {
|
|||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
"ll-rebuild": Record<string, unknown>;
|
"ll-rebuild": Record<string, unknown>;
|
||||||
|
"ll-upgrade": Record<string, unknown>;
|
||||||
"ll-badge-rebuild": Record<string, unknown>;
|
"ll-badge-rebuild": Record<string, unknown>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
|
|||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
import { HuiCard } from "../cards/hui-card";
|
import { HuiCard } from "../cards/hui-card";
|
||||||
import { computeCardSize } from "../common/compute-card-size";
|
import { computeCardSize } from "../common/compute-card-size";
|
||||||
import type { Lovelace, LovelaceBadge, LovelaceCard } from "../types";
|
import type { Lovelace, LovelaceBadge } from "../types";
|
||||||
|
|
||||||
// Find column with < 5 size, else smallest column
|
// Find column with < 5 size, else smallest column
|
||||||
const getColumnIndex = (columnSizes: number[], size: number) => {
|
const getColumnIndex = (columnSizes: number[], size: number) => {
|
||||||
@ -249,7 +249,7 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _addCardToColumn(columnEl, index, editMode) {
|
private _addCardToColumn(columnEl, index, editMode) {
|
||||||
const card: LovelaceCard = this.cards[index];
|
const card: HuiCard = this.cards[index];
|
||||||
if (!editMode || this.isStrategy) {
|
if (!editMode || this.isStrategy) {
|
||||||
card.editMode = false;
|
card.editMode = false;
|
||||||
columnEl.appendChild(card);
|
columnEl.appendChild(card);
|
||||||
|
@ -17,7 +17,7 @@ import type { HomeAssistant } from "../../../types";
|
|||||||
import { HuiCard } from "../cards/hui-card";
|
import { HuiCard } from "../cards/hui-card";
|
||||||
import { HuiCardOptions } from "../components/hui-card-options";
|
import { HuiCardOptions } from "../components/hui-card-options";
|
||||||
import { HuiWarning } from "../components/hui-warning";
|
import { HuiWarning } from "../components/hui-warning";
|
||||||
import type { Lovelace, LovelaceCard } from "../types";
|
import type { Lovelace } from "../types";
|
||||||
|
|
||||||
let editCodeLoaded = false;
|
let editCodeLoaded = false;
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ export class PanelView extends LitElement implements LovelaceViewElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public cards: HuiCard[] = [];
|
@property({ attribute: false }) public cards: HuiCard[] = [];
|
||||||
|
|
||||||
@state() private _card?: LovelaceCard | HuiWarning | HuiCardOptions;
|
@state() private _card?: HuiCard | HuiWarning | HuiCardOptions;
|
||||||
|
|
||||||
public setConfig(_config: LovelaceViewConfig): void {}
|
public setConfig(_config: LovelaceViewConfig): void {}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ export class PanelView extends LitElement implements LovelaceViewElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const card: LovelaceCard = this.cards[0];
|
const card: HuiCard = this.cards[0];
|
||||||
card.isPanel = true;
|
card.isPanel = true;
|
||||||
|
|
||||||
if (this.isStrategy || !this.lovelace?.editMode) {
|
if (this.isStrategy || !this.lovelace?.editMode) {
|
||||||
|
@ -15,7 +15,7 @@ import type { HomeAssistant } from "../../../types";
|
|||||||
import { HuiCard } from "../cards/hui-card";
|
import { HuiCard } from "../cards/hui-card";
|
||||||
import { HuiCardOptions } from "../components/hui-card-options";
|
import { HuiCardOptions } from "../components/hui-card-options";
|
||||||
import { replaceCard } from "../editor/config-util";
|
import { replaceCard } from "../editor/config-util";
|
||||||
import type { Lovelace, LovelaceCard } from "../types";
|
import type { Lovelace } from "../types";
|
||||||
|
|
||||||
export class SideBarView extends LitElement implements LovelaceViewElement {
|
export class SideBarView extends LitElement implements LovelaceViewElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
@ -140,9 +140,9 @@ export class SideBarView extends LitElement implements LovelaceViewElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.cards.forEach((card: LovelaceCard, idx) => {
|
this.cards.forEach((card, idx) => {
|
||||||
const cardConfig = this._config?.cards?.[idx];
|
const cardConfig = this._config?.cards?.[idx];
|
||||||
let element: LovelaceCard | HuiCardOptions;
|
let element: HuiCard | HuiCardOptions;
|
||||||
if (this.isStrategy || !this.lovelace?.editMode) {
|
if (this.isStrategy || !this.lovelace?.editMode) {
|
||||||
card.editMode = false;
|
card.editMode = false;
|
||||||
element = card;
|
element = card;
|
||||||
|
@ -21,7 +21,6 @@ import "../cards/hui-card";
|
|||||||
import type { HuiCard } from "../cards/hui-card";
|
import type { HuiCard } from "../cards/hui-card";
|
||||||
import { processConfigEntities } from "../common/process-config-entities";
|
import { processConfigEntities } from "../common/process-config-entities";
|
||||||
import { createBadgeElement } from "../create-element/create-badge-element";
|
import { createBadgeElement } from "../create-element/create-badge-element";
|
||||||
import { createErrorCardConfig } from "../create-element/create-element-base";
|
|
||||||
import { createViewElement } from "../create-element/create-view-element";
|
import { createViewElement } from "../create-element/create-view-element";
|
||||||
import { showCreateCardDialog } from "../editor/card-editor/show-create-card-dialog";
|
import { showCreateCardDialog } from "../editor/card-editor/show-create-card-dialog";
|
||||||
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
||||||
@ -77,19 +76,12 @@ export class HUIView extends ReactiveElement {
|
|||||||
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
||||||
const element = document.createElement("hui-card");
|
const element = document.createElement("hui-card");
|
||||||
element.hass = this.hass;
|
element.hass = this.hass;
|
||||||
element.lovelace = this.lovelace;
|
element.editMode = this.lovelace.editMode;
|
||||||
element.setConfig(cardConfig);
|
element.config = cardConfig;
|
||||||
element.addEventListener(
|
element.addEventListener("card-updated", (ev: Event) => {
|
||||||
"ll-rebuild",
|
|
||||||
(ev: Event) => {
|
|
||||||
// In edit mode let it go to hui-root and rebuild whole view.
|
|
||||||
if (!this.lovelace!.editMode) {
|
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this._rebuildCard(element, cardConfig);
|
this._cards = [...this._cards];
|
||||||
}
|
});
|
||||||
},
|
|
||||||
{ once: true }
|
|
||||||
);
|
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,11 +175,7 @@ export class HUIView extends ReactiveElement {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this._cards.forEach((element) => {
|
this._cards.forEach((element) => {
|
||||||
try {
|
|
||||||
element.hass = this.hass;
|
element.hass = this.hass;
|
||||||
} catch (e: any) {
|
|
||||||
this._rebuildCard(element, createErrorCardConfig(e.message, null));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this._sections.forEach((element) => {
|
this._sections.forEach((element) => {
|
||||||
@ -226,12 +214,7 @@ export class HUIView extends ReactiveElement {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
this._cards.forEach((element) => {
|
this._cards.forEach((element) => {
|
||||||
try {
|
element.editMode = this.lovelace.editMode;
|
||||||
element.hass = this.hass;
|
|
||||||
element.lovelace = this.lovelace;
|
|
||||||
} catch (e: any) {
|
|
||||||
this._rebuildCard(element, createErrorCardConfig(e.message, null));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (changedProperties.has("_cards")) {
|
if (changedProperties.has("_cards")) {
|
||||||
@ -388,19 +371,6 @@ export class HUIView extends ReactiveElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _rebuildCard(
|
|
||||||
cardElToReplace: HuiCard,
|
|
||||||
config: LovelaceCardConfig
|
|
||||||
): void {
|
|
||||||
const newCardEl = this._createCardElement(config);
|
|
||||||
if (cardElToReplace.parentElement) {
|
|
||||||
cardElToReplace.parentElement!.replaceChild(newCardEl, cardElToReplace);
|
|
||||||
}
|
|
||||||
this._cards = this._cards!.map((curCardEl) =>
|
|
||||||
curCardEl === cardElToReplace ? newCardEl : curCardEl
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _rebuildBadge(
|
private _rebuildBadge(
|
||||||
badgeElToReplace: LovelaceBadge,
|
badgeElToReplace: LovelaceBadge,
|
||||||
config: LovelaceBadgeConfig
|
config: LovelaceBadgeConfig
|
||||||
|
@ -17,12 +17,13 @@ import {
|
|||||||
html,
|
html,
|
||||||
nothing,
|
nothing,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||||
import { storage } from "../../common/decorators/storage";
|
import { storage } from "../../common/decorators/storage";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
|
import { supportsFeature } from "../../common/entity/supports-feature";
|
||||||
import { navigate } from "../../common/navigate";
|
import { navigate } from "../../common/navigate";
|
||||||
import { constructUrlCurrentPath } from "../../common/url/construct-url";
|
import { constructUrlCurrentPath } from "../../common/url/construct-url";
|
||||||
import {
|
import {
|
||||||
@ -40,6 +41,7 @@ import "../../components/ha-two-pane-top-app-bar-fixed";
|
|||||||
import { deleteConfigEntry } from "../../data/config_entries";
|
import { deleteConfigEntry } from "../../data/config_entries";
|
||||||
import { getExtendedEntityRegistryEntry } from "../../data/entity_registry";
|
import { getExtendedEntityRegistryEntry } from "../../data/entity_registry";
|
||||||
import { fetchIntegrationManifest } from "../../data/integration";
|
import { fetchIntegrationManifest } from "../../data/integration";
|
||||||
|
import { LovelaceCardConfig } from "../../data/lovelace/config/card";
|
||||||
import { TodoListEntityFeature, getTodoLists } from "../../data/todo";
|
import { TodoListEntityFeature, getTodoLists } from "../../data/todo";
|
||||||
import { showConfigFlowDialog } from "../../dialogs/config-flow/show-dialog-config-flow";
|
import { showConfigFlowDialog } from "../../dialogs/config-flow/show-dialog-config-flow";
|
||||||
import {
|
import {
|
||||||
@ -49,11 +51,8 @@ import {
|
|||||||
import { showVoiceCommandDialog } from "../../dialogs/voice-command-dialog/show-ha-voice-command-dialog";
|
import { showVoiceCommandDialog } from "../../dialogs/voice-command-dialog/show-ha-voice-command-dialog";
|
||||||
import { haStyle } from "../../resources/styles";
|
import { haStyle } from "../../resources/styles";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import { HuiErrorCard } from "../lovelace/cards/hui-error-card";
|
import "../lovelace/cards/hui-card";
|
||||||
import { createCardElement } from "../lovelace/create-element/create-card-element";
|
|
||||||
import { LovelaceCard } from "../lovelace/types";
|
|
||||||
import { showTodoItemEditDialog } from "./show-dialog-todo-item-editor";
|
import { showTodoItemEditDialog } from "./show-dialog-todo-item-editor";
|
||||||
import { supportsFeature } from "../../common/entity/supports-feature";
|
|
||||||
|
|
||||||
@customElement("ha-panel-todo")
|
@customElement("ha-panel-todo")
|
||||||
class PanelTodo extends LitElement {
|
class PanelTodo extends LitElement {
|
||||||
@ -63,8 +62,6 @@ class PanelTodo extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean, reflect: true }) public mobile = false;
|
@property({ type: Boolean, reflect: true }) public mobile = false;
|
||||||
|
|
||||||
@state() private _card?: LovelaceCard | HuiErrorCard;
|
|
||||||
|
|
||||||
@storage({
|
@storage({
|
||||||
key: "selectedTodoEntity",
|
key: "selectedTodoEntity",
|
||||||
state: true,
|
state: true,
|
||||||
@ -128,15 +125,10 @@ class PanelTodo extends LitElement {
|
|||||||
if (changedProperties.has("_entityId") || !this.hasUpdated) {
|
if (changedProperties.has("_entityId") || !this.hasUpdated) {
|
||||||
this._setupTodoElement();
|
this._setupTodoElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedProperties.has("hass") && this._card) {
|
|
||||||
this._card.hass = this.hass;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setupTodoElement(): void {
|
private _setupTodoElement(): void {
|
||||||
if (!this._entityId) {
|
if (!this._entityId) {
|
||||||
this._card = undefined;
|
|
||||||
navigate(constructUrlCurrentPath(""), { replace: true });
|
navigate(constructUrlCurrentPath(""), { replace: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -144,13 +136,16 @@ class PanelTodo extends LitElement {
|
|||||||
constructUrlCurrentPath(createSearchParam({ entity_id: this._entityId })),
|
constructUrlCurrentPath(createSearchParam({ entity_id: this._entityId })),
|
||||||
{ replace: true }
|
{ replace: true }
|
||||||
);
|
);
|
||||||
this._card = createCardElement({
|
|
||||||
type: "todo-list",
|
|
||||||
entity: this._entityId,
|
|
||||||
}) as LovelaceCard;
|
|
||||||
this._card.hass = this.hass;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _cardConfig = memoizeOne(
|
||||||
|
(entityId: string) =>
|
||||||
|
({
|
||||||
|
type: "todo-list",
|
||||||
|
entity: entityId,
|
||||||
|
}) as LovelaceCardConfig
|
||||||
|
);
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const entityRegistryEntry = this._entityId
|
const entityRegistryEntry = this._entityId
|
||||||
? this.hass.entities[this._entityId]
|
? this.hass.entities[this._entityId]
|
||||||
@ -274,7 +269,16 @@ class PanelTodo extends LitElement {
|
|||||||
: nothing}
|
: nothing}
|
||||||
</ha-button-menu>
|
</ha-button-menu>
|
||||||
<div id="columns">
|
<div id="columns">
|
||||||
<div class="column">${this._card}</div>
|
<div class="column">
|
||||||
|
${this._entityId
|
||||||
|
? html`
|
||||||
|
<hui-card
|
||||||
|
.hass=${this.hass}
|
||||||
|
.config=${this._cardConfig(this._entityId)}
|
||||||
|
></hui-card>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
${entityState &&
|
${entityState &&
|
||||||
supportsFeature(entityState, TodoListEntityFeature.CREATE_TODO_ITEM)
|
supportsFeature(entityState, TodoListEntityFeature.CREATE_TODO_ITEM)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user