diff --git a/src/components/buttons/ha-call-api-button.js b/src/components/buttons/ha-call-api-button.js deleted file mode 100644 index ba090cc9fd..0000000000 --- a/src/components/buttons/ha-call-api-button.js +++ /dev/null @@ -1,65 +0,0 @@ -import { html, LitElement } from "lit-element"; -import { fireEvent } from "../../common/dom/fire_event"; -import "./ha-progress-button"; - -class HaCallApiButton extends LitElement { - render() { - return html` - - `; - } - - constructor() { - super(); - this.method = "POST"; - this.data = {}; - this.disabled = false; - this.progress = false; - } - - static get properties() { - return { - hass: {}, - progress: Boolean, - path: String, - method: String, - data: {}, - disabled: Boolean, - }; - } - - get progressButton() { - return this.renderRoot.querySelector("ha-progress-button"); - } - - async _buttonTapped() { - this.progress = true; - const eventData = { - method: this.method, - path: this.path, - data: this.data, - }; - - try { - const resp = await this.hass.callApi(this.method, this.path, this.data); - this.progress = false; - this.progressButton.actionSuccess(); - eventData.success = true; - eventData.response = resp; - } catch (err) { - this.progress = false; - this.progressButton.actionError(); - eventData.success = false; - eventData.response = err; - } - - fireEvent(this, "hass-api-called", eventData); - } -} - -customElements.define("ha-call-api-button", HaCallApiButton); diff --git a/src/components/buttons/ha-call-api-button.ts b/src/components/buttons/ha-call-api-button.ts new file mode 100644 index 0000000000..ab5d075373 --- /dev/null +++ b/src/components/buttons/ha-call-api-button.ts @@ -0,0 +1,77 @@ +import { css, CSSResult, html, LitElement, property, query } from "lit-element"; +import { fireEvent } from "../../common/dom/fire_event"; +import { HomeAssistant } from "../../types"; +import "./ha-progress-button"; + +class HaCallApiButton extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property() public method: "POST" | "GET" | "PUT" | "DELETE" = "POST"; + + @property() public data = {}; + + @property({ type: Boolean, reflect: true }) public disabled = false; + + @property({ type: Boolean }) public progress = false; + + @property() public path?: string; + + @query("ha-progress-button", true) private _progressButton; + + render() { + return html` + + `; + } + + async _buttonTapped() { + this.progress = true; + const eventData: { + method: string; + path: string; + data: any; + success?: boolean; + response?: any; + } = { + method: this.method, + path: this.path!, + data: this.data, + }; + + try { + const resp = await this.hass.callApi(this.method, this.path!, this.data); + this.progress = false; + this._progressButton.actionSuccess(); + eventData.success = true; + eventData.response = resp; + } catch (err) { + this.progress = false; + this._progressButton.actionError(); + eventData.success = false; + eventData.response = err; + } + + fireEvent(this, "hass-api-called", eventData as any); + } + + static get styles(): CSSResult { + return css` + :host([disabled]) { + pointer-events: none; + } + `; + } +} + +customElements.define("ha-call-api-button", HaCallApiButton); + +declare global { + interface HTMLElementTagNameMap { + "ha-call-api-button": HaCallApiButton; + } +} diff --git a/src/data/cloud.ts b/src/data/cloud.ts index 3aa285be0d..f153ea2041 100644 --- a/src/data/cloud.ts +++ b/src/data/cloud.ts @@ -46,6 +46,7 @@ export interface CloudPreferences { export type CloudStatusLoggedIn = CloudStatusBase & { email: string; + google_registered: boolean; google_entities: EntityFilter; google_domains: string[]; alexa_entities: EntityFilter; diff --git a/src/panels/config/cloud/account/cloud-alexa-pref.ts b/src/panels/config/cloud/account/cloud-alexa-pref.ts index 04b693fab9..8d6c190d7d 100644 --- a/src/panels/config/cloud/account/cloud-alexa-pref.ts +++ b/src/panels/config/cloud/account/cloud-alexa-pref.ts @@ -169,7 +169,7 @@ export class CloudAlexaPref extends LitElement { .switch { position: absolute; right: 24px; - top: 32px; + top: 24px; } :host([dir="rtl"]) .switch { right: auto; diff --git a/src/panels/config/cloud/account/cloud-google-pref.ts b/src/panels/config/cloud/account/cloud-google-pref.ts index 1d47bc2ddc..7fc8a82047 100644 --- a/src/panels/config/cloud/account/cloud-google-pref.ts +++ b/src/panels/config/cloud/account/cloud-google-pref.ts @@ -14,11 +14,12 @@ import "../../../../components/buttons/ha-call-api-button"; import "../../../../components/ha-card"; import type { HaSwitch } from "../../../../components/ha-switch"; import { CloudStatusLoggedIn, updateCloudPref } from "../../../../data/cloud"; +import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box"; import type { HomeAssistant } from "../../../../types"; import { showSaveSuccessToast } from "../../../../util/toast-saved-success"; export class CloudGooglePref extends LitElement { - @property({ attribute: false }) public hass?: HomeAssistant; + @property({ attribute: false }) public hass!: HomeAssistant; @property() public cloudStatus?: CloudStatusLoggedIn; @@ -35,7 +36,7 @@ export class CloudGooglePref extends LitElement { return html` @@ -47,36 +48,53 @@ export class CloudGooglePref extends LitElement { >
- ${this.hass!.localize("ui.panel.config.cloud.account.google.info")} - +

+ ${this.hass.localize("ui.panel.config.cloud.account.google.info")} +

+ ${!this.cloudStatus.google_registered + ? html` +

+ ${this.hass.localize( + "ui.panel.config.cloud.account.google.not_configured_title" + )} +

+

+ ${this.hass.localize( + "ui.panel.config.cloud.account.google.not_configured_text" + )} +

+ + + ` + : ""} ${google_enabled ? html`

- ${this.hass!.localize( + ${this.hass.localize( "ui.panel.config.cloud.account.google.enable_state_reporting" )}

@@ -88,25 +106,25 @@ export class CloudGooglePref extends LitElement {

- ${this.hass!.localize( + ${this.hass.localize( "ui.panel.config.cloud.account.google.info_state_reporting" )}

- ${this.hass!.localize( + ${this.hass.localize( "ui.panel.config.cloud.account.google.security_devices" )}

- ${this.hass!.localize( + ${this.hass.localize( "ui.panel.config.cloud.account.google.enter_pin_info" )} - ${this.hass!.localize( + ${this.hass.localize( "ui.panel.config.cloud.account.google.sync_entities" )} -
- ${this.hass!.localize( + + ${this.hass.localize( "ui.panel.config.cloud.account.google.manage_entities" - )} + )} +
`; } - private _syncEntitiesCalled(ev: CustomEvent) { + private async _syncEntitiesCalled(ev: CustomEvent) { if (!ev.detail.success && ev.detail.response.status_code === 404) { - alert( - this.hass!.localize( - "ui.panel.config.cloud.account.google.sync_entities_404_message" - ) - ); + this._syncFailed(); } } + private async _syncFailed() { + showAlertDialog(this, { + title: this.hass.localize( + "ui.panel.config.cloud.account.google.not_configured_title" + ), + text: this.hass.localize( + "ui.panel.config.cloud.account.google.not_configured_text" + ), + }); + fireEvent(this, "ha-refresh-cloud-status"); + } + private async _enableToggleChanged(ev) { const toggle = ev.target as HaSwitch; try { - await updateCloudPref(this.hass!, { [toggle.id]: toggle.checked! }); + await updateCloudPref(this.hass, { [toggle.id]: toggle.checked! }); fireEvent(this, "ha-refresh-cloud-status"); } catch (err) { toggle.checked = !toggle.checked; @@ -163,7 +189,7 @@ export class CloudGooglePref extends LitElement { private async _reportToggleChanged(ev) { const toggle = ev.target as HaSwitch; try { - await updateCloudPref(this.hass!, { + await updateCloudPref(this.hass, { google_report_state: toggle.checked!, }); fireEvent(this, "ha-refresh-cloud-status"); @@ -180,14 +206,14 @@ export class CloudGooglePref extends LitElement { private async _pinChanged(ev) { const input = ev.target as PaperInputElement; try { - await updateCloudPref(this.hass!, { + await updateCloudPref(this.hass, { [input.id]: input.value || null, }); - showSaveSuccessToast(this, this.hass!); + showSaveSuccessToast(this, this.hass); fireEvent(this, "ha-refresh-cloud-status"); } catch (err) { alert( - `${this.hass!.localize( + `${this.hass.localize( "ui.panel.config.cloud.account.google.enter_pin_error" )} ${err.message}` ); @@ -203,7 +229,7 @@ export class CloudGooglePref extends LitElement { .switch { position: absolute; right: 24px; - top: 32px; + top: 24px; } :host([dir="rtl"]) .switch { right: auto; @@ -213,20 +239,21 @@ export class CloudGooglePref extends LitElement { color: var(--primary-color); font-weight: 500; } - .secure_devices { - padding-top: 8px; - } paper-input { width: 250px; } .card-actions { display: flex; + justify-content: space-between; } .card-actions a { text-decoration: none; } - .spacer { - flex-grow: 1; + .warning { + color: var(--error-color); + } + .secure_devices { + padding-top: 8px; } .state-reporting { display: flex; diff --git a/src/panels/config/cloud/account/cloud-remote-pref.ts b/src/panels/config/cloud/account/cloud-remote-pref.ts index 0df92f38da..dbc31c7a94 100644 --- a/src/panels/config/cloud/account/cloud-remote-pref.ts +++ b/src/panels/config/cloud/account/cloud-remote-pref.ts @@ -148,7 +148,7 @@ export class CloudRemotePref extends LitElement { .switch { position: absolute; right: 24px; - top: 32px; + top: 24px; } :host([dir="rtl"]) .switch { right: auto; 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 7dd4b18354..4582ff7a1b 100644 --- a/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts +++ b/src/panels/config/cloud/google-assistant/cloud-google-assistant.ts @@ -371,7 +371,9 @@ class CloudGoogleAssistant extends LitElement { await this._updateConfig(entityId, { should_expose: newExposed, }); - this._ensureEntitySync(); + if (this.cloudStatus.google_registered) { + this._ensureEntitySync(); + } } private async _disable2FAChanged(ev: Event) { diff --git a/src/translations/en.json b/src/translations/en.json index 70ca41b36a..14f27de00e 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -1805,7 +1805,7 @@ "google": { "title": "Google Assistant", "info": "With the Google Assistant integration for Home Assistant Cloud you'll be able to control all your Home Assistant devices via any Google Assistant-enabled device.", - "enable_ha_skill": "Activate the Home Assistant skill for Google Assistant", + "enable_ha_skill": "Activate the Home Assistant Cloud skill for Google Assistant", "config_documentation": "Configuration documentation", "enable_state_reporting": "Enable State Reporting", "info_state_reporting": "If you enable state reporting, Home Assistant will send all state changes of exposed entities to Google. This allows you to always see the latest states in the Google app.", @@ -1816,7 +1816,9 @@ "sync_entities": "Sync Entities to Google", "sync_entities_404_message": "Failed to sync your entities to Google, ask Google 'Hey Google, sync my devices' to sync your entities.", "manage_entities": "Manage Entities", - "enter_pin_error": "Unable to store PIN:" + "enter_pin_error": "Unable to store PIN:", + "not_configured_title": "Google Assistant is not activated", + "not_configured_text": "Before you can use Google Assistant, you need to activate the Home Assistant Cloud skill for Google Assistant in the Google Home app." }, "webhooks": { "title": "Webhooks",