Compare commits

...

4 Commits

Author SHA1 Message Date
Thomas Lovén
aecbfeaaa0 Force editor rebuild on stack card switch 2022-05-31 11:39:56 +00:00
Thomas Lovén
498732566e Highlight cards in stacks 2022-05-31 11:18:37 +00:00
Thomas Lovén
b22c51bc2c Highlight entities card rows 2022-05-31 11:16:02 +00:00
Thomas Lovén
5bc2fd059c Allow data passed from editor to preview 2022-05-31 11:13:41 +00:00
8 changed files with 115 additions and 13 deletions

View File

@@ -6,7 +6,8 @@ import {
PropertyValues, PropertyValues,
TemplateResult, TemplateResult,
} from "lit"; } from "lit";
import { customElement, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { DOMAINS_TOGGLE } from "../../../common/const"; import { DOMAINS_TOGGLE } from "../../../common/const";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
@@ -54,6 +55,8 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
return { type: "entities", entities: foundEntities }; return { type: "entities", entities: foundEntities };
} }
@property() public editMode?: boolean | any;
@state() private _config?: EntitiesCardConfig; @state() private _config?: EntitiesCardConfig;
private _hass?: HomeAssistant; private _hass?: HomeAssistant;
@@ -217,9 +220,15 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
`} `}
</h1> </h1>
`} `}
<div id="states" class="card-content"> <div
${this._configEntities!.map((entityConf) => id="states"
this.renderEntity(entityConf) class=${classMap({
"card-content": true,
highlight: this.editMode?.selectedRow !== undefined,
})}
>
${this._configEntities!.map((entityConf, idx) =>
this.renderEntity(entityConf, idx)
)} )}
</div> </div>
@@ -272,6 +281,12 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
#states > div { #states > div {
position: relative; position: relative;
} }
#states.highlight > div.selected {
opacity: 1;
}
#states.highlight > div {
opacity: 0.5;
}
.icon { .icon {
padding: 0px 18px 0px 8px; padding: 0px 18px 0px 8px;
@@ -293,7 +308,10 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
`; `;
} }
private renderEntity(entityConf: LovelaceRowConfig): TemplateResult { private renderEntity(
entityConf: LovelaceRowConfig,
idx: number
): TemplateResult {
const element = createRowElement( const element = createRowElement(
(!("type" in entityConf) || entityConf.type === "conditional") && (!("type" in entityConf) || entityConf.type === "conditional") &&
this._config!.state_color this._config!.state_color
@@ -307,7 +325,13 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
element.hass = this._hass; element.hass = this._hass;
} }
return html`<div>${element}</div>`; return html`<div
class=${classMap({
selected: this.editMode?.selectedRow === idx,
})}
>
${element}
</div>`;
} }
} }

View File

@@ -7,6 +7,7 @@ import {
TemplateResult, TemplateResult,
} from "lit"; } from "lit";
import { property, state } from "lit/decorators"; import { property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { LovelaceCardConfig } from "../../../data/lovelace"; import { LovelaceCardConfig } from "../../../data/lovelace";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { createCardElement } from "../create-element/create-card-element"; import { createCardElement } from "../create-element/create-card-element";
@@ -28,7 +29,7 @@ export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
@property({ attribute: false }) public hass?: HomeAssistant; @property({ attribute: false }) public hass?: HomeAssistant;
@property() public editMode?: boolean; @property() public editMode?: any;
@property() protected _cards?: LovelaceCard[]; @property() protected _cards?: LovelaceCard[];
@@ -43,8 +44,16 @@ export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
throw new Error("Invalid configuration"); throw new Error("Invalid configuration");
} }
this._config = config; this._config = config;
this._cards = config.cards.map((card) => { this._cards = config.cards.map((card, idx) => {
const element = this._createCardElement(card) as LovelaceCard; const element = this._createCardElement(card) as LovelaceCard;
if (this.editMode !== undefined) {
if (this.editMode?.selected === idx) {
element.classList.add("selected");
element.editMode = this.editMode.data;
} else {
element.editMode = true;
}
}
return element; return element;
}); });
} }
@@ -58,12 +67,18 @@ export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
return; return;
} }
for (const element of this._cards) { for (const [idx, element] of this._cards.entries()) {
if (this.hass) { if (this.hass) {
element.hass = this.hass; element.hass = this.hass;
} }
if (this.editMode !== undefined) { if (this.editMode !== undefined) {
element.editMode = this.editMode; if (this.editMode.selected === idx) {
element.editMode = this.editMode.data ?? true;
element.classList.add("selected");
} else {
element.editMode = true;
element.classList.remove("selected");
}
} }
} }
} }
@@ -77,7 +92,12 @@ export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
${this._config.title ${this._config.title
? html`<h1 class="card-header">${this._config.title}</h1>` ? html`<h1 class="card-header">${this._config.title}</h1>`
: ""} : ""}
<div id="root">${this._cards}</div> <div
id="root"
class=${classMap({ highlight: this.editMode?.selected !== undefined })}
>
${this._cards}
</div>
`; `;
} }
@@ -95,6 +115,12 @@ export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
display: block; display: block;
padding: 24px 16px 16px; padding: 24px 16px 16px;
} }
#root.highlight > *.selected {
opacity: 1;
}
#root.highlight > * {
opacity: 0.5;
}
`; `;
} }

View File

@@ -12,6 +12,8 @@ export class HuiCardPreview extends ReactiveElement {
@property() public config?: LovelaceCardConfig; @property() public config?: LovelaceCardConfig;
@property() public editMode = true;
private _element?: LovelaceCard; private _element?: LovelaceCard;
private get _error() { private get _error() {
@@ -81,6 +83,9 @@ export class HuiCardPreview extends ReactiveElement {
this._element.hass = this.hass; this._element.hass = this.hass;
} }
} }
if (changedProperties.has("editMode")) {
this._element!.editMode = this.editMode;
}
} }
private _createCard(configValue: LovelaceCardConfig): void { private _createCard(configValue: LovelaceCardConfig): void {
@@ -90,6 +95,7 @@ export class HuiCardPreview extends ReactiveElement {
if (this.hass) { if (this.hass) {
this._element!.hass = this.hass; this._element!.hass = this.hass;
} }
this._element!.editMode = this.editMode;
this.appendChild(this._element!); this.appendChild(this._element!);
} }

View File

@@ -43,6 +43,13 @@ declare global {
interface HTMLElementEventMap { interface HTMLElementEventMap {
"reload-lovelace": HASSDomEvent<undefined>; "reload-lovelace": HASSDomEvent<undefined>;
} }
interface HASSDomEvents {
"edit-mode-changed": any;
}
interface HTMLElementEventMap {
"edit-mode-changed": HASSDomEvent<any>;
}
} }
@customElement("hui-dialog-edit-card") @customElement("hui-dialog-edit-card")
@@ -77,10 +84,13 @@ export class HuiDialogEditCard
@state() private _isEscapeEnabled = true; @state() private _isEscapeEnabled = true;
@state() private _editMode = true;
public async showDialog(params: EditCardDialogParams): Promise<void> { public async showDialog(params: EditCardDialogParams): Promise<void> {
this._params = params; this._params = params;
this._GUImode = true; this._GUImode = true;
this._guiModeAvailable = true; this._guiModeAvailable = true;
this._editMode = true;
const [view, card] = params.path; const [view, card] = params.path;
this._viewConfig = params.lovelaceConfig.views[view]; this._viewConfig = params.lovelaceConfig.views[view];
this._cardConfig = this._cardConfig =
@@ -205,6 +215,7 @@ export class HuiDialogEditCard
.lovelace=${this._params.lovelaceConfig} .lovelace=${this._params.lovelaceConfig}
.value=${this._cardConfig} .value=${this._cardConfig}
@config-changed=${this._handleConfigChanged} @config-changed=${this._handleConfigChanged}
@edit-mode-changed=${this._handleEditModeChanged}
@GUImode-changed=${this._handleGUIModeChanged} @GUImode-changed=${this._handleGUIModeChanged}
@editor-save=${this._save} @editor-save=${this._save}
dialogInitialFocus dialogInitialFocus
@@ -214,6 +225,7 @@ export class HuiDialogEditCard
<hui-card-preview <hui-card-preview
.hass=${this.hass} .hass=${this.hass}
.config=${this._cardConfig} .config=${this._cardConfig}
.editMode=${this._editMode}
class=${this._error ? "blur" : ""} class=${this._error ? "blur" : ""}
></hui-card-preview> ></hui-card-preview>
${this._error ${this._error
@@ -284,6 +296,10 @@ export class HuiDialogEditCard
this._dirty = true; this._dirty = true;
} }
private _handleEditModeChanged(ev: HASSDomEvent<any>) {
this._editMode = ev.detail ?? true;
}
private _handleGUIModeChanged(ev: HASSDomEvent<GUIModeChangedEvent>): void { private _handleGUIModeChanged(ev: HASSDomEvent<GUIModeChangedEvent>): void {
ev.stopPropagation(); ev.stopPropagation();
this._GUImode = ev.detail.guiMode; this._GUImode = ev.detail.guiMode;

View File

@@ -408,10 +408,15 @@ export class HuiEntitiesCardEditor
private _editDetailElement(ev: HASSDomEvent<EditSubElementEvent>): void { private _editDetailElement(ev: HASSDomEvent<EditSubElementEvent>): void {
this._subElementEditorConfig = ev.detail.subElementConfig; this._subElementEditorConfig = ev.detail.subElementConfig;
fireEvent(this, "edit-mode-changed", {
selectedRow: ev.detail.subElementConfig?.index,
});
} }
private _goBack(): void { private _goBack(): void {
this._subElementEditorConfig = undefined; this._subElementEditorConfig = undefined;
fireEvent(this, "edit-mode-changed", true);
} }
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {

View File

@@ -144,6 +144,7 @@ export class HuiStackCardEditor
.lovelace=${this.lovelace} .lovelace=${this.lovelace}
@config-changed=${this._handleConfigChanged} @config-changed=${this._handleConfigChanged}
@GUImode-changed=${this._handleGUIModeChanged} @GUImode-changed=${this._handleGUIModeChanged}
@edit-mode-changed=${this._handleEditModeChanged}
></hui-card-element-editor> ></hui-card-element-editor>
` `
: html` : html`
@@ -166,6 +167,9 @@ export class HuiStackCardEditor
this._setMode(true); this._setMode(true);
this._guiModeAvailable = true; this._guiModeAvailable = true;
this._selectedCard = parseInt(ev.detail.selected, 10); this._selectedCard = parseInt(ev.detail.selected, 10);
if (this._cardEditorEl) {
this._cardEditorEl.forceRebuild = true;
}
} }
protected _handleConfigChanged(ev: HASSDomEvent<ConfigChangedEvent>) { protected _handleConfigChanged(ev: HASSDomEvent<ConfigChangedEvent>) {
@@ -226,6 +230,14 @@ export class HuiStackCardEditor
this._guiModeAvailable = ev.detail.guiModeAvailable; this._guiModeAvailable = ev.detail.guiModeAvailable;
} }
protected _handleEditModeChanged(ev: HASSDomEvent<any>) {
ev.stopPropagation();
fireEvent(this, "edit-mode-changed", {
selected: this._selectedCard,
data: ev.detail,
});
}
protected _toggleMode(): void { protected _toggleMode(): void {
this._cardEditorEl?.toggleMode(); this._cardEditorEl?.toggleMode();
} }
@@ -237,6 +249,13 @@ export class HuiStackCardEditor
} }
} }
protected updated(changedProperties) {
if (changedProperties.has("_selectedCard"))
fireEvent(this, "edit-mode-changed", {
selected: this._selectedCard,
});
}
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return [ return [
configElementStyle, configElementStyle,

View File

@@ -53,6 +53,8 @@ export abstract class HuiElementEditor<T> extends LitElement {
@property({ attribute: false }) public lovelace?: LovelaceConfig; @property({ attribute: false }) public lovelace?: LovelaceConfig;
public forceRebuild = false;
@state() private _yaml?: string; @state() private _yaml?: string;
@state() private _config?: T; @state() private _config?: T;
@@ -292,7 +294,11 @@ export abstract class HuiElementEditor<T> extends LitElement {
this._errors = undefined; this._errors = undefined;
this._warnings = undefined; this._warnings = undefined;
if (this._configElementType !== this.configElementType) { if (
this._configElementType !== this.configElementType ||
this.forceRebuild
) {
this.forceRebuild = false;
// If the type has changed, we need to load a new GUI editor // If the type has changed, we need to load a new GUI editor
this._guiSupported = undefined; this._guiSupported = undefined;
this._configElement = undefined; this._configElement = undefined;

View File

@@ -38,7 +38,7 @@ export interface LovelaceBadge extends HTMLElement {
export interface LovelaceCard extends HTMLElement { export interface LovelaceCard extends HTMLElement {
hass?: HomeAssistant; hass?: HomeAssistant;
isPanel?: boolean; isPanel?: boolean;
editMode?: boolean; editMode?: any;
getCardSize(): number | Promise<number>; getCardSize(): number | Promise<number>;
setConfig(config: LovelaceCardConfig): void; setConfig(config: LovelaceCardConfig): void;
} }