Use report errors instead of strict for template subscription (#17824)

This commit is contained in:
Bram Kragten 2023-09-06 09:53:54 +02:00 committed by GitHub
parent 3a07af6ad2
commit 3c48157793
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 119 additions and 88 deletions

View File

@ -6,6 +6,11 @@ export interface RenderTemplateResult {
listeners: TemplateListeners; listeners: TemplateListeners;
} }
export interface RenderTemplateError {
error: string;
level: "ERROR" | "WARNING";
}
export interface TemplateListeners { export interface TemplateListeners {
all: boolean; all: boolean;
domains: string[]; domains: string[];
@ -27,19 +32,23 @@ interface TemplatePreviewError {
export const subscribeRenderTemplate = ( export const subscribeRenderTemplate = (
conn: Connection, conn: Connection,
onChange: (result: RenderTemplateResult) => void, onChange: (result: RenderTemplateResult | RenderTemplateError) => void,
params: { params: {
template: string; template: string;
entity_ids?: string | string[]; entity_ids?: string | string[];
variables?: Record<string, unknown>; variables?: Record<string, unknown>;
timeout?: number; timeout?: number;
strict?: boolean; strict?: boolean;
report_errors?: boolean;
} }
): Promise<UnsubscribeFunc> => ): Promise<UnsubscribeFunc> =>
conn.subscribeMessage((msg: RenderTemplateResult) => onChange(msg), { conn.subscribeMessage(
type: "render_template", (msg: RenderTemplateResult | RenderTemplateError) => onChange(msg),
...params, {
}); type: "render_template",
...params,
}
);
export const subscribePreviewTemplate = ( export const subscribePreviewTemplate = (
hass: HomeAssistant, hass: HomeAssistant,

View File

@ -4,6 +4,7 @@ import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import { debounce } from "../../../common/util/debounce"; import { debounce } from "../../../common/util/debounce";
import "../../../components/ha-alert";
import "../../../components/ha-circular-progress"; import "../../../components/ha-circular-progress";
import "../../../components/ha-code-editor"; import "../../../components/ha-code-editor";
import { import {
@ -44,6 +45,8 @@ class HaPanelDevTemplate extends LitElement {
@state() private _error?: string; @state() private _error?: string;
@state() private _errorLevel?: "ERROR" | "WARNING";
@state() private _rendering = false; @state() private _rendering = false;
@state() private _templateResult?: RenderTemplateResult; @state() private _templateResult?: RenderTemplateResult;
@ -157,83 +160,87 @@ class HaPanelDevTemplate extends LitElement {
size="small" size="small"
></ha-circular-progress>` ></ha-circular-progress>`
: ""} : ""}
${this._error
? html`<ha-alert
alert-type=${this._errorLevel?.toLowerCase() || "error"}
>${this._error}</ha-alert
>`
: nothing}
${this._templateResult ${this._templateResult
? html`${this.hass.localize( ? html`${this.hass.localize(
"ui.panel.developer-tools.tabs.templates.result_type" "ui.panel.developer-tools.tabs.templates.result_type"
)}: )}:
${resultType}` ${resultType}
: ""} <!-- prettier-ignore -->
<!-- prettier-ignore --> <pre class="rendered ${classMap({
<pre [resultType]: resultType,
class="rendered ${classMap({ })}"
error: Boolean(this._error), >${type === "object"
[resultType]: resultType, ? JSON.stringify(this._templateResult.result, null, 2)
})}" : this._templateResult.result}</pre>
>${this._error}${type === "object" ${this._templateResult.listeners.time
? JSON.stringify(this._templateResult!.result, null, 2) ? html`
: this._templateResult?.result}</pre> <p>
${this._templateResult?.listeners.time ${this.hass.localize(
? html` "ui.panel.developer-tools.tabs.templates.time"
<p> )}
${this.hass.localize( </p>
"ui.panel.developer-tools.tabs.templates.time" `
)} : ""}
</p> ${!this._templateResult.listeners
` ? nothing
: nothing} : this._templateResult.listeners.all
${!this._templateResult?.listeners ? html`
? nothing <p class="all_listeners">
: this._templateResult.listeners.all ${this.hass.localize(
? html` "ui.panel.developer-tools.tabs.templates.all_listeners"
<p class="all_listeners"> )}
${this.hass.localize( </p>
"ui.panel.developer-tools.tabs.templates.all_listeners" `
)} : this._templateResult.listeners.domains.length ||
</p> this._templateResult.listeners.entities.length
` ? html`
: this._templateResult.listeners.domains.length || <p>
this._templateResult.listeners.entities.length ${this.hass.localize(
? html` "ui.panel.developer-tools.tabs.templates.listeners"
<p> )}
${this.hass.localize( </p>
"ui.panel.developer-tools.tabs.templates.listeners" <ul>
)} ${this._templateResult.listeners.domains
</p> .sort()
<ul> .map(
${this._templateResult.listeners.domains (domain) => html`
.sort() <li>
.map( <b
(domain) => html` >${this.hass.localize(
<li> "ui.panel.developer-tools.tabs.templates.domain"
<b )}</b
>${this.hass.localize( >: ${domain}
"ui.panel.developer-tools.tabs.templates.domain" </li>
)}</b `
>: ${domain} )}
</li> ${this._templateResult.listeners.entities
` .sort()
)} .map(
${this._templateResult.listeners.entities (entity_id) => html`
.sort() <li>
.map( <b
(entity_id) => html` >${this.hass.localize(
<li> "ui.panel.developer-tools.tabs.templates.entity"
<b )}</b
>${this.hass.localize( >: ${entity_id}
"ui.panel.developer-tools.tabs.templates.entity" </li>
)}</b `
>: ${entity_id} )}
</li> </ul>
` `
)} : !this._templateResult.listeners.time
</ul> ? html`<span class="all_listeners">
` ${this.hass.localize(
: !this._templateResult?.listeners.time "ui.panel.developer-tools.tabs.templates.no_listeners"
? html`<span class="all_listeners"> )}
${this.hass.localize( </span>`
"ui.panel.developer-tools.tabs.templates.no_listeners" : nothing}`
)}
</span>`
: nothing} : nothing}
</div> </div>
</div> </div>
@ -276,6 +283,7 @@ class HaPanelDevTemplate extends LitElement {
.render-pane { .render-pane {
position: relative; position: relative;
max-width: 50%; max-width: 50%;
flex: 1;
} }
.render-spinner { .render-spinner {
@ -284,6 +292,11 @@ class HaPanelDevTemplate extends LitElement {
right: 8px; right: 8px;
} }
ha-alert {
margin-bottom: 8px;
display: block;
}
.rendered { .rendered {
@apply --paper-font-code1; @apply --paper-font-code1;
clear: both; clear: both;
@ -297,10 +310,6 @@ class HaPanelDevTemplate extends LitElement {
color: var(--warning-color); color: var(--warning-color);
} }
.rendered.error {
color: var(--error-color);
}
@media all and (max-width: 870px) { @media all and (max-width: 870px) {
.render-pane { .render-pane {
max-width: 100%; max-width: 100%;
@ -323,6 +332,7 @@ class HaPanelDevTemplate extends LitElement {
this._template = ev.detail.value; this._template = ev.detail.value;
if (this._error) { if (this._error) {
this._error = undefined; this._error = undefined;
this._errorLevel = undefined;
} }
this._debounceRender(); this._debounceRender();
} }
@ -334,20 +344,31 @@ class HaPanelDevTemplate extends LitElement {
this._unsubRenderTemplate = subscribeRenderTemplate( this._unsubRenderTemplate = subscribeRenderTemplate(
this.hass.connection, this.hass.connection,
(result) => { (result) => {
this._templateResult = result; if ("error" in result) {
this._error = undefined; // We show the latest error, or a warning if there are no errors
if (result.level === "ERROR" || this._errorLevel !== "ERROR") {
this._error = result.error;
this._errorLevel = result.level;
}
} else {
this._templateResult = result;
this._error = undefined;
this._errorLevel = undefined;
}
}, },
{ {
template: this._template, template: this._template,
timeout: 3, timeout: 3,
strict: true, report_errors: true,
} }
); );
await this._unsubRenderTemplate; await this._unsubRenderTemplate;
} catch (err: any) { } catch (err: any) {
this._error = "Unknown error"; this._error = "Unknown error";
this._errorLevel = undefined;
if (err.message) { if (err.message) {
this._error = err.message; this._error = err.message;
this._errorLevel = undefined;
this._templateResult = undefined; this._templateResult = undefined;
} }
this._unsubRenderTemplate = undefined; this._unsubRenderTemplate = undefined;

View File

@ -127,7 +127,7 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard {
this._unsubRenderTemplate = subscribeRenderTemplate( this._unsubRenderTemplate = subscribeRenderTemplate(
this.hass.connection, this.hass.connection,
(result) => { (result) => {
this._templateResult = result; this._templateResult = result as RenderTemplateResult;
}, },
{ {
template: this._config.content, template: this._config.content,
@ -139,6 +139,7 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard {
strict: true, strict: true,
} }
); );
await this._unsubRenderTemplate;
} catch (_err) { } catch (_err) {
this._templateResult = { this._templateResult = {
result: this._config!.content, result: this._config!.content,