mirror of
				https://github.com/home-assistant/frontend.git
				synced 2025-10-31 14:39:38 +00:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			20220301.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