+ ${this.hass.localize( + "ui.dialogs.more_info_control.restored.not_provided" + )} +
++ ${this.hass.localize( + "ui.dialogs.more_info_control.restored.remove_intro" + )} +
[[localize('ui.panel.config.cloud.forgot_password.instructions')]]
diff --git a/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts b/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts
index 84e3c77d1c..bdf23ec5f5 100644
--- a/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts
+++ b/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts
@@ -6,6 +6,7 @@ import {
html,
LitElement,
property,
+ internalProperty,
TemplateResult,
} from "lit-element";
import memoizeOne from "memoize-one";
@@ -50,13 +51,13 @@ const configIsExposed = (config: GoogleEntityConfig) =>
@customElement("cloud-google-assistant")
class CloudGoogleAssistant extends LitElement {
- @property() public hass!: HomeAssistant;
+ @property({ attribute: false }) public hass!: HomeAssistant;
@property() public cloudStatus!: CloudStatusLoggedIn;
@property() public narrow!: boolean;
- @property() private _entities?: GoogleEntity[];
+ @internalProperty() private _entities?: GoogleEntity[];
@property()
private _entityConfigs: CloudPreferences["google_entity_configs"] = {};
@@ -361,7 +362,7 @@ class CloudGoogleAssistant extends LitElement {
color: var(--primary-text-color);
background-color: var(
--ha-card-background,
- var(--paper-card-background-color, white)
+ var(--card-background-color, white)
);
padding: 16px 8px;
text-align: center;
diff --git a/src/panels/config/cloud/ha-config-cloud.ts b/src/panels/config/cloud/ha-config-cloud.ts
index 93d4bef9fd..333eaff674 100644
--- a/src/panels/config/cloud/ha-config-cloud.ts
+++ b/src/panels/config/cloud/ha-config-cloud.ts
@@ -1,5 +1,5 @@
import { PolymerElement } from "@polymer/polymer";
-import { customElement, property } from "lit-element";
+import { customElement, property, internalProperty } from "lit-element";
import { navigate } from "../../../common/navigate";
import { CloudStatus } from "../../../data/cloud";
import {
@@ -16,7 +16,7 @@ const NOT_LOGGED_IN_URLS = ["login", "register", "forgot-password"];
@customElement("ha-config-cloud")
class HaConfigCloud extends HassRouterPage {
- @property() public hass!: HomeAssistant;
+ @property({ attribute: false }) public hass!: HomeAssistant;
@property() public isWide!: boolean;
@@ -77,9 +77,9 @@ class HaConfigCloud extends HassRouterPage {
},
};
- @property() private _flashMessage = "";
+ @internalProperty() private _flashMessage = "";
- @property() private _loginEmail = "";
+ @internalProperty() private _loginEmail = "";
private _resolveCloudStatusLoaded!: () => void;
diff --git a/src/panels/config/core/ha-config-core-form.ts b/src/panels/config/core/ha-config-core-form.ts
index 57dc3327d9..e4b302b139 100644
--- a/src/panels/config/core/ha-config-core-form.ts
+++ b/src/panels/config/core/ha-config-core-form.ts
@@ -10,6 +10,7 @@ import {
html,
LitElement,
property,
+ internalProperty,
TemplateResult,
} from "lit-element";
import { UNIT_C } from "../../../common/const";
@@ -22,17 +23,17 @@ import type { HomeAssistant } from "../../../types";
@customElement("ha-config-core-form")
class ConfigCoreForm extends LitElement {
- @property() public hass!: HomeAssistant;
+ @property({ attribute: false }) public hass!: HomeAssistant;
- @property() private _working = false;
+ @internalProperty() private _working = false;
- @property() private _location!: [number, number];
+ @internalProperty() private _location!: [number, number];
- @property() private _elevation!: string;
+ @internalProperty() private _elevation!: string;
- @property() private _unitSystem!: ConfigUpdateValues["unit_system"];
+ @internalProperty() private _unitSystem!: ConfigUpdateValues["unit_system"];
- @property() private _timeZone!: string;
+ @internalProperty() private _timeZone!: string;
protected render(): TemplateResult {
const canEdit = ["storage", "default"].includes(
diff --git a/src/panels/config/core/ha-config-name-form.ts b/src/panels/config/core/ha-config-name-form.ts
index 6543546c67..d8315c6104 100644
--- a/src/panels/config/core/ha-config-name-form.ts
+++ b/src/panels/config/core/ha-config-name-form.ts
@@ -8,6 +8,7 @@ import {
html,
LitElement,
property,
+ internalProperty,
TemplateResult,
} from "lit-element";
import "../../../components/ha-card";
@@ -17,11 +18,11 @@ import type { HomeAssistant } from "../../../types";
@customElement("ha-config-name-form")
class ConfigNameForm extends LitElement {
- @property() public hass!: HomeAssistant;
+ @property({ attribute: false }) public hass!: HomeAssistant;
- @property() private _working = false;
+ @internalProperty() private _working = false;
- @property() private _name!: ConfigUpdateValues["location_name"];
+ @internalProperty() private _name!: ConfigUpdateValues["location_name"];
protected render(): TemplateResult {
const canEdit = ["storage", "default"].includes(
diff --git a/src/panels/config/core/ha-config-url-form.ts b/src/panels/config/core/ha-config-url-form.ts
index 216cd7b947..e63b256e0c 100644
--- a/src/panels/config/core/ha-config-url-form.ts
+++ b/src/panels/config/core/ha-config-url-form.ts
@@ -8,6 +8,7 @@ import {
html,
LitElement,
property,
+ internalProperty,
TemplateResult,
} from "lit-element";
import "../../../components/ha-card";
@@ -17,15 +18,15 @@ import type { HomeAssistant } from "../../../types";
@customElement("ha-config-url-form")
class ConfigUrlForm extends LitElement {
- @property() public hass!: HomeAssistant;
+ @property({ attribute: false }) public hass!: HomeAssistant;
- @property() private _error?: string;
+ @internalProperty() private _error?: string;
- @property() private _working = false;
+ @internalProperty() private _working = false;
- @property() private _external_url?: string;
+ @internalProperty() private _external_url?: string;
- @property() private _internal_url?: string;
+ @internalProperty() private _internal_url?: string;
protected render(): TemplateResult {
const canEdit = ["storage", "default"].includes(
diff --git a/src/panels/config/dashboard/ha-config-dashboard.ts b/src/panels/config/dashboard/ha-config-dashboard.ts
index 9fdb8add69..33b419c6d5 100644
--- a/src/panels/config/dashboard/ha-config-dashboard.ts
+++ b/src/panels/config/dashboard/ha-config-dashboard.ts
@@ -24,7 +24,7 @@ import { mdiCloudLock } from "@mdi/js";
@customElement("ha-config-dashboard")
class HaConfigDashboard extends LitElement {
- @property() public hass!: HomeAssistant;
+ @property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean, reflect: true })
public narrow!: boolean;
diff --git a/src/panels/config/dashboard/ha-config-navigation.ts b/src/panels/config/dashboard/ha-config-navigation.ts
index 74c5afcfed..b5ce582e20 100644
--- a/src/panels/config/dashboard/ha-config-navigation.ts
+++ b/src/panels/config/dashboard/ha-config-navigation.ts
@@ -18,7 +18,7 @@ import { HomeAssistant } from "../../../types";
@customElement("ha-config-navigation")
class HaConfigNavigation extends LitElement {
- @property() public hass!: HomeAssistant;
+ @property({ attribute: false }) public hass!: HomeAssistant;
@property() public showAdvanced!: boolean;
diff --git a/src/panels/config/devices/device-detail/ha-device-automation-card.ts b/src/panels/config/devices/device-detail/ha-device-automation-card.ts
index 3549a9b9b8..ba0a8b7d5a 100644
--- a/src/panels/config/devices/device-detail/ha-device-automation-card.ts
+++ b/src/panels/config/devices/device-detail/ha-device-automation-card.ts
@@ -16,7 +16,7 @@ import { HomeAssistant } from "../../../../types";
export abstract class HaDeviceAutomationCard<
T extends DeviceAutomation
> extends LitElement {
- @property() public hass!: HomeAssistant;
+ @property({ attribute: false }) public hass!: HomeAssistant;
@property() public deviceId?: string;
diff --git a/src/panels/config/devices/device-detail/ha-device-automation-dialog.ts b/src/panels/config/devices/device-detail/ha-device-automation-dialog.ts
index 28a59b03c4..a7a9b2a661 100644
--- a/src/panels/config/devices/device-detail/ha-device-automation-dialog.ts
+++ b/src/panels/config/devices/device-detail/ha-device-automation-dialog.ts
@@ -4,6 +4,7 @@ import {
html,
LitElement,
property,
+ internalProperty,
TemplateResult,
} from "lit-element";
import "../../../../components/ha-dialog";
@@ -24,15 +25,15 @@ import { DeviceAutomationDialogParams } from "./show-dialog-device-automation";
@customElement("dialog-device-automation")
export class DialogDeviceAutomation extends LitElement {
- @property() public hass!: HomeAssistant;
+ @property({ attribute: false }) public hass!: HomeAssistant;
- @property() private _triggers: DeviceTrigger[] = [];
+ @internalProperty() private _triggers: DeviceTrigger[] = [];
- @property() private _conditions: DeviceCondition[] = [];
+ @internalProperty() private _conditions: DeviceCondition[] = [];
- @property() private _actions: DeviceAction[] = [];
+ @internalProperty() private _actions: DeviceAction[] = [];
- @property() private _params?: DeviceAutomationDialogParams;
+ @internalProperty() private _params?: DeviceAutomationDialogParams;
public async showDialog(params: DeviceAutomationDialogParams): Promise
${this.hass.localize(
"ui.panel.config.script.editor.modes.description",
@@ -284,6 +313,30 @@ export class HaScriptEditor extends LitElement {
this._dirty = true;
}
+ private _aliasChanged(ev: CustomEvent) {
+ if (this.scriptEntityId || this._entityId) {
+ return;
+ }
+ const aliasSlugify = slugify((ev.target as any).value, "_");
+ let id = aliasSlugify;
+ let i = 2;
+ while (this.hass.states[`script.${id}`]) {
+ id = `${aliasSlugify}_${i}`;
+ i++;
+ }
+ this._entityId = id;
+ }
+
+ private _idChanged(ev: CustomEvent) {
+ ev.stopPropagation();
+ this._entityId = (ev.target as any).value;
+ if (this.hass.states[`script.${this._entityId}`]) {
+ this._idError = true;
+ } else {
+ this._idError = false;
+ }
+ }
+
private _valueChanged(ev: CustomEvent) {
ev.stopPropagation();
const target = ev.target as any;
@@ -338,9 +391,15 @@ export class HaScriptEditor extends LitElement {
}
private _saveScript(): void {
+ if (this._idError) {
+ this._errors = this.hass.localize(
+ "ui.panel.config.script.editor.id_already_exists_save_error"
+ );
+ return;
+ }
const id = this.scriptEntityId
? computeObjectId(this.scriptEntityId)
- : Date.now();
+ : this._entityId || Date.now();
this.hass!.callApi("POST", "config/script/config/" + id, this._config).then(
() => {
this._dirty = false;
diff --git a/src/panels/config/script/ha-script-picker.ts b/src/panels/config/script/ha-script-picker.ts
index 8fba4004ba..ccfad94f8e 100644
--- a/src/panels/config/script/ha-script-picker.ts
+++ b/src/panels/config/script/ha-script-picker.ts
@@ -25,10 +25,11 @@ import { showToast } from "../../../util/toast";
import { configSections } from "../ha-panel-config";
import "../../../components/ha-svg-icon";
import { mdiPlus } from "@mdi/js";
+import { stateIcon } from "../../../common/entity/state_icon";
@customElement("ha-script-picker")
class HaScriptPicker extends LitElement {
- @property() public hass!: HomeAssistant;
+ @property({ attribute: false }) public hass!: HomeAssistant;
@property() public scripts!: HassEntity[];
@@ -43,6 +44,7 @@ class HaScriptPicker extends LitElement {
return {
...script,
name: computeStateName(script),
+ icon: stateIcon(script),
};
});
});
@@ -65,6 +67,11 @@ class HaScriptPicker extends LitElement {
>
`,
},
+ icon: {
+ title: "",
+ type: "icon",
+ template: (icon) => html` [[_description]]
+ [[_description]]
+
@@ -227,6 +242,10 @@ class HaPanelDevService extends LocalizeMixin(PolymerElement) {
type: String,
computed: "_computeDescription(hass, _domain, _service)",
},
+ rtl: {
+ reflectToAttribute: true,
+ computed: "_computeRTL(hass)",
+ },
};
}
@@ -329,6 +348,10 @@ class HaPanelDevService extends LocalizeMixin(PolymerElement) {
_yamlChanged(ev) {
this.serviceData = ev.detail.value;
}
+
+ _computeRTL(hass) {
+ return computeRTL(hass);
+ }
}
customElements.define("developer-tools-service", HaPanelDevService);
diff --git a/src/panels/developer-tools/state/developer-tools-state.js b/src/panels/developer-tools/state/developer-tools-state.js
index c1199baebc..7c4dbf8933 100644
--- a/src/panels/developer-tools/state/developer-tools-state.js
+++ b/src/panels/developer-tools/state/developer-tools-state.js
@@ -13,6 +13,7 @@ import { EventsMixin } from "../../../mixins/events-mixin";
import LocalizeMixin from "../../../mixins/localize-mixin";
import "../../../styles/polymer-ha-style";
import { mdiInformationOutline } from "@mdi/js";
+import { computeRTL } from "../../../common/util/compute_rtl";
const ERROR_SENTINEL = {};
/*
@@ -29,7 +30,6 @@ class HaPanelDevState extends EventsMixin(LocalizeMixin(PolymerElement)) {
-moz-user-select: initial;
display: block;
padding: 16px;
- direction: ltr;
}
.inputs {
@@ -44,8 +44,13 @@ class HaPanelDevState extends EventsMixin(LocalizeMixin(PolymerElement)) {
text-align: left;
}
+ :host([rtl]) .entities th {
+ text-align: right;
+ }
+
.entities tr {
vertical-align: top;
+ direction: ltr;
}
.entities tr:nth-child(odd) {
@@ -232,6 +237,10 @@ class HaPanelDevState extends EventsMixin(LocalizeMixin(PolymerElement)) {
computed:
"computeEntities(hass, _entityFilter, _stateFilter, _attributeFilter)",
},
+ rtl: {
+ reflectToAttribute: true,
+ computed: "_computeRTL(hass)",
+ },
};
}
@@ -396,6 +405,10 @@ class HaPanelDevState extends EventsMixin(LocalizeMixin(PolymerElement)) {
_yamlChanged(ev) {
this._stateAttributes = ev.detail.value;
}
+
+ _computeRTL(hass) {
+ return computeRTL(hass);
+ }
}
customElements.define("developer-tools-state", HaPanelDevState);
diff --git a/src/panels/history/ha-panel-history.ts b/src/panels/history/ha-panel-history.ts
index 21e43a2aa7..08fabe00bf 100644
--- a/src/panels/history/ha-panel-history.ts
+++ b/src/panels/history/ha-panel-history.ts
@@ -4,7 +4,13 @@ import "@polymer/app-layout/app-toolbar/app-toolbar";
import { computeRTL } from "../../common/util/compute_rtl";
import "../../components/ha-menu-button";
import "../../components/state-history-charts";
-import { LitElement, css, property, PropertyValues } from "lit-element";
+import {
+ LitElement,
+ css,
+ property,
+ internalProperty,
+ PropertyValues,
+} from "lit-element";
import { html } from "lit-html";
import { haStyle } from "../../resources/styles";
import { HomeAssistant } from "../../types";
@@ -30,7 +36,7 @@ class HaPanelHistory extends LitElement {
@property({ reflect: true, type: Boolean }) rtl = false;
- @property() private _ranges?: DateRangePickerRanges;
+ @internalProperty() private _ranges?: DateRangePickerRanges;
public constructor() {
super();
diff --git a/src/panels/logbook/ha-logbook.ts b/src/panels/logbook/ha-logbook.ts
index 1cce036af0..8b6d8bc36a 100644
--- a/src/panels/logbook/ha-logbook.ts
+++ b/src/panels/logbook/ha-logbook.ts
@@ -21,7 +21,7 @@ import { HomeAssistant } from "../../types";
import { restoreScroll } from "../../common/decorators/restore-scroll";
class HaLogbook extends LitElement {
- @property() public hass!: HomeAssistant;
+ @property({ attribute: false }) public hass!: HomeAssistant;
@property() public userIdToName = {};
diff --git a/src/panels/logbook/ha-panel-logbook.ts b/src/panels/logbook/ha-panel-logbook.ts
index 8a0cf68b1f..36e0823fa5 100644
--- a/src/panels/logbook/ha-panel-logbook.ts
+++ b/src/panels/logbook/ha-panel-logbook.ts
@@ -10,6 +10,7 @@ import "./ha-logbook";
import {
LitElement,
property,
+ internalProperty,
customElement,
html,
css,
@@ -49,7 +50,7 @@ export class HaPanelLogbook extends LitElement {
@property({ reflect: true, type: Boolean }) rtl = false;
- @property() private _ranges?: DateRangePickerRanges;
+ @internalProperty() private _ranges?: DateRangePickerRanges;
private _fetchUserDone?: Promise