mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-14 03:39:26 +00:00
Compare commits
3 Commits
20210423.0
...
template-e
Author | SHA1 | Date | |
---|---|---|---|
![]() |
72bf0c918a | ||
![]() |
419f5d13bf | ||
![]() |
16549b3404 |
88
src/dialogs/template-editor/ha-template-editor.ts
Normal file
88
src/dialogs/template-editor/ha-template-editor.ts
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import "../../panels/developer-tools/template/developer-tools-template";
|
||||||
|
import "@material/mwc-button/mwc-button";
|
||||||
|
import "../../components/ha-code-editor";
|
||||||
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import "@material/mwc-list/mwc-list-item";
|
||||||
|
import {
|
||||||
|
css,
|
||||||
|
CSSResultArray,
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
internalProperty,
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
} from "lit-element";
|
||||||
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
|
import "../../components/ha-circular-progress";
|
||||||
|
import "../../components/ha-dialog";
|
||||||
|
import "../../components/ha-header-bar";
|
||||||
|
import { haStyle } from "../../resources/styles";
|
||||||
|
import { HomeAssistant } from "../../types";
|
||||||
|
import { TemplateEditorParams } from "./show-dialog-template-editor";
|
||||||
|
|
||||||
|
@customElement("ha-template-editor")
|
||||||
|
export class TemplateEditor extends LitElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@internalProperty() private _opened = false;
|
||||||
|
|
||||||
|
@internalProperty() private _startingTemplate?: string;
|
||||||
|
|
||||||
|
public showDialog(params: TemplateEditorParams) {
|
||||||
|
this._startingTemplate = `${params.startingTemplate}\n\n\n\n`;
|
||||||
|
this._opened = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public closeDialog() {
|
||||||
|
this._opened = false;
|
||||||
|
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
if (!this._opened) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`<ha-dialog
|
||||||
|
.heading=${this.hass.localize(
|
||||||
|
"ui.panel.developer-tools.tabs.templates.editor"
|
||||||
|
)}
|
||||||
|
open
|
||||||
|
@closed=${this.closeDialog}
|
||||||
|
hideActions
|
||||||
|
>
|
||||||
|
<div class="content">
|
||||||
|
<developer-tools-template
|
||||||
|
.narrow=${true}
|
||||||
|
.hass=${this.hass}
|
||||||
|
.simple=${true}
|
||||||
|
.startingTemplate=${this._startingTemplate}
|
||||||
|
></developer-tools-template>
|
||||||
|
</div>
|
||||||
|
</ha-dialog>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultArray {
|
||||||
|
return [
|
||||||
|
haStyle,
|
||||||
|
css`
|
||||||
|
:host {
|
||||||
|
width: 100%;
|
||||||
|
--mdc-dialog-max-width: 700px;
|
||||||
|
--mdc-dialog-min-width: 700px;
|
||||||
|
--mdc-dialog-max-height: calc(100% - 72px);
|
||||||
|
--mdc-dialog-min-height: 400px;
|
||||||
|
--dialog-content-padding: 0px;
|
||||||
|
--template-results-width: 100%;
|
||||||
|
--mdc-dialog-content-ink-color: var(--primary-text-color);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-template-editor": TemplateEditor;
|
||||||
|
}
|
||||||
|
}
|
21
src/dialogs/template-editor/show-dialog-template-editor.ts
Normal file
21
src/dialogs/template-editor/show-dialog-template-editor.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
|
|
||||||
|
export interface TemplateEditorParams {
|
||||||
|
startingTemplate?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const loadTemplateEditor = () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "template-editor-dialog" */ "./ha-template-editor"
|
||||||
|
);
|
||||||
|
|
||||||
|
export const showTemplateEditor = (
|
||||||
|
element: HTMLElement,
|
||||||
|
dialogParams: TemplateEditorParams
|
||||||
|
): void => {
|
||||||
|
fireEvent(element, "show-dialog", {
|
||||||
|
dialogTag: "ha-template-editor",
|
||||||
|
dialogImport: loadTemplateEditor,
|
||||||
|
dialogParams,
|
||||||
|
});
|
||||||
|
};
|
@@ -48,6 +48,10 @@ class HaPanelDevTemplate extends LitElement {
|
|||||||
|
|
||||||
@property() public narrow!: boolean;
|
@property() public narrow!: boolean;
|
||||||
|
|
||||||
|
@property() public simple = false;
|
||||||
|
|
||||||
|
@property() public startingTemplate?: string;
|
||||||
|
|
||||||
@internalProperty() private _error?: string;
|
@internalProperty() private _error?: string;
|
||||||
|
|
||||||
@internalProperty() private _rendering = false;
|
@internalProperty() private _rendering = false;
|
||||||
@@ -72,7 +76,9 @@ class HaPanelDevTemplate extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected firstUpdated() {
|
protected firstUpdated() {
|
||||||
if (localStorage && localStorage["panel-dev-template-template"]) {
|
if (this.startingTemplate) {
|
||||||
|
this._template = this.startingTemplate;
|
||||||
|
} else if (localStorage && localStorage["panel-dev-template-template"]) {
|
||||||
this._template = localStorage["panel-dev-template-template"];
|
this._template = localStorage["panel-dev-template-template"];
|
||||||
} else {
|
} else {
|
||||||
this._template = DEMO_TEMPLATE;
|
this._template = DEMO_TEMPLATE;
|
||||||
@@ -82,13 +88,6 @@ class HaPanelDevTemplate extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
const type = typeof this._templateResult?.result;
|
|
||||||
const resultType =
|
|
||||||
type === "object"
|
|
||||||
? Array.isArray(this._templateResult?.result)
|
|
||||||
? "list"
|
|
||||||
: "dict"
|
|
||||||
: type;
|
|
||||||
return html`
|
return html`
|
||||||
<div
|
<div
|
||||||
class="content ${classMap({
|
class="content ${classMap({
|
||||||
@@ -97,42 +96,7 @@ class HaPanelDevTemplate extends LitElement {
|
|||||||
})}"
|
})}"
|
||||||
>
|
>
|
||||||
<div class="edit-pane">
|
<div class="edit-pane">
|
||||||
<p>
|
${this.simple ? "" : this._renderDescription()}
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.developer-tools.tabs.templates.description"
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="http://jinja.pocoo.org/docs/dev/templates/"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
>${this.hass.localize(
|
|
||||||
"ui.panel.developer-tools.tabs.templates.jinja_documentation"
|
|
||||||
)}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="${documentationUrl(
|
|
||||||
this.hass,
|
|
||||||
"/docs/configuration/templating/"
|
|
||||||
)}"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.developer-tools.tabs.templates.template_extensions"
|
|
||||||
)}</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.developer-tools.tabs.templates.editor"
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<ha-code-editor
|
<ha-code-editor
|
||||||
mode="jinja2"
|
mode="jinja2"
|
||||||
.value=${this._template}
|
.value=${this._template}
|
||||||
@@ -147,103 +111,156 @@ class HaPanelDevTemplate extends LitElement {
|
|||||||
</mwc-button>
|
</mwc-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="render-pane">
|
${this._renderResult()}
|
||||||
${this._rendering
|
|
||||||
? html`<ha-circular-progress
|
|
||||||
class="render-spinner"
|
|
||||||
active
|
|
||||||
size="small"
|
|
||||||
></ha-circular-progress>`
|
|
||||||
: ""}
|
|
||||||
${this._templateResult
|
|
||||||
? html`${this.hass.localize(
|
|
||||||
"ui.panel.developer-tools.tabs.templates.result_type"
|
|
||||||
)}:
|
|
||||||
${resultType}`
|
|
||||||
: ""}
|
|
||||||
<!-- prettier-ignore -->
|
|
||||||
<pre
|
|
||||||
class="rendered ${classMap({
|
|
||||||
error: Boolean(this._error),
|
|
||||||
[resultType]: resultType,
|
|
||||||
})}"
|
|
||||||
>${this._error}${type === "object"
|
|
||||||
? JSON.stringify(this._templateResult!.result, null, 2)
|
|
||||||
: this._templateResult?.result}</pre>
|
|
||||||
${this._templateResult?.listeners.time
|
|
||||||
? html`
|
|
||||||
<p>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.developer-tools.tabs.templates.time"
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
${!this._templateResult?.listeners
|
|
||||||
? ""
|
|
||||||
: this._templateResult.listeners.all
|
|
||||||
? html`
|
|
||||||
<p class="all_listeners">
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.developer-tools.tabs.templates.all_listeners"
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
`
|
|
||||||
: this._templateResult.listeners.domains.length ||
|
|
||||||
this._templateResult.listeners.entities.length
|
|
||||||
? html`
|
|
||||||
<p>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.developer-tools.tabs.templates.listeners"
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
${this._templateResult.listeners.domains
|
|
||||||
.sort()
|
|
||||||
.map(
|
|
||||||
(domain) =>
|
|
||||||
html`
|
|
||||||
<li>
|
|
||||||
<b
|
|
||||||
>${this.hass.localize(
|
|
||||||
"ui.panel.developer-tools.tabs.templates.domain"
|
|
||||||
)}</b
|
|
||||||
>: ${domain}
|
|
||||||
</li>
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
${this._templateResult.listeners.entities
|
|
||||||
.sort()
|
|
||||||
.map(
|
|
||||||
(entity_id) =>
|
|
||||||
html`
|
|
||||||
<li>
|
|
||||||
<b
|
|
||||||
>${this.hass.localize(
|
|
||||||
"ui.panel.developer-tools.tabs.templates.entity"
|
|
||||||
)}</b
|
|
||||||
>: ${entity_id}
|
|
||||||
</li>
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
`
|
|
||||||
: !this._templateResult?.listeners.time
|
|
||||||
? html` <span class="all_listeners">
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.developer-tools.tabs.templates.no_listeners"
|
|
||||||
)}
|
|
||||||
</span>`
|
|
||||||
: html``}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _renderResult() {
|
||||||
|
const type = typeof this._templateResult?.result;
|
||||||
|
const resultType =
|
||||||
|
type === "object"
|
||||||
|
? Array.isArray(this._templateResult?.result)
|
||||||
|
? "list"
|
||||||
|
: "dict"
|
||||||
|
: type;
|
||||||
|
|
||||||
|
return html`<div class="render-pane">
|
||||||
|
${this._rendering
|
||||||
|
? html`<ha-circular-progress
|
||||||
|
class="render-spinner"
|
||||||
|
active
|
||||||
|
size="small"
|
||||||
|
></ha-circular-progress>`
|
||||||
|
: ""}
|
||||||
|
${this._templateResult
|
||||||
|
? html`${this.hass.localize(
|
||||||
|
"ui.panel.developer-tools.tabs.templates.result_type"
|
||||||
|
)}:
|
||||||
|
${resultType}`
|
||||||
|
: ""}
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<pre
|
||||||
|
class="rendered ${classMap({
|
||||||
|
error: Boolean(this._error),
|
||||||
|
[resultType]: resultType,
|
||||||
|
})}"
|
||||||
|
>${this._error}${type === "object"
|
||||||
|
? JSON.stringify(this._templateResult!.result, null, 2)
|
||||||
|
: this._templateResult?.result}</pre>
|
||||||
|
${this._templateResult?.listeners.time
|
||||||
|
? html`
|
||||||
|
<p>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.developer-tools.tabs.templates.time"
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
${!this._templateResult?.listeners
|
||||||
|
? ""
|
||||||
|
: this._templateResult.listeners.all
|
||||||
|
? html`
|
||||||
|
<p class="all_listeners">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.developer-tools.tabs.templates.all_listeners"
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
`
|
||||||
|
: this._templateResult.listeners.domains.length ||
|
||||||
|
this._templateResult.listeners.entities.length
|
||||||
|
? html`
|
||||||
|
<p>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.developer-tools.tabs.templates.listeners"
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
${this._templateResult.listeners.domains
|
||||||
|
.sort()
|
||||||
|
.map(
|
||||||
|
(domain) =>
|
||||||
|
html`
|
||||||
|
<li>
|
||||||
|
<b
|
||||||
|
>${this.hass.localize(
|
||||||
|
"ui.panel.developer-tools.tabs.templates.domain"
|
||||||
|
)}</b
|
||||||
|
>: ${domain}
|
||||||
|
</li>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
${this._templateResult.listeners.entities
|
||||||
|
.sort()
|
||||||
|
.map(
|
||||||
|
(entity_id) =>
|
||||||
|
html`
|
||||||
|
<li>
|
||||||
|
<b
|
||||||
|
>${this.hass.localize(
|
||||||
|
"ui.panel.developer-tools.tabs.templates.entity"
|
||||||
|
)}</b
|
||||||
|
>: ${entity_id}
|
||||||
|
</li>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
: !this._templateResult?.listeners.time
|
||||||
|
? html` <span class="all_listeners">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.developer-tools.tabs.templates.no_listeners"
|
||||||
|
)}
|
||||||
|
</span>`
|
||||||
|
: html``}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderDescription() {
|
||||||
|
return html`<p>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.developer-tools.tabs.templates.description"
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="http://jinja.pocoo.org/docs/dev/templates/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>${this.hass.localize(
|
||||||
|
"ui.panel.developer-tools.tabs.templates.jinja_documentation"
|
||||||
|
)}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="${documentationUrl(
|
||||||
|
this.hass,
|
||||||
|
"/docs/configuration/templating/"
|
||||||
|
)}"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.developer-tools.tabs.templates.template_extensions"
|
||||||
|
)}</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
${this.hass.localize("ui.panel.developer-tools.tabs.templates.editor")}
|
||||||
|
</p>`;
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultArray {
|
static get styles(): CSSResultArray {
|
||||||
return [
|
return [
|
||||||
haStyle,
|
haStyle,
|
||||||
css`
|
css`
|
||||||
|
:root {
|
||||||
|
--template-results-width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
-ms-user-select: initial;
|
-ms-user-select: initial;
|
||||||
-webkit-user-select: initial;
|
-webkit-user-select: initial;
|
||||||
@@ -264,12 +281,12 @@ class HaPanelDevTemplate extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.horizontal .edit-pane {
|
.horizontal .edit-pane {
|
||||||
max-width: 50%;
|
max-width: var(--template-results-width, 50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.render-pane {
|
.render-pane {
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: 50%;
|
max-width: var(--template-results-width, 50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.render-spinner {
|
.render-spinner {
|
||||||
|
@@ -7,10 +7,15 @@ import {
|
|||||||
} from "../dialogs/quick-bar/show-dialog-quick-bar";
|
} from "../dialogs/quick-bar/show-dialog-quick-bar";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
import { storeState } from "../util/ha-pref-storage";
|
import { storeState } from "../util/ha-pref-storage";
|
||||||
|
import {
|
||||||
|
showTemplateEditor,
|
||||||
|
TemplateEditorParams,
|
||||||
|
} from "../dialogs/template-editor/show-dialog-template-editor";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
"hass-quick-bar": QuickBarParams;
|
"hass-quick-bar": QuickBarParams;
|
||||||
|
"hass-template-editor": TemplateEditorParams;
|
||||||
"hass-enable-shortcuts": HomeAssistant["enableShortcuts"];
|
"hass-enable-shortcuts": HomeAssistant["enableShortcuts"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,18 +37,27 @@ export default <T extends Constructor<HassElement>>(superClass: T) =>
|
|||||||
tinykeys(window, {
|
tinykeys(window, {
|
||||||
e: (ev) => this._showQuickBar(ev),
|
e: (ev) => this._showQuickBar(ev),
|
||||||
c: (ev) => this._showQuickBar(ev, true),
|
c: (ev) => this._showQuickBar(ev, true),
|
||||||
|
t: (ev) => this._showTemplateEditor(ev),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _showQuickBar(e: KeyboardEvent, commandMode = false) {
|
private _showQuickBar(e: KeyboardEvent, commandMode = false) {
|
||||||
if (!this._canShowQuickBar(e)) {
|
if (!this._canShowDialogWithShortcut(e)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
showQuickBar(this, { commandMode });
|
showQuickBar(this, { commandMode });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canShowQuickBar(e: KeyboardEvent) {
|
private _showTemplateEditor(e: KeyboardEvent) {
|
||||||
|
if (!this._canShowDialogWithShortcut(e)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
showTemplateEditor(this, { startingTemplate: "{{ states.sun.sun }}" });
|
||||||
|
}
|
||||||
|
|
||||||
|
private _canShowDialogWithShortcut(e: KeyboardEvent) {
|
||||||
return (
|
return (
|
||||||
this.hass?.user?.is_admin &&
|
this.hass?.user?.is_admin &&
|
||||||
this.hass.enableShortcuts &&
|
this.hass.enableShortcuts &&
|
||||||
|
Reference in New Issue
Block a user