diff --git a/gallery/src/demos/demo-ha-alert.ts b/gallery/src/demos/demo-ha-alert.ts
index e42c00f20e..677c772127 100644
--- a/gallery/src/demos/demo-ha-alert.ts
+++ b/gallery/src/demos/demo-ha-alert.ts
@@ -107,19 +107,21 @@ export class DemoHaAlert extends LitElement {
protected render(): TemplateResult {
return html`
- ${alerts.map(
- (alert) => html`
-
- ${alert.description}
-
- `
- )}
+
+ ${alerts.map(
+ (alert) => html`
+
+ ${alert.description}
+
+ `
+ )}
+
`;
}
@@ -130,6 +132,10 @@ export class DemoHaAlert extends LitElement {
max-width: 600px;
margin: 24px auto;
}
+ ha-alert {
+ display: block;
+ margin: 24px 0;
+ }
.condition {
padding: 16px;
display: flex;
diff --git a/package.json b/package.json
index 1382092b59..3a3dfe5645 100644
--- a/package.json
+++ b/package.json
@@ -64,8 +64,8 @@
"@material/mwc-tab": "0.25.1",
"@material/mwc-tab-bar": "0.25.1",
"@material/top-app-bar": "13.0.0-canary.65125b3a6.0",
- "@mdi/js": "6.1.95",
- "@mdi/svg": "6.1.95",
+ "@mdi/js": "6.2.95",
+ "@mdi/svg": "6.2.95",
"@polymer/app-layout": "^3.1.0",
"@polymer/iron-flex-layout": "^3.0.1",
"@polymer/iron-icon": "^3.0.1",
@@ -108,7 +108,7 @@
"deep-freeze": "^0.0.1",
"fuse.js": "^6.0.0",
"google-timezones-json": "^1.0.2",
- "hls.js": "^1.0.10",
+ "hls.js": "^1.0.11",
"home-assistant-js-websocket": "^5.11.1",
"idb-keyval": "^5.1.3",
"intl-messageformat": "^9.9.1",
diff --git a/setup.py b/setup.py
index 046031c504..b860bf0595 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name="home-assistant-frontend",
- version="20211002.0",
+ version="20211004.0",
description="The Home Assistant frontend",
url="https://github.com/home-assistant/frontend",
author="The Home Assistant Authors",
diff --git a/src/components/chart/state-history-chart-timeline.ts b/src/components/chart/state-history-chart-timeline.ts
index 7fa9d4d552..6aa8c2951b 100644
--- a/src/components/chart/state-history-chart-timeline.ts
+++ b/src/components/chart/state-history-chart-timeline.ts
@@ -56,7 +56,11 @@ const getColor = (
entityState: HassEntity,
computedStyles: CSSStyleDeclaration
) => {
- if (invertOnOff(entityState)) {
+ // Inversion is only valid for "on" or "off" state
+ if (
+ (stateString === "on" || stateString === "off") &&
+ invertOnOff(entityState)
+ ) {
stateString = stateString === "on" ? "off" : "on";
}
if (stateColorMap.has(stateString)) {
diff --git a/src/components/ha-alert.ts b/src/components/ha-alert.ts
index b9468a8b92..ddd3c641e7 100644
--- a/src/components/ha-alert.ts
+++ b/src/components/ha-alert.ts
@@ -51,15 +51,11 @@ class HaAlert extends LitElement {
[this.alertType]: true,
})}"
>
-
+
-
+
${this.title ? html`
${this.title}
` : ""}
@@ -94,7 +90,7 @@ class HaAlert extends LitElement {
static styles = css`
.issue-type {
position: relative;
- padding: 4px;
+ padding: 8px;
display: flex;
margin: 4px 0;
}
@@ -113,11 +109,16 @@ class HaAlert extends LitElement {
border-radius: 4px;
}
.icon {
- margin: 4px 8px;
+ margin-right: 8px;
width: 24px;
}
- .main-content.no-title {
- margin-top: 6px;
+ .icon.no-title {
+ align-self: center;
+ }
+ .issue-type.rtl > .icon {
+ margin-right: 0px;
+ margin-left: 8px;
+ width: 24px;
}
.issue-type.rtl > .content {
flex-direction: row-reverse;
@@ -126,24 +127,22 @@ class HaAlert extends LitElement {
.content {
display: flex;
justify-content: space-between;
+ align-items: center;
width: 100%;
}
.main-content {
overflow-wrap: anywhere;
}
.title {
+ margin-top: 2px;
font-weight: bold;
- margin-top: 6px;
}
-
mwc-button {
--mdc-theme-primary: var(--primary-text-color);
}
-
- .action {
- align-self: center;
+ mwc-icon-button {
+ --mdc-icon-button-size: 36px;
}
-
.issue-type.info > .icon {
color: var(--info-color);
}
diff --git a/src/components/ha-form/ha-form-string.ts b/src/components/ha-form/ha-form-string.ts
index 82e4520bfa..98c4d13c30 100644
--- a/src/components/ha-form/ha-form-string.ts
+++ b/src/components/ha-form/ha-form-string.ts
@@ -12,6 +12,8 @@ import type {
HaFormStringSchema,
} from "./ha-form";
+const MASKED_FIELDS = ["password", "secret", "token"];
+
@customElement("ha-form-string")
export class HaFormString extends LitElement implements HaFormElement {
@property() public schema!: HaFormStringSchema;
@@ -33,7 +35,7 @@ export class HaFormString extends LitElement implements HaFormElement {
}
protected render(): TemplateResult {
- return this.schema.name.includes("password")
+ return MASKED_FIELDS.some((field) => this.schema.name.includes(field))
? html`
({
- ...statistic,
- state: this.hass.states[statistic.statistic_id],
- issues: issues[statistic.statistic_id],
- }));
+ const statsIds = new Set();
+
+ this._data = statisticIds.map((statistic) => {
+ statsIds.add(statistic.statistic_id);
+ return {
+ ...statistic,
+ state: this.hass.states[statistic.statistic_id],
+ issues: issues[statistic.statistic_id],
+ };
+ });
+
+ Object.keys(issues).forEach((statisticId) => {
+ if (!statsIds.has(statisticId)) {
+ this._data.push({
+ statistic_id: statisticId,
+ unit_of_measurement: "",
+ state: this.hass.states[statisticId],
+ issues: issues[statisticId],
+ });
+ }
+ });
}
private _fixIssue(ev) {
- const issue = ev.currentTarget.data[0] as StatisticsValidationResult;
- if (issue.type === "unsupported_unit") {
- showAlertDialog(this, {
- title: "Unsupported unit",
- text: html`The unit of your entity is not a supported unit for the
- device class of the entity, ${issue.data.device_class}.
-
Statistics can not be generated until this entity has a
- supported unit.
If this unit was provided by an
- integration, this is a bug. Please report an issue.
If you
- have set this unit yourself, and want to have statistics generated,
- make sure the unit matched the device class. The supported units are
- documented in the
-
- developer documentation.`,
- });
- return;
+ const issues = (ev.currentTarget.data as StatisticsValidationResult[]).sort(
+ (itemA, itemB) =>
+ (FIX_ISSUES_ORDER[itemA.type] ?? 99) -
+ (FIX_ISSUES_ORDER[itemB.type] ?? 99)
+ );
+ const issue = issues[0];
+ switch (issue.type) {
+ case "entity_not_recorded":
+ showAlertDialog(this, {
+ title: "Entity not recorded",
+ text: html`State changes of this entity are not recorded, therefore,
+ we can not track long term statistics for it.
You
+ probably excluded this entity, or have just included some
+ entities.
See the
+
+ recorder documentation
+ for more information.`,
+ });
+ break;
+ case "unsupported_state_class":
+ showAlertDialog(this, {
+ title: "Unsupported state class",
+ text: html`The state class of this entity, ${issue.data.state_class}
+ is not supported.
Statistics can not be generated until this
+ entity has a supported state class.
If this state class
+ was provided by an integration, this is a bug. Please report an
+ issue.
If you have set this state class yourself, please
+ correct it. The different state classes and when to use which can be
+ found in the
+
+ developer documentation.`,
+ });
+ break;
+ case "unsupported_unit_metadata":
+ showFixStatisticsUnsupportedUnitMetadataDialog(this, {
+ issue,
+ fixedCallback: () => {
+ this._validateStatistics();
+ },
+ });
+ break;
+ case "unsupported_unit_state":
+ showAlertDialog(this, {
+ title: "Unsupported unit",
+ text: html`The unit of your entity is not a supported unit for the
+ device class of the entity, ${issue.data.device_class}.
+
Statistics can not be generated until this entity has a
+ supported unit.
If this unit was provided by an
+ integration, this is a bug. Please report an issue.
If
+ you have set this unit yourself, and want to have statistics
+ generated, make sure the unit matches the device class. The
+ supported units are documented in the
+
+ developer documentation.`,
+ });
+ break;
+ case "units_changed":
+ showFixStatisticsUnitsChangedDialog(this, {
+ issue,
+ fixedCallback: () => {
+ this._validateStatistics();
+ },
+ });
+ break;
+ default:
+ showAlertDialog(this, {
+ title: "Fix issue",
+ text: "Fixing this issue is not supported yet.",
+ });
}
- if (issue.type === "units_changed") {
- showFixStatisticsUnitsChangedDialog(this, {
- issue,
- fixedCallback: () => {
- this._validateStatistics();
- },
- });
- return;
- }
- showAlertDialog(this, {
- title: "Fix issue",
- text: "Fixing this issue is not supported yet.",
- });
}
static get styles(): CSSResultGroup {
diff --git a/src/panels/developer-tools/statistics/dialog-statistics-fix-unsupported-unit-meta.ts b/src/panels/developer-tools/statistics/dialog-statistics-fix-unsupported-unit-meta.ts
new file mode 100644
index 0000000000..fd7e7ae61f
--- /dev/null
+++ b/src/panels/developer-tools/statistics/dialog-statistics-fix-unsupported-unit-meta.ts
@@ -0,0 +1,79 @@
+import "@material/mwc-button/mwc-button";
+import { LitElement, TemplateResult, html, CSSResultGroup } from "lit";
+import { customElement, property, state } from "lit/decorators";
+import "../../../components/ha-dialog";
+import { fireEvent } from "../../../common/dom/fire_event";
+import { haStyle, haStyleDialog } from "../../../resources/styles";
+import { HomeAssistant } from "../../../types";
+import { updateStatisticsMetadata } from "../../../data/history";
+import "../../../components/ha-formfield";
+import "../../../components/ha-radio";
+import { DialogStatisticsUnsupportedUnitMetaParams } from "./show-dialog-statistics-fix-unsupported-unit-meta";
+
+@customElement("dialog-statistics-fix-unsupported-unit-meta")
+export class DialogStatisticsFixUnsupportedUnitMetadata extends LitElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @state() private _params?: DialogStatisticsUnsupportedUnitMetaParams;
+
+ public showDialog(params: DialogStatisticsUnsupportedUnitMetaParams): void {
+ this._params = params;
+ }
+
+ public closeDialog(): void {
+ this._params = undefined;
+ fireEvent(this, "dialog-closed", { dialog: this.localName });
+ }
+
+ protected render(): TemplateResult | void {
+ if (!this._params) {
+ return html``;
+ }
+
+ return html`
+
+
+ The unit of the statistics in your database for this entity is not a
+ supported unit for the device class of the entity,
+ ${this._params.issue.data.device_class}. It should be
+ ${this._params.issue.data.supported_unit}.
+
+
+ Do you want to update the unit of the history statistics to
+ ${this._params.issue.data.supported_unit}?
+
+
+
+ Fix
+
+
+ ${this.hass.localize("ui.common.close")}
+
+
+ `;
+ }
+
+ private async _fixIssue(): Promise {
+ await updateStatisticsMetadata(
+ this.hass,
+ this._params!.issue.data.statistic_id,
+ this._params!.issue.data.supported_unit
+ );
+ this._params?.fixedCallback();
+ this.closeDialog();
+ }
+
+ static get styles(): CSSResultGroup {
+ return [haStyle, haStyleDialog];
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "dialog-statistics-fix-unsupported-unit-meta": DialogStatisticsFixUnsupportedUnitMetadata;
+ }
+}
diff --git a/src/panels/developer-tools/statistics/show-dialog-statistics-fix-unsupported-unit-meta.ts b/src/panels/developer-tools/statistics/show-dialog-statistics-fix-unsupported-unit-meta.ts
new file mode 100644
index 0000000000..828f3094bc
--- /dev/null
+++ b/src/panels/developer-tools/statistics/show-dialog-statistics-fix-unsupported-unit-meta.ts
@@ -0,0 +1,21 @@
+import { fireEvent } from "../../../common/dom/fire_event";
+import { StatisticsValidationResultUnsupportedUnitMetadata } from "../../../data/history";
+
+export const loadFixUnsupportedUnitMetaDialog = () =>
+ import("./dialog-statistics-fix-unsupported-unit-meta");
+
+export interface DialogStatisticsUnsupportedUnitMetaParams {
+ issue: StatisticsValidationResultUnsupportedUnitMetadata;
+ fixedCallback: () => void;
+}
+
+export const showFixStatisticsUnsupportedUnitMetadataDialog = (
+ element: HTMLElement,
+ detailParams: DialogStatisticsUnsupportedUnitMetaParams
+): void => {
+ fireEvent(element, "show-dialog", {
+ dialogTag: "dialog-statistics-fix-unsupported-unit-meta",
+ dialogImport: loadFixUnsupportedUnitMetaDialog,
+ dialogParams: detailParams,
+ });
+};
diff --git a/src/translations/en.json b/src/translations/en.json
index 237d1a460f..9757d2ffa5 100755
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -3728,7 +3728,10 @@
"issue": "Issue",
"issues": {
"units_changed": "The unit of this entity changed from ''{metadata_unit}'' to ''{state_unit}''.",
- "unsupported_unit": "The unit (''{state_unit}'') of this entity doesn't match a unit of device class ''{device_class}''."
+ "unsupported_unit_state": "The unit (''{state_unit}'') of this entity doesn't match a unit of device class ''{device_class}''.",
+ "unsupported_unit_metadata": "The unit (''{state_unit}'') of the recorded statistics doesn't match a unit of device class ''{device_class}''.",
+ "unsupported_state_class": "The state class ''{state_class}'' of this entity is not supported.",
+ "entity_not_recorded": "This entity is excluded from being recorded."
},
"fix_issue": {
"units_changed": {
diff --git a/yarn.lock b/yarn.lock
index d8a7d889ed..9292abb467 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2783,17 +2783,17 @@ __metadata:
languageName: node
linkType: hard
-"@mdi/js@npm:6.1.95":
- version: 6.1.95
- resolution: "@mdi/js@npm:6.1.95"
- checksum: 318899617da78956ae1e0650b83be65aa459f7fdb9f45212fe081776016e3b9881d1cf03458f65a5d86a99c3387caad0d87828808bca87e21db7e69706337016
+"@mdi/js@npm:6.2.95":
+ version: 6.2.95
+ resolution: "@mdi/js@npm:6.2.95"
+ checksum: 85f33d0bbb0665ef048dbcae8759eb7b17db35594f1e471c71946fb36ea8416d3c21b3a1013bb587c7293f2c84d97af6ed791a6904625abdae7ec96a75569e5e
languageName: node
linkType: hard
-"@mdi/svg@npm:6.1.95":
- version: 6.1.95
- resolution: "@mdi/svg@npm:6.1.95"
- checksum: 55e522e1758509f9a293600b0fdd6fd874aaefe8c4a404391fe11c178b24afd7a37601775af846776ac60899c03d74e39a5e061615bc65918bef8679b3dea968
+"@mdi/svg@npm:6.2.95":
+ version: 6.2.95
+ resolution: "@mdi/svg@npm:6.2.95"
+ checksum: c2f14e8b62ae4c31da84af44d13f02b050c9a7759e20f08c9088996b2cafea5ff372c89795d57e976d8a693034964dad8f65bc75eea02834d1d8784e2e22627e
languageName: node
linkType: hard
@@ -8915,10 +8915,10 @@ fsevents@^1.2.7:
languageName: node
linkType: hard
-"hls.js@npm:^1.0.10":
- version: 1.0.10
- resolution: "hls.js@npm:1.0.10"
- checksum: 56fb2729a55a68a384e3fbba4a6146702533896ac467d556afeefa12c315d64d68c2a21673d345ebacf392172ad7e8429f597a12ed90d2506b77a3093d05e596
+"hls.js@npm:^1.0.11":
+ version: 1.0.11
+ resolution: "hls.js@npm:1.0.11"
+ checksum: 0375871cf8ffef3374f44284028d235bb122dc5ee2a36b765124e8caca1ec97ba96738ef8de261fbdecf78669e7bf3fb8aee1070f239c7791add44fad50df180
languageName: node
linkType: hard
@@ -8982,8 +8982,8 @@ fsevents@^1.2.7:
"@material/mwc-tab": 0.25.1
"@material/mwc-tab-bar": 0.25.1
"@material/top-app-bar": 13.0.0-canary.65125b3a6.0
- "@mdi/js": 6.1.95
- "@mdi/svg": 6.1.95
+ "@mdi/js": 6.2.95
+ "@mdi/svg": 6.2.95
"@open-wc/dev-server-hmr": ^0.0.2
"@polymer/app-layout": ^3.1.0
"@polymer/iron-flex-layout": ^3.0.1
@@ -9067,7 +9067,7 @@ fsevents@^1.2.7:
gulp-merge-json: ^1.3.1
gulp-rename: ^2.0.0
gulp-zopfli-green: ^3.0.1
- hls.js: ^1.0.10
+ hls.js: ^1.0.11
home-assistant-js-websocket: ^5.11.1
html-minifier: ^4.0.0
husky: ^1.3.1