Sensor Card Editor to Ha Form (#11810)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
Zack Barett 2022-02-23 14:46:52 -06:00 committed by GitHub
parent 1719d062b3
commit 684c232c8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,7 +1,8 @@
import "@material/mwc-list/mwc-list-item"; import "../../../../components/ha-form/ha-form";
import "@polymer/paper-input/paper-input"; import type { HassEntity } from "home-assistant-js-websocket";
import { CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { import {
assert, assert,
assign, assign,
@ -13,20 +14,13 @@ import {
union, union,
} from "superstruct"; } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { stopPropagation } from "../../../../common/dom/stop_propagation";
import { computeDomain } from "../../../../common/entity/compute_domain"; import { computeDomain } from "../../../../common/entity/compute_domain";
import { domainIcon } from "../../../../common/entity/domain_icon"; import { domainIcon } from "../../../../common/entity/domain_icon";
import "../../../../components/entity/ha-entity-picker"; import type { HaFormSchema } from "../../../../components/ha-form/types";
import "../../../../components/ha-formfield"; import type { HomeAssistant } from "../../../../types";
import "../../../../components/ha-icon-picker"; import type { SensorCardConfig } from "../../cards/types";
import "../../../../components/ha-select"; import type { LovelaceCardEditor } from "../../types";
import "../../../../components/ha-switch";
import { HomeAssistant } from "../../../../types";
import { SensorCardConfig } from "../../cards/types";
import "../../components/hui-theme-select-editor";
import { LovelaceCardEditor } from "../../types";
import { baseLovelaceCardConfig } from "../structs/base-card-struct"; import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { EditorTarget, EntitiesEditorEvent } from "../types";
import { configElementStyle } from "./config-elements-style"; import { configElementStyle } from "./config-elements-style";
const cardConfigStruct = assign( const cardConfigStruct = assign(
@ -43,8 +37,6 @@ const cardConfigStruct = assign(
}) })
); );
const includeDomains = ["counter", "input_number", "number", "sensor"];
@customElement("hui-sensor-card-editor") @customElement("hui-sensor-card-editor")
export class HuiSensorCardEditor export class HuiSensorCardEditor
extends LitElement extends LitElement
@ -59,201 +51,124 @@ export class HuiSensorCardEditor
this._config = config; this._config = config;
} }
get _entity(): string { private _schema = memoizeOne(
return this._config!.entity || ""; (
} entity: string,
icon: string | undefined,
get _name(): string { entityState: HassEntity
return this._config!.name || ""; ): HaFormSchema[] => [
} {
name: "entity",
get _icon(): string { selector: {
return this._config!.icon || ""; entity: { domain: ["counter", "input_number", "number", "sensor"] },
} },
},
get _graph(): string { { name: "name", selector: { text: {} } },
return this._config!.graph || "none"; {
} type: "grid",
name: "",
get _unit(): string { schema: [
return this._config!.unit || ""; {
} name: "icon",
selector: {
get _detail(): number { icon: {
return this._config!.detail ?? 1; placeholder: icon || entityState?.attributes.icon,
} fallbackPath:
!icon && !entityState?.attributes.icon && entityState
get _theme(): string { ? domainIcon(computeDomain(entity), entityState)
return this._config!.theme || ""; : undefined,
} },
},
get _hours_to_show(): number | string { },
return this._config!.hours_to_show || "24"; {
} name: "graph",
selector: {
select: {
options: [
{
value: "none",
label: "None",
},
{
value: "line",
label: "Line",
},
],
},
},
},
{ name: "unit", selector: { text: {} } },
{ name: "detail", selector: { boolean: {} } },
{ name: "theme", selector: { theme: {} } },
{
name: "hours_to_show",
selector: { number: { min: 1, mode: "box" } },
},
],
},
]
);
protected render(): TemplateResult { protected render(): TemplateResult {
if (!this.hass || !this._config) { if (!this.hass || !this._config) {
return html``; return html``;
} }
const graphs = ["line", "none"]; const entityState = this.hass.states[this._config.entity];
const entityState = this.hass.states[this._entity]; const schema = this._schema(
this._config.entity,
this._config.icon,
entityState
);
const data = {
hours_to_show: 24,
graph: "none",
...this._config,
detail: this._config!.detail === 2,
};
return html` return html`
<div class="card-config"> <ha-form
<ha-entity-picker
.label="${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.entity"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.required"
)})"
.hass=${this.hass} .hass=${this.hass}
.value=${this._entity} .data=${data}
.configValue=${"entity"} .schema=${schema}
.includeDomains=${includeDomains} .computeLabel=${this._computeLabelCallback}
@change=${this._valueChanged}
allow-custom-entity
></ha-entity-picker>
<paper-input
.label="${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.name"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.value=${this._name}
.configValue=${"name"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
></paper-input> ></ha-form>
<div class="side-by-side">
<ha-icon-picker
.label="${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.icon"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.value=${this._icon}
.placeholder=${this._icon || entityState?.attributes.icon}
.fallbackPath=${!this._icon &&
!entityState?.attributes.icon &&
entityState
? domainIcon(computeDomain(entityState.entity_id), entityState)
: undefined}
.configValue=${"icon"}
@value-changed=${this._valueChanged}
></ha-icon-picker>
<ha-select
.label="${this.hass.localize(
"ui.panel.lovelace.editor.card.sensor.graph_type"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.configValue=${"graph"}
@selected=${this._valueChanged}
@closed=${stopPropagation}
fixedMenuPosition
naturalMenuWidth
.value=${this._graph}
>
${graphs.map(
(graph) =>
html`<mwc-list-item .value=${graph}>${graph}</mwc-list-item>`
)}
</ha-select>
</div>
<div class="side-by-side">
<paper-input
.label="${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.unit"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.value=${this._unit}
.configValue=${"unit"}
@value-changed=${this._valueChanged}
></paper-input>
<ha-formfield
label=${this.hass.localize(
"ui.panel.lovelace.editor.card.sensor.show_more_detail"
)}
>
<ha-switch
.checked=${this._detail === 2}
.configValue=${"detail"}
@change=${this._change}
></ha-switch>
</ha-formfield>
</div>
<div class="side-by-side">
<hui-theme-select-editor
.hass=${this.hass}
.value=${this._theme}
.configValue=${"theme"}
@value-changed=${this._valueChanged}
></hui-theme-select-editor>
<paper-input
.label="${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.hours_to_show"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
type="number"
.value=${this._hours_to_show}
min="1"
.configValue=${"hours_to_show"}
@value-changed=${this._valueChanged}
></paper-input>
</div>
</div>
`; `;
} }
private _change(ev: Event) { private _valueChanged(ev: CustomEvent): void {
if (!this._config || !this.hass) { const config = ev.detail.value;
return; config.detail = config.detail ? 2 : 1;
fireEvent(this, "config-changed", { config });
} }
const value = (ev.target! as EditorTarget).checked ? 2 : 1; private _computeLabelCallback = (schema: HaFormSchema) => {
if (schema.name === "entity") {
if (this._detail === value) { return `${this.hass!.localize(
return; "ui.panel.lovelace.editor.card.generic.entity"
)} (${this.hass!.localize(
"ui.panel.lovelace.editor.card.config.required"
)})`;
} }
this._config = { if (schema.name === "detail") {
...this._config, return this.hass!.localize(
detail: value, "ui.panel.lovelace.editor.card.sensor.show_more_detail"
);
}
return (
this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
) ||
this.hass!.localize(`ui.panel.lovelace.editor.card.sensor.${schema.name}`)
);
}; };
fireEvent(this, "config-changed", { config: this._config });
}
private _valueChanged(ev: EntitiesEditorEvent): void {
if (!this._config || !this.hass) {
return;
}
const target = ev.target! as EditorTarget;
if (this[`_${target.configValue}`] === target.value) {
return;
}
if (target.configValue) {
if (
target.value === "" ||
(target.type === "number" && isNaN(Number(target.value)))
) {
this._config = { ...this._config };
delete this._config[target.configValue!];
} else {
let value: any = target.value;
if (target.type === "number") {
value = Number(value);
}
this._config = { ...this._config, [target.configValue!]: value };
}
}
fireEvent(this, "config-changed", { config: this._config });
}
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return configElementStyle; return configElementStyle;
} }