mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 10:16:46 +00:00
Convert hui-view to Lit (#2265)
* Convert hui-view to Lit * Add super call to updated * Update src/panels/lovelace/hui-view.ts Co-Authored-By: balloob <paulus@home-assistant.io> * Apply suggestions from code review Co-Authored-By: balloob <paulus@home-assistant.io> * Address comments" * Fix things
This commit is contained in:
parent
ccc6262026
commit
767307ef47
@ -14,9 +14,9 @@ import { swapCard, moveCard } from "../editor/config-util";
|
|||||||
|
|
||||||
export class HuiCardOptions extends hassLocalizeLitMixin(LitElement) {
|
export class HuiCardOptions extends hassLocalizeLitMixin(LitElement) {
|
||||||
public cardConfig?: LovelaceCardConfig;
|
public cardConfig?: LovelaceCardConfig;
|
||||||
protected hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
protected lovelace?: Lovelace;
|
public lovelace?: Lovelace;
|
||||||
protected path?: [number, number];
|
public path?: [number, number];
|
||||||
|
|
||||||
static get properties(): PropertyDeclarations {
|
static get properties(): PropertyDeclarations {
|
||||||
return { hass: {}, lovelace: {}, path: {} };
|
return { hass: {}, lovelace: {}, path: {} };
|
||||||
|
@ -38,6 +38,9 @@ import "./components/notifications/hui-notification-drawer";
|
|||||||
import "./components/notifications/hui-notifications-button";
|
import "./components/notifications/hui-notifications-button";
|
||||||
import "./hui-unused-entities";
|
import "./hui-unused-entities";
|
||||||
import "./hui-view";
|
import "./hui-view";
|
||||||
|
// Not a duplicate import, this one is for type
|
||||||
|
// tslint:disable-next-line
|
||||||
|
import { HUIView } from "./hui-view";
|
||||||
import createCardElement from "./common/create-card-element";
|
import createCardElement from "./common/create-card-element";
|
||||||
import { showEditViewDialog } from "./editor/view-editor/show-edit-view-dialog";
|
import { showEditViewDialog } from "./editor/view-editor/show-edit-view-dialog";
|
||||||
import { Lovelace } from "./types";
|
import { Lovelace } from "./types";
|
||||||
@ -336,10 +339,10 @@ class HUIRoot extends hassLocalizeLitMixin(LitElement) {
|
|||||||
super.updated(changedProperties);
|
super.updated(changedProperties);
|
||||||
|
|
||||||
const view = this._view;
|
const view = this._view;
|
||||||
const huiView = view.lastChild as any;
|
const huiView = view.lastChild as HUIView;
|
||||||
|
|
||||||
if (changedProperties.has("columns") && huiView) {
|
if (changedProperties.has("columns") && huiView) {
|
||||||
(this._view.lastChild as any).columns = this.columns;
|
huiView.columns = this.columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedProperties.has("hass") && huiView) {
|
if (changedProperties.has("hass") && huiView) {
|
||||||
|
@ -1,20 +1,75 @@
|
|||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
import {
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyValues,
|
||||||
|
PropertyDeclarations,
|
||||||
|
} from "@polymer/lit-element";
|
||||||
|
import { TemplateResult } from "lit-html";
|
||||||
|
import { PolymerElement } from "@polymer/polymer";
|
||||||
|
|
||||||
import "../../components/entity/ha-state-label-badge";
|
import "../../components/entity/ha-state-label-badge";
|
||||||
|
|
||||||
import applyThemesOnElement from "../../common/dom/apply_themes_on_element";
|
import applyThemesOnElement from "../../common/dom/apply_themes_on_element";
|
||||||
|
|
||||||
import EventsMixin from "../../mixins/events-mixin";
|
import { hassLocalizeLitMixin } from "../../mixins/lit-localize-mixin";
|
||||||
import localizeMixin from "../../mixins/localize-mixin";
|
import { LovelaceViewConfig } from "../../data/lovelace";
|
||||||
|
import { HomeAssistant } from "../../types";
|
||||||
|
|
||||||
|
import { Lovelace, LovelaceCard } from "./types";
|
||||||
import createCardElement from "./common/create-card-element";
|
import createCardElement from "./common/create-card-element";
|
||||||
import { computeCardSize } from "./common/compute-card-size";
|
import { computeCardSize } from "./common/compute-card-size";
|
||||||
import { showEditCardDialog } from "./editor/card-editor/show-edit-card-dialog";
|
import { showEditCardDialog } from "./editor/card-editor/show-edit-card-dialog";
|
||||||
|
|
||||||
let editCodeLoaded = false;
|
let editCodeLoaded = false;
|
||||||
|
|
||||||
class HUIView extends localizeMixin(EventsMixin(PolymerElement)) {
|
export class HUIView extends hassLocalizeLitMixin(LitElement) {
|
||||||
static get template() {
|
public hass?: HomeAssistant;
|
||||||
|
public lovelace?: Lovelace;
|
||||||
|
public columns?: number;
|
||||||
|
public index?: number;
|
||||||
|
private _cards: LovelaceCard[];
|
||||||
|
private _badges: Array<{ element: PolymerElement; entityId: string }>;
|
||||||
|
|
||||||
|
static get properties(): PropertyDeclarations {
|
||||||
|
return {
|
||||||
|
hass: {},
|
||||||
|
lovelace: {},
|
||||||
|
columns: {},
|
||||||
|
index: {},
|
||||||
|
_cards: {},
|
||||||
|
_badges: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._cards = [];
|
||||||
|
this._badges = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
${this.renderStyles()}
|
||||||
|
<div id="badges"></div>
|
||||||
|
<div id="columns"></div>
|
||||||
|
${
|
||||||
|
this.lovelace!.editMode
|
||||||
|
? html`
|
||||||
|
<paper-fab
|
||||||
|
elevated="2"
|
||||||
|
icon="hass:plus"
|
||||||
|
title="${
|
||||||
|
this.localize("ui.panel.lovelace.editor.edit_card.add")
|
||||||
|
}"
|
||||||
|
@click="${this._addCard}"
|
||||||
|
></paper-fab>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected renderStyles(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<style>
|
<style>
|
||||||
:host {
|
:host {
|
||||||
@ -57,10 +112,6 @@ class HUIView extends localizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
paper-fab[hidden] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 500px) {
|
@media (max-width: 500px) {
|
||||||
:host {
|
:host {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
@ -79,58 +130,60 @@ class HUIView extends localizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div id="badges"></div>
|
|
||||||
<div id="columns"></div>
|
|
||||||
<paper-fab
|
|
||||||
hidden$="[[!lovelace.editMode]]"
|
|
||||||
elevated="2"
|
|
||||||
icon="hass:plus"
|
|
||||||
title=[[localize("ui.panel.lovelace.editor.edit_card.add")]]
|
|
||||||
on-click="_addCard"
|
|
||||||
></paper-fab>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get properties() {
|
protected updated(changedProperties: PropertyValues): void {
|
||||||
return {
|
super.updated(changedProperties);
|
||||||
hass: {
|
|
||||||
type: Object,
|
const lovelace = this.lovelace!;
|
||||||
observer: "_hassChanged",
|
|
||||||
},
|
if (lovelace.editMode && !editCodeLoaded) {
|
||||||
lovelace: {
|
editCodeLoaded = true;
|
||||||
type: Object,
|
import(/* webpackChunkName: "hui-view-editable" */ "./hui-view-editable");
|
||||||
observer: "_lovelaceChanged",
|
}
|
||||||
},
|
|
||||||
config: Object,
|
let editModeChanged = false;
|
||||||
columns: Number,
|
let configChanged = false;
|
||||||
editMode: Boolean,
|
|
||||||
index: Number,
|
if (changedProperties.has("lovelace")) {
|
||||||
};
|
const oldLovelace = changedProperties.get("lovelace") as Lovelace;
|
||||||
|
editModeChanged =
|
||||||
|
!oldLovelace || lovelace.editMode !== oldLovelace.editMode;
|
||||||
|
configChanged = !oldLovelace || lovelace.config !== oldLovelace.config;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configChanged) {
|
||||||
|
this._createBadges(lovelace.config.views[this.index!]);
|
||||||
|
} else if (changedProperties.has("hass")) {
|
||||||
|
this._badges.forEach((badge) => {
|
||||||
|
const { element, entityId } = badge;
|
||||||
|
element.setProperties({
|
||||||
|
hass: this.hass,
|
||||||
|
state: this.hass!.states[entityId],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configChanged || editModeChanged || changedProperties.has("columns")) {
|
||||||
|
this._createCards(lovelace.config.views[this.index!]);
|
||||||
|
} else if (changedProperties.has("hass")) {
|
||||||
|
this._cards.forEach((element) => {
|
||||||
|
element.hass = this.hass;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static get observers() {
|
private _addCard(): void {
|
||||||
return [
|
|
||||||
// Put all properties in 1 observer so we only call configChanged once
|
|
||||||
"_createBadges(config)",
|
|
||||||
"_createCards(config, columns, editMode)",
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this._cards = [];
|
|
||||||
this._badges = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
_addCard() {
|
|
||||||
showEditCardDialog(this, {
|
showEditCardDialog(this, {
|
||||||
lovelace: this.lovelace,
|
lovelace: this.lovelace!,
|
||||||
path: [this.index],
|
path: [this.index!],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_createBadges(config) {
|
private _createBadges(config: LovelaceViewConfig): void {
|
||||||
const root = this.$.badges;
|
const root = this.shadowRoot!.getElementById("badges")!;
|
||||||
|
|
||||||
while (root.lastChild) {
|
while (root.lastChild) {
|
||||||
root.removeChild(root.lastChild);
|
root.removeChild(root.lastChild);
|
||||||
}
|
}
|
||||||
@ -141,14 +194,18 @@ class HUIView extends localizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const elements = [];
|
const elements: HUIView["_badges"] = [];
|
||||||
for (const entityId of config.badges) {
|
for (const entityId of config.badges) {
|
||||||
if (!(entityId in this.hass.states)) continue;
|
if (!(entityId in this.hass!.states)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const element = document.createElement("ha-state-label-badge");
|
const element = document.createElement(
|
||||||
|
"ha-state-label-badge"
|
||||||
|
) as PolymerElement;
|
||||||
element.setProperties({
|
element.setProperties({
|
||||||
hass: this.hass,
|
hass: this.hass,
|
||||||
state: this.hass.states[entityId],
|
state: this.hass!.states[entityId],
|
||||||
});
|
});
|
||||||
elements.push({ element, entityId });
|
elements.push({ element, entityId });
|
||||||
root.appendChild(element);
|
root.appendChild(element);
|
||||||
@ -157,8 +214,8 @@ class HUIView extends localizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
root.style.display = elements.length > 0 ? "block" : "none";
|
root.style.display = elements.length > 0 ? "block" : "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
_createCards(config) {
|
private _createCards(config: LovelaceViewConfig): void {
|
||||||
const root = this.$.columns;
|
const root = this.shadowRoot!.getElementById("columns")!;
|
||||||
|
|
||||||
while (root.lastChild) {
|
while (root.lastChild) {
|
||||||
root.removeChild(root.lastChild);
|
root.removeChild(root.lastChild);
|
||||||
@ -169,14 +226,14 @@ class HUIView extends localizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const elements = [];
|
const elements: LovelaceCard[] = [];
|
||||||
const elementsToAppend = [];
|
const elementsToAppend: HTMLElement[] = [];
|
||||||
config.cards.forEach((cardConfig, cardIndex) => {
|
config.cards.forEach((cardConfig, cardIndex) => {
|
||||||
const element = createCardElement(cardConfig);
|
const element = createCardElement(cardConfig) as LovelaceCard;
|
||||||
element.hass = this.hass;
|
element.hass = this.hass;
|
||||||
elements.push(element);
|
elements.push(element);
|
||||||
|
|
||||||
if (!this.lovelace.editMode) {
|
if (!this.lovelace!.editMode) {
|
||||||
elementsToAppend.push(element);
|
elementsToAppend.push(element);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -184,14 +241,14 @@ class HUIView extends localizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
const wrapper = document.createElement("hui-card-options");
|
const wrapper = document.createElement("hui-card-options");
|
||||||
wrapper.hass = this.hass;
|
wrapper.hass = this.hass;
|
||||||
wrapper.lovelace = this.lovelace;
|
wrapper.lovelace = this.lovelace;
|
||||||
wrapper.path = [this.index, cardIndex];
|
wrapper.path = [this.index!, cardIndex];
|
||||||
wrapper.appendChild(element);
|
wrapper.appendChild(element);
|
||||||
elementsToAppend.push(wrapper);
|
elementsToAppend.push(wrapper);
|
||||||
});
|
});
|
||||||
|
|
||||||
let columns = [];
|
let columns: HTMLElement[][] = [];
|
||||||
const columnEntityCount = [];
|
const columnEntityCount: number[] = [];
|
||||||
for (let i = 0; i < this.columns; i++) {
|
for (let i = 0; i < this.columns!; i++) {
|
||||||
columns.push([]);
|
columns.push([]);
|
||||||
columnEntityCount.push(0);
|
columnEntityCount.push(0);
|
||||||
}
|
}
|
||||||
@ -233,29 +290,15 @@ class HUIView extends localizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
this._cards = elements;
|
this._cards = elements;
|
||||||
|
|
||||||
if ("theme" in config) {
|
if ("theme" in config) {
|
||||||
applyThemesOnElement(root, this.hass.themes, config.theme);
|
applyThemesOnElement(root, this.hass!.themes, config.theme);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_hassChanged(hass) {
|
|
||||||
this._badges.forEach((badge) => {
|
|
||||||
const { element, entityId } = badge;
|
|
||||||
element.setProperties({
|
|
||||||
hass,
|
|
||||||
state: hass.states[entityId],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
this._cards.forEach((element) => {
|
|
||||||
element.hass = hass;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_lovelaceChanged(lovelace) {
|
|
||||||
if (lovelace.editMode && !editCodeLoaded) {
|
|
||||||
editCodeLoaded = true;
|
|
||||||
import(/* webpackChunkName: "hui-view-editable" */ "./hui-view-editable");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-view": HUIView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
customElements.define("hui-view", HUIView);
|
customElements.define("hui-view", HUIView);
|
@ -119,7 +119,7 @@ describe("moveCard", () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = function() {
|
const result = () => {
|
||||||
moveCard(config, [1, 0], [1]);
|
moveCard(config, [1, 0], [1]);
|
||||||
};
|
};
|
||||||
assert.throws(
|
assert.throws(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user