- ${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);
+}