diff --git a/src/components/entity/ha-entity-attribute-picker.ts b/src/components/entity/ha-entity-attribute-picker.ts index e9c3b52e0f..5b1dbfc080 100644 --- a/src/components/entity/ha-entity-attribute-picker.ts +++ b/src/components/entity/ha-entity-attribute-picker.ts @@ -19,6 +19,7 @@ import { PolymerChangedEvent } from "../../polymer-types"; import { HomeAssistant } from "../../types"; import "../ha-svg-icon"; import "./state-badge"; +import { formatAttributeName } from "../../util/hass-attributes-util"; import "@material/mwc-icon-button/mwc-icon-button"; export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean; @@ -35,7 +36,9 @@ const rowRenderer = (root: HTMLElement, _owner, model: { item: string }) => { `; } - root.querySelector("paper-item")!.textContent = model.item; + root.querySelector("paper-item")!.textContent = formatAttributeName( + model.item + ); }; @customElement("ha-entity-attribute-picker") @@ -92,7 +95,7 @@ class HaEntityAttributePicker extends LitElement { this.hass.localize( "ui.components.entity.entity-attribute-picker.attribute" )} - .value=${this._value} + .value=${this._value ? formatAttributeName(this._value) : ""} .disabled=${this.disabled || !this.entityId} class="input" autocapitalize="none" @@ -140,7 +143,7 @@ class HaEntityAttributePicker extends LitElement { } private get _value() { - return this.value || ""; + return this.value; } private _openedChanged(ev: PolymerChangedEvent) { diff --git a/src/components/ha-attributes.ts b/src/components/ha-attributes.ts index 7f3966bc26..f51d006072 100644 --- a/src/components/ha-attributes.ts +++ b/src/components/ha-attributes.ts @@ -9,7 +9,9 @@ import { TemplateResult, } from "lit-element"; import { until } from "lit-html/directives/until"; -import hassAttributeUtil from "../util/hass-attributes-util"; +import hassAttributeUtil, { + formatAttributeName, +} from "../util/hass-attributes-util"; let jsYamlPromise: Promise; @@ -34,7 +36,7 @@ class HaAttributes extends LitElement { (attribute) => html`
- ${attribute.replace(/_/g, " ").replace(/\bid\b/g, "ID")} + ${formatAttributeName(attribute)}
${this.formatAttribute(attribute)} @@ -61,12 +63,12 @@ class HaAttributes extends LitElement { justify-content: space-between; } .data-entry .value { - max-width: 200px; + max-width: 50%; overflow-wrap: break-word; text-align: right; } - .key:first-letter { - text-transform: capitalize; + .key { + flex-grow: 1; } .attribution { color: var(--secondary-text-color); diff --git a/src/components/ha-climate-state.ts b/src/components/ha-climate-state.ts index 39ece5ee43..1aa49ae6b2 100644 --- a/src/components/ha-climate-state.ts +++ b/src/components/ha-climate-state.ts @@ -63,7 +63,7 @@ class HaClimateState extends LitElement { private _computeTarget(): string { if (!this.hass || !this.stateObj) { - return ""; + return ""; } if ( diff --git a/src/dialogs/more-info/controls/more-info-sun.ts b/src/dialogs/more-info/controls/more-info-sun.ts index a611e521cf..b92de7e261 100644 --- a/src/dialogs/more-info/controls/more-info-sun.ts +++ b/src/dialogs/more-info/controls/more-info-sun.ts @@ -72,6 +72,12 @@ class MoreInfoSun extends LitElement { flex-direction: row; justify-content: space-between; } + ha-relative-time { + display: inline-block; + } + ha-relative-time::first-letter { + text-transform: lowercase; + } `; } } diff --git a/src/panels/config/customize/types/ha-customize-icon.js b/src/panels/config/customize/types/ha-customize-icon.js index 87ff4d7457..86b32ed5bb 100644 --- a/src/panels/config/customize/types/ha-customize-icon.js +++ b/src/panels/config/customize/types/ha-customize-icon.js @@ -21,7 +21,7 @@ class HaCustomizeIcon extends PolymerElement { diff --git a/src/panels/config/customize/types/ha-customize-string.js b/src/panels/config/customize/types/ha-customize-string.js index 71b142a5a1..72fb4a685c 100644 --- a/src/panels/config/customize/types/ha-customize-string.js +++ b/src/panels/config/customize/types/ha-customize-string.js @@ -2,6 +2,7 @@ import "@polymer/paper-input/paper-input"; import { html } from "@polymer/polymer/lib/utils/html-tag"; /* eslint-plugin-disable lit */ import { PolymerElement } from "@polymer/polymer/polymer-element"; +import { formatAttributeName } from "../../../../util/hass-attributes-util"; class HaCustomizeString extends PolymerElement { static get template() { @@ -25,7 +26,10 @@ class HaCustomizeString extends PolymerElement { } getLabel(item) { - return item.description + (item.type === "json" ? " (JSON formatted)" : ""); + return ( + formatAttributeName(item.description) + + (item.type === "json" ? " (JSON formatted)" : "") + ); } } customElements.define("ha-customize-string", HaCustomizeString); diff --git a/src/translations/en.json b/src/translations/en.json index c6d3edb73c..062751aac7 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -528,7 +528,6 @@ "history": "History", "last_changed": "Last changed", "last_updated": "Last updated", - "last_changed": "Last changed", "script": { "last_action": "Last Action", "last_triggered": "Last Triggered" diff --git a/src/util/hass-attributes-util.js b/src/util/hass-attributes-util.js deleted file mode 100644 index dd1d78c8ae..0000000000 --- a/src/util/hass-attributes-util.js +++ /dev/null @@ -1,115 +0,0 @@ -const hassAttributeUtil = {}; - -hassAttributeUtil.DOMAIN_DEVICE_CLASS = { - binary_sensor: [ - "battery", - "cold", - "connectivity", - "door", - "garage_door", - "gas", - "heat", - "light", - "lock", - "moisture", - "motion", - "moving", - "occupancy", - "opening", - "plug", - "power", - "presence", - "problem", - "safety", - "smoke", - "sound", - "vibration", - "window", - ], - cover: [ - "awning", - "blind", - "curtain", - "damper", - "door", - "garage", - "shade", - "shutter", - "window", - ], - humidifier: ["dehumidifier", "humidifier"], - sensor: [ - "battery", - "humidity", - "illuminance", - "temperature", - "pressure", - "power", - "signal_strength", - "timestamp", - ], - switch: ["switch", "outlet"], -}; - -hassAttributeUtil.UNKNOWN_TYPE = "json"; -hassAttributeUtil.ADD_TYPE = "key-value"; - -hassAttributeUtil.TYPE_TO_TAG = { - string: "ha-customize-string", - json: "ha-customize-string", - icon: "ha-customize-icon", - boolean: "ha-customize-boolean", - array: "ha-customize-array", - "key-value": "ha-customize-key-value", -}; - -// Attributes here serve dual purpose: -// 1) Any key of this object won't be shown in more-info window. -// 2) Any key which has value other than undefined will appear in customization -// config according to its value. -hassAttributeUtil.LOGIC_STATE_ATTRIBUTES = hassAttributeUtil.LOGIC_STATE_ATTRIBUTES || { - entity_picture: undefined, - friendly_name: { type: "string", description: "Name" }, - icon: { type: "icon" }, - emulated_hue: { - type: "boolean", - domains: ["emulated_hue"], - }, - emulated_hue_name: { - type: "string", - domains: ["emulated_hue"], - }, - haaska_hidden: undefined, - haaska_name: undefined, - supported_features: undefined, - attribution: undefined, - restored: undefined, - custom_ui_more_info: { type: "string" }, - custom_ui_state_card: { type: "string" }, - device_class: { - type: "array", - options: hassAttributeUtil.DOMAIN_DEVICE_CLASS, - description: "Device class", - domains: ["binary_sensor", "cover", "humidifier", "sensor", "switch"], - }, - assumed_state: { - type: "boolean", - domains: [ - "switch", - "light", - "cover", - "climate", - "fan", - "humidifier", - "group", - "water_heater", - ], - }, - initial_state: { - type: "string", - domains: ["automation"], - }, - unit_of_measurement: { type: "string" }, -}; - -export default hassAttributeUtil; diff --git a/src/util/hass-attributes-util.ts b/src/util/hass-attributes-util.ts new file mode 100644 index 0000000000..51efbbe295 --- /dev/null +++ b/src/util/hass-attributes-util.ts @@ -0,0 +1,120 @@ +const hassAttributeUtil = { + DOMAIN_DEVICE_CLASS: { + binary_sensor: [ + "battery", + "cold", + "connectivity", + "door", + "garage_door", + "gas", + "heat", + "light", + "lock", + "moisture", + "motion", + "moving", + "occupancy", + "opening", + "plug", + "power", + "presence", + "problem", + "safety", + "smoke", + "sound", + "vibration", + "window", + ], + cover: [ + "awning", + "blind", + "curtain", + "damper", + "door", + "garage", + "shade", + "shutter", + "window", + ], + humidifier: ["dehumidifier", "humidifier"], + sensor: [ + "battery", + "humidity", + "illuminance", + "temperature", + "pressure", + "power", + "signal_strength", + "timestamp", + ], + switch: ["switch", "outlet"], + }, + UNKNOWN_TYPE: "json", + ADD_TYPE: "key-value", + TYPE_TO_TAG: { + string: "ha-customize-string", + json: "ha-customize-string", + icon: "ha-customize-icon", + boolean: "ha-customize-boolean", + array: "ha-customize-array", + "key-value": "ha-customize-key-value", + }, + LOGIC_STATE_ATTRIBUTES: {}, +}; + +// Attributes here serve dual purpose: +// 1) Any key of this object won't be shown in more-info window. +// 2) Any key which has value other than undefined will appear in customization +// config according to its value. +hassAttributeUtil.LOGIC_STATE_ATTRIBUTES = { + entity_picture: undefined, + friendly_name: { type: "string", description: "Name" }, + icon: { type: "icon" }, + emulated_hue: { + type: "boolean", + domains: ["emulated_hue"], + }, + emulated_hue_name: { + type: "string", + domains: ["emulated_hue"], + }, + haaska_hidden: undefined, + haaska_name: undefined, + supported_features: undefined, + attribution: undefined, + restored: undefined, + custom_ui_more_info: { type: "string" }, + custom_ui_state_card: { type: "string" }, + device_class: { + type: "array", + options: hassAttributeUtil.DOMAIN_DEVICE_CLASS, + description: "Device class", + domains: ["binary_sensor", "cover", "humidifier", "sensor", "switch"], + }, + assumed_state: { + type: "boolean", + domains: [ + "switch", + "light", + "cover", + "climate", + "fan", + "humidifier", + "group", + "water_heater", + ], + }, + initial_state: { + type: "string", + domains: ["automation"], + }, + unit_of_measurement: { type: "string" }, +}; + +export default hassAttributeUtil; + +// Convert from internal snake_case format to user-friendly format +export function formatAttributeName(value: string): string { + value = value.replace(/_/g, " ").replace(/\bid\b/g, "ID"); + return value.charAt(0).toUpperCase() + value.slice(1); +}