Check if Google Assistant is linked (#8613)

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
Bram Kragten 2021-03-29 19:27:45 +02:00 committed by GitHub
parent 10b8efc5cb
commit 66c30a59e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 171 additions and 127 deletions

View File

@ -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`
<ha-progress-button
.progress="${this.progress}"
@click="${this._buttonTapped}"
?disabled="${this.disabled}"
><slot></slot
></ha-progress-button>
`;
}
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);

View File

@ -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`
<ha-progress-button
.progress=${this.progress}
@click=${this._buttonTapped}
?disabled=${this.disabled}
><slot></slot
></ha-progress-button>
`;
}
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;
}
}

View File

@ -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;

View File

@ -169,7 +169,7 @@ export class CloudAlexaPref extends LitElement {
.switch {
position: absolute;
right: 24px;
top: 32px;
top: 24px;
}
:host([dir="rtl"]) .switch {
right: auto;

View File

@ -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`
<ha-card
header=${this.hass!.localize(
header=${this.hass.localize(
"ui.panel.config.cloud.account.google.title"
)}
>
@ -47,36 +48,53 @@ export class CloudGooglePref extends LitElement {
></ha-switch>
</div>
<div class="card-content">
${this.hass!.localize("ui.panel.config.cloud.account.google.info")}
<ul>
<li>
<a
href="https://assistant.google.com/services/a/uid/00000091fd5fb875?hl=en-US"
target="_blank"
rel="noreferrer"
>
${this.hass!.localize(
"ui.panel.config.cloud.account.google.enable_ha_skill"
)}
</a>
</li>
<li>
<a
href="https://www.nabucasa.com/config/google_assistant/"
target="_blank"
rel="noreferrer"
>
${this.hass!.localize(
"ui.panel.config.cloud.account.google.config_documentation"
)}
</a>
</li>
</ul>
<p>
${this.hass.localize("ui.panel.config.cloud.account.google.info")}
</p>
${!this.cloudStatus.google_registered
? html`
<h3 class="warning">
${this.hass.localize(
"ui.panel.config.cloud.account.google.not_configured_title"
)}
</h3>
<p>
${this.hass.localize(
"ui.panel.config.cloud.account.google.not_configured_text"
)}
</p>
<ul>
<li>
<a
href="https://assistant.google.com/services/a/uid/00000091fd5fb875?hl=en-US"
target="_blank"
rel="noreferrer"
>
${this.hass.localize(
"ui.panel.config.cloud.account.google.enable_ha_skill"
)}
</a>
</li>
<li>
<a
href="https://www.nabucasa.com/config/google_assistant/"
target="_blank"
rel="noreferrer"
>
${this.hass.localize(
"ui.panel.config.cloud.account.google.config_documentation"
)}
</a>
</li>
</ul>
`
: ""}
${google_enabled
? html`
<div class="state-reporting">
<h3>
${this.hass!.localize(
${this.hass.localize(
"ui.panel.config.cloud.account.google.enable_state_reporting"
)}
</h3>
@ -88,25 +106,25 @@ export class CloudGooglePref extends LitElement {
</div>
</div>
<p>
${this.hass!.localize(
${this.hass.localize(
"ui.panel.config.cloud.account.google.info_state_reporting"
)}
</p>
<div class="secure_devices">
<h3>
${this.hass!.localize(
${this.hass.localize(
"ui.panel.config.cloud.account.google.security_devices"
)}
</h3>
${this.hass!.localize(
${this.hass.localize(
"ui.panel.config.cloud.account.google.enter_pin_info"
)}
<paper-input
label="${this.hass!.localize(
label="${this.hass.localize(
"ui.panel.config.cloud.account.google.devices_pin"
)}"
id="google_secure_devices_pin"
placeholder="${this.hass!.localize(
placeholder="${this.hass.localize(
"ui.panel.config.cloud.account.google.enter_pin_hint"
)}"
.value=${google_secure_devices_pin || ""}
@ -119,41 +137,49 @@ export class CloudGooglePref extends LitElement {
<div class="card-actions">
<ha-call-api-button
.hass=${this.hass}
.disabled="${!google_enabled}"
.disabled="${!this.cloudStatus.google_registered ||
!google_enabled}"
@hass-api-called=${this._syncEntitiesCalled}
path="cloud/google_actions/sync"
>
${this.hass!.localize(
${this.hass.localize(
"ui.panel.config.cloud.account.google.sync_entities"
)}
</ha-call-api-button>
<div class="spacer"></div>
<a href="/config/cloud/google-assistant">
<mwc-button
>${this.hass!.localize(
<mwc-button>
${this.hass.localize(
"ui.panel.config.cloud.account.google.manage_entities"
)}</mwc-button
>
)}
</mwc-button>
</a>
</div>
</ha-card>
`;
}
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;

View File

@ -148,7 +148,7 @@ export class CloudRemotePref extends LitElement {
.switch {
position: absolute;
right: 24px;
top: 32px;
top: 24px;
}
:host([dir="rtl"]) .switch {
right: auto;

View File

@ -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) {

View File

@ -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",