Skip to content

Commit

Permalink
104 error custom element doesnt exist on builtin cards (#278)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcokreeft87 authored Oct 14, 2023
1 parent 1194504 commit 5ad26fa
Show file tree
Hide file tree
Showing 9 changed files with 572 additions and 422 deletions.
4 changes: 2 additions & 2 deletions info.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{% if installed %}

### Features
{% if version_installed.replace("v", "").replace(".","") | int < 10730 %}
- Fixed `Custom element doesn't exist`
{% if version_installed.replace("v", "").replace(".","") | int < 10800 %}
- Fixed `Changed loading of cards to await dependencies`
{% endif %}

{% if version_installed.replace("v", "").replace(".","") | int < 10725 %}
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "room-card",
"version": "1.07.30",
"version": "1.08.00",
"description": "Show entities in Home Assistant's Lovelace UI",
"keywords": [
"home-assistant",
Expand Down
16 changes: 8 additions & 8 deletions room-card.js

Large diffs are not rendered by default.

Binary file modified room-card.js.gz
Binary file not shown.
88 changes: 52 additions & 36 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { CSSResult, html, LitElement, PropertyValues, TemplateResult } from 'lit';
import { property, customElement } from 'lit/decorators.js';
import { HomeAssistant, LovelaceCard, LovelaceCardConfig, createThing } from 'custom-card-helpers';
import { HassEntities } from 'home-assistant-js-websocket/dist';

import { checkConfig, entityStyles, renderEntitiesRow, renderInfoEntity, renderRows, renderTitle } from './entity';
import { getEntityIds, hasConfigOrEntitiesChanged, mapStateObject } from './util';
import { getEntityIds, parseConfig } from './util';
import { hideIfCard } from './hide';
import { style } from './styles';
import { HomeAssistantEntity, RoomCardConfig, RoomCardEntity, RoomCardLovelaceCardConfig, RoomCardRow } from './types/room-card-types';
import { RoomCardConfig, RoomCardLovelaceCardConfig } from './types/room-card-types';
import * as packageJson from '../package.json';

console.info(
Expand All @@ -21,24 +22,19 @@ console.info(
type: 'room-card',
name: 'Room card',
preview: false,
description: 'Show multiple entity states, attributes and icons in a single card in Home Assistant\'s Lovelace UI',
description: 'Show multiple entity states, attributes and icons in a single card in Home Assistant\'s Lovelace UI',
});
/* eslint-enable @typescript-eslint/no-explicit-any */

@customElement('room-card')
export default class RoomCard extends LitElement {
@property() _hass?: HomeAssistant;
private _hass?: HomeAssistant;
@property() monitoredStates?: HassEntities;
@property() config?: RoomCardConfig;
@property() _helpers: { createCardElement(config: LovelaceCardConfig): LovelaceCard }

private entity: RoomCardEntity | undefined;
private info_entities: RoomCardEntity[] = [];
private entities: RoomCardEntity[] = [];
private rows: RoomCardRow[] = [];
private stateObj: HomeAssistantEntity | undefined;

getChildCustomCardTypes(cards: RoomCardLovelaceCardConfig[], target: Set<string>) {
if (!cards) return;
if (!cards) return;

for (const card of cards) {
if (card.type.indexOf('custom:') === 0) {
Expand All @@ -50,7 +46,7 @@ export default class RoomCard extends LitElement {

async waitForDependentComponents(config: RoomCardConfig) {
const distinctTypes = new Set<string>();
this.getChildCustomCardTypes(config.cards, distinctTypes);
this.getChildCustomCardTypes(config.cards, distinctTypes);
await Promise.all(Array.from(distinctTypes).map(type => customElements.whenDefined(type)));
}

Expand All @@ -69,48 +65,68 @@ export default class RoomCard extends LitElement {
}

protected shouldUpdate(changedProps: PropertyValues): boolean {
return hasConfigOrEntitiesChanged(this.config, changedProps);
}
const result = this.monitoredStates !== undefined
&& this.config !== undefined
&& changedProps.size > 0
&& this._helpers !== undefined
&& this._helpers.createCardElement !== undefined;

set hass(hass: HomeAssistant) {
this._hass = hass;

if (hass && this.config) {
this.stateObj = this.config.entity !== undefined ? hass.states[this.config.entity] : undefined;
this.entity = this.config.entity !== undefined ? { ...this.config, stateObj: this.stateObj } : undefined;

this.info_entities = this.config.info_entities?.map(entity => mapStateObject(entity, hass, this.config)) ?? [];
return result;
}

this.entities = this.config.entities?.map(entity => mapStateObject(entity, hass, this.config)) ?? [];
this.rows =
this.config.rows?.map((row) => {
const rowEntities = row.entities?.map(entity => mapStateObject(entity, hass, this.config));
return { entities: rowEntities, hide_if: row.hide_if, content_alignment: row.content_alignment };
}) ?? [];
updateMonitoredStates(hass: HomeAssistant): void {
const newStates = { ...this.monitoredStates };
let anyUpdates = false;

for (const entityId of this.config.entityIds) {
if (entityId in hass.states) {
const monitoredEntity = this.monitoredStates && this.monitoredStates[entityId];

/* istanbul ignore next */
if (!this.monitoredStates || monitoredEntity?.last_updated < hass.states[entityId].last_updated ||
monitoredEntity?.last_changed < hass.states[entityId].last_changed) {
anyUpdates = hass.states[entityId] !== newStates[entityId];
newStates[entityId] = hass.states[entityId];
}
} else if (this.monitoredStates && entityId in this.monitoredStates) {
anyUpdates = true;
delete newStates[entityId];
}
}

this.config.hass = hass;
if (anyUpdates) {
this.monitoredStates = newStates;
}
}

@property()
get hass() { return this._hass; }
set hass(hass: HomeAssistant) {
this.updateMonitoredStates(hass);
this._hass = hass;
}

static get styles(): CSSResult {
return style;
}

render() : TemplateResult<1> {
render(): TemplateResult<1> {
if (!this._hass || !this.config) return html``;

const { entity, info_entities, entities, rows, stateObj } = parseConfig(this.config, this._hass);

try {
return html`
<ha-card elevation="2" style="${entityStyles(this.config.card_styles, this.stateObj, this._hass)}">
<ha-card elevation="2" style="${entityStyles(this.config.card_styles, stateObj, this._hass)}">
<div class="card-header">
${renderTitle(this.config, this._hass, this, this.entity)}
${renderTitle(this.config, this._hass, this, entity)}
<div class="entities-info-row">
${this.info_entities.map((entity) => renderInfoEntity(entity, this._hass, this))}
${info_entities.map((entity) => renderInfoEntity(entity, this._hass, this))}
</div>
</div>
${this.rows !== undefined && this.rows.length > 0 ?
renderRows(this.rows, this._hass, this) :
renderEntitiesRow(this.config, this.entities, this._hass, this)}
${rows !== undefined && rows.length > 0 ?
renderRows(rows, this._hass, this) :
renderEntitiesRow(this.config, entities, this._hass, this)}
${this.config.cards?.map((card) => this.createCardElement(card, this._hass))}
</ha-card>
`;
Expand Down
21 changes: 21 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,25 @@ export const evalTemplate = (hass: HomeAssistant | undefined, state: HassEntity,

export const renderClasses = (config: RoomCardConfig | RoomCardRow, classes?: string): string => {
return `entities-row ${config.content_alignment ? `content-${config.content_alignment}` : 'content-left'}${classes !== undefined ? ` ${classes}` : '' }`;
}

export const parseConfig = (config?: RoomCardConfig, hass?: HomeAssistant): { entity?: RoomCardEntity, info_entities: RoomCardEntity[], entities: RoomCardEntity[], rows?: RoomCardRow[], stateObj?: HomeAssistantEntity } => {
const result = { info_entities: [], entities: [] } as { entity?: RoomCardEntity, info_entities: RoomCardEntity[], entities: RoomCardEntity[], rows?: RoomCardRow[], stateObj?: HomeAssistantEntity };

if (!hass || !config) return result;

result.stateObj = config.entity !== undefined ? hass.states[config.entity] : undefined;
result.entity = config.entity !== undefined ? { ...config, stateObj: result.stateObj } : undefined;
result.info_entities = config.info_entities?.map(entity => mapStateObject(entity, hass, config)) ?? [];
result.entities = config.entities?.map(entity => mapStateObject(entity, hass, config)) ?? [];

result.rows =
config.rows?.map((row) => {
const rowEntities = row.entities?.map(entity => mapStateObject(entity, hass, config));
return { entities: rowEntities, hide_if: row.hide_if, content_alignment: row.content_alignment };
}) ?? [];

config.hass = hass;

return result;
}
Loading

0 comments on commit 5ad26fa

Please sign in to comment.