mirror of
https://github.com/home-assistant/frontend.git
synced 2025-11-09 19:09:48 +00:00
Add area, device, floor and formatted state to template editor completions (#26383)
This commit is contained in:
58
src/components/ha-code-editor-completion-items.ts
Normal file
58
src/components/ha-code-editor-completion-items.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators";
|
||||||
|
|
||||||
|
export interface CompletionItem {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
subValue?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@customElement("ha-code-editor-completion-items")
|
||||||
|
export class HaCodeEditorCompletionItems extends LitElement {
|
||||||
|
@property({ attribute: false }) public items: CompletionItem[] = [];
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return this.items.map(
|
||||||
|
(item) => html`
|
||||||
|
<span><strong>${item.label}</strong>:</span>
|
||||||
|
<span
|
||||||
|
>${item.value}${item.subValue && item.subValue.length > 0
|
||||||
|
? // prettier-ignore
|
||||||
|
html` (<pre>${item.subValue}</pre>)`
|
||||||
|
: nothing}</span
|
||||||
|
>
|
||||||
|
`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static styles = css`
|
||||||
|
:host {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
gap: 6px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-flow: wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin: 0 3px;
|
||||||
|
padding: 3px;
|
||||||
|
background-color: var(--markdown-code-background-color, none);
|
||||||
|
border-radius: var(--ha-border-radius-sm, 4px);
|
||||||
|
line-height: var(--ha-line-height-condensed);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-code-editor-completion-items": HaCodeEditorCompletionItems;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import type {
|
import type {
|
||||||
Completion,
|
Completion,
|
||||||
CompletionContext,
|
CompletionContext,
|
||||||
|
CompletionInfo,
|
||||||
CompletionResult,
|
CompletionResult,
|
||||||
CompletionSource,
|
CompletionSource,
|
||||||
} from "@codemirror/autocomplete";
|
} from "@codemirror/autocomplete";
|
||||||
@@ -9,14 +10,17 @@ import type { EditorView, KeyBinding, ViewUpdate } from "@codemirror/view";
|
|||||||
import { mdiArrowExpand, mdiArrowCollapse } from "@mdi/js";
|
import { mdiArrowExpand, mdiArrowCollapse } from "@mdi/js";
|
||||||
import type { HassEntities } from "home-assistant-js-websocket";
|
import type { HassEntities } from "home-assistant-js-websocket";
|
||||||
import type { PropertyValues } from "lit";
|
import type { PropertyValues } from "lit";
|
||||||
import { css, ReactiveElement } from "lit";
|
import { css, ReactiveElement, html, render } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { stopPropagation } from "../common/dom/stop_propagation";
|
import { stopPropagation } from "../common/dom/stop_propagation";
|
||||||
|
import { getEntityContext } from "../common/entity/context/get_entity_context";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
|
import type { CompletionItem } from "./ha-code-editor-completion-items";
|
||||||
import "./ha-icon";
|
import "./ha-icon";
|
||||||
import "./ha-icon-button";
|
import "./ha-icon-button";
|
||||||
|
import "./ha-code-editor-completion-items";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
@@ -324,15 +328,72 @@ export class HaCodeEditor extends ReactiveElement {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private _renderInfo = (completion: Completion): CompletionInfo => {
|
||||||
|
const key = completion.label;
|
||||||
|
const context = getEntityContext(this.hass!.states[key], this.hass!);
|
||||||
|
|
||||||
|
const completionInfo = document.createElement("div");
|
||||||
|
completionInfo.classList.add("completion-info");
|
||||||
|
|
||||||
|
const formattedState = this.hass!.formatEntityState(this.hass!.states[key]);
|
||||||
|
|
||||||
|
const completionItems: CompletionItem[] = [
|
||||||
|
{
|
||||||
|
label: this.hass!.localize(
|
||||||
|
"ui.components.entity.entity-state-picker.state"
|
||||||
|
),
|
||||||
|
value: formattedState,
|
||||||
|
subValue:
|
||||||
|
// If the state exactly matches the formatted state, don't show the raw state
|
||||||
|
this.hass!.states[key].state === formattedState
|
||||||
|
? undefined
|
||||||
|
: this.hass!.states[key].state,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (context.device && context.device.name) {
|
||||||
|
completionItems.push({
|
||||||
|
label: this.hass!.localize("ui.components.device-picker.device"),
|
||||||
|
value: context.device.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.area && context.area.name) {
|
||||||
|
completionItems.push({
|
||||||
|
label: this.hass!.localize("ui.components.area-picker.area"),
|
||||||
|
value: context.area.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.floor && context.floor.name) {
|
||||||
|
completionItems.push({
|
||||||
|
label: this.hass!.localize("ui.components.floor-picker.floor"),
|
||||||
|
value: context.floor.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render(
|
||||||
|
html`
|
||||||
|
<ha-code-editor-completion-items
|
||||||
|
.items=${completionItems}
|
||||||
|
></ha-code-editor-completion-items>
|
||||||
|
`,
|
||||||
|
completionInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
return completionInfo;
|
||||||
|
};
|
||||||
|
|
||||||
private _getStates = memoizeOne((states: HassEntities): Completion[] => {
|
private _getStates = memoizeOne((states: HassEntities): Completion[] => {
|
||||||
if (!states) {
|
if (!states) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = Object.keys(states).map((key) => ({
|
const options = Object.keys(states).map((key) => ({
|
||||||
type: "variable",
|
type: "variable",
|
||||||
label: key,
|
label: key,
|
||||||
detail: states[key].attributes.friendly_name,
|
detail: states[key].attributes.friendly_name,
|
||||||
info: `State: ${states[key].state}`,
|
info: this._renderInfo,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
@@ -615,6 +676,20 @@ export class HaCodeEditor extends ReactiveElement {
|
|||||||
top: calc(var(--safe-area-inset-top, 0px) + 8px);
|
top: calc(var(--safe-area-inset-top, 0px) + 8px);
|
||||||
right: calc(var(--safe-area-inset-right, 0px) + 8px);
|
right: calc(var(--safe-area-inset-right, 0px) + 8px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.completion-info {
|
||||||
|
display: grid;
|
||||||
|
gap: 3px;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide completion info on narrow screens */
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.cm-completionInfo,
|
||||||
|
.completion-info {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user