-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add cloud signup to voice flow (#22941)
- Loading branch information
1 parent
3e02d95
commit f8fb5d7
Showing
4 changed files
with
590 additions
and
154 deletions.
There are no files selected for viewing
174 changes: 174 additions & 0 deletions
174
src/dialogs/voice-assistant-setup/cloud/cloud-step-intro.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
import { mdiEarth, mdiMicrophoneMessage, mdiOpenInNew } from "@mdi/js"; | ||
import { LitElement, css, html } from "lit"; | ||
import { customElement, property } from "lit/decorators"; | ||
import { fireEvent } from "../../../common/dom/fire_event"; | ||
import "../../../components/ha-button"; | ||
import "../../../components/ha-svg-icon"; | ||
import type { HomeAssistant } from "../../../types"; | ||
import { brandsUrl } from "../../../util/brands-url"; | ||
import { AssistantSetupStyles } from "../styles"; | ||
|
||
@customElement("cloud-step-intro") | ||
export class CloudStepIntro extends LitElement { | ||
@property({ attribute: false }) public hass!: HomeAssistant; | ||
|
||
render() { | ||
return html`<div class="content"> | ||
<img | ||
src=${`/static/images/logo_nabu_casa${this.hass.themes?.darkMode ? "_dark" : ""}.png`} | ||
alt="Nabu Casa logo" | ||
/> | ||
<h1>The power of Home Assistant Cloud</h1> | ||
<div class="features"> | ||
<div class="feature speech"> | ||
<div class="logos"> | ||
<div class="round-icon"> | ||
<ha-svg-icon .path=${mdiMicrophoneMessage}></ha-svg-icon> | ||
</div> | ||
</div> | ||
<h2> | ||
${this.hass.localize( | ||
"ui.panel.config.voice_assistants.assistants.cloud.features.speech.title" | ||
)} | ||
<span class="no-wrap"></span> | ||
</h2> | ||
<p> | ||
${this.hass.localize( | ||
"ui.panel.config.voice_assistants.assistants.cloud.features.speech.text" | ||
)} | ||
</p> | ||
</div> | ||
<div class="feature access"> | ||
<div class="logos"> | ||
<div class="round-icon"> | ||
<ha-svg-icon .path=${mdiEarth}></ha-svg-icon> | ||
</div> | ||
</div> | ||
<h2> | ||
Remote access | ||
<span class="no-wrap"></span> | ||
</h2> | ||
<p> | ||
Secure remote access to your system while supporting the | ||
development of Home Assistant. | ||
</p> | ||
</div> | ||
<div class="feature"> | ||
<div class="logos"> | ||
<img | ||
alt="Google Assistant" | ||
src=${brandsUrl({ | ||
domain: "google_assistant", | ||
type: "icon", | ||
darkOptimized: this.hass.themes?.darkMode, | ||
})} | ||
crossorigin="anonymous" | ||
referrerpolicy="no-referrer" | ||
/> | ||
<img | ||
alt="Amazon Alexa" | ||
src=${brandsUrl({ | ||
domain: "alexa", | ||
type: "icon", | ||
darkOptimized: this.hass.themes?.darkMode, | ||
})} | ||
crossorigin="anonymous" | ||
referrerpolicy="no-referrer" | ||
/> | ||
</div> | ||
<h2> | ||
${this.hass.localize( | ||
"ui.panel.config.voice_assistants.assistants.cloud.features.assistants.title" | ||
)} | ||
</h2> | ||
<p> | ||
${this.hass.localize( | ||
"ui.panel.config.voice_assistants.assistants.cloud.features.assistants.text" | ||
)} | ||
</p> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="footer side-by-side"> | ||
<a | ||
href="https://www.nabucasa.com" | ||
target="_blank" | ||
rel="noreferrer noopenner" | ||
> | ||
<ha-button> | ||
<ha-svg-icon .path=${mdiOpenInNew} slot="icon"></ha-svg-icon> | ||
nabucasa.com | ||
</ha-button> | ||
</a> | ||
<ha-button unelevated @click=${this._signUp} | ||
>Try 1 month for free</ha-button | ||
> | ||
</div>`; | ||
} | ||
|
||
private _signUp() { | ||
fireEvent(this, "cloud-step", { step: "SIGNUP" }); | ||
} | ||
|
||
static styles = [ | ||
AssistantSetupStyles, | ||
css` | ||
:host { | ||
display: flex; | ||
} | ||
.features { | ||
display: flex; | ||
flex-direction: column; | ||
grid-gap: 16px; | ||
padding: 16px; | ||
} | ||
.feature { | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
text-align: center; | ||
margin-bottom: 16px; | ||
} | ||
.feature .logos { | ||
margin-bottom: 16px; | ||
} | ||
.feature .logos > * { | ||
width: 40px; | ||
height: 40px; | ||
margin: 0 4px; | ||
} | ||
.round-icon { | ||
border-radius: 50%; | ||
color: #6e41ab; | ||
background-color: #e8dcf7; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
font-size: 24px; | ||
} | ||
.access .round-icon { | ||
color: #00aef8; | ||
background-color: #cceffe; | ||
} | ||
.feature h2 { | ||
font-weight: 500; | ||
font-size: 16px; | ||
line-height: 24px; | ||
margin-top: 0; | ||
margin-bottom: 8px; | ||
} | ||
.feature p { | ||
font-weight: 400; | ||
font-size: 14px; | ||
line-height: 20px; | ||
margin: 0; | ||
} | ||
`, | ||
]; | ||
} | ||
|
||
declare global { | ||
interface HTMLElementTagNameMap { | ||
"cloud-step-intro": CloudStepIntro; | ||
} | ||
} |
167 changes: 167 additions & 0 deletions
167
src/dialogs/voice-assistant-setup/cloud/cloud-step-signin.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
import { LitElement, css, html } from "lit"; | ||
import { customElement, property, query, state } from "lit/decorators"; | ||
import { fireEvent } from "../../../common/dom/fire_event"; | ||
import { navigate } from "../../../common/navigate"; | ||
import "../../../components/ha-alert"; | ||
import "../../../components/ha-button"; | ||
import "../../../components/ha-password-field"; | ||
import type { HaPasswordField } from "../../../components/ha-password-field"; | ||
import "../../../components/ha-svg-icon"; | ||
import "../../../components/ha-textfield"; | ||
import type { HaTextField } from "../../../components/ha-textfield"; | ||
import { cloudLogin } from "../../../data/cloud"; | ||
import type { HomeAssistant } from "../../../types"; | ||
import { showAlertDialog } from "../../generic/show-dialog-box"; | ||
import { AssistantSetupStyles } from "../styles"; | ||
|
||
@customElement("cloud-step-signin") | ||
export class CloudStepSignin extends LitElement { | ||
@property({ attribute: false }) public hass!: HomeAssistant; | ||
|
||
@state() private _requestInProgress = false; | ||
|
||
@state() private _error?: string; | ||
|
||
@query("#email", true) private _emailField!: HaTextField; | ||
|
||
@query("#password", true) private _passwordField!: HaPasswordField; | ||
|
||
render() { | ||
return html`<div class="content"> | ||
<img | ||
src=${`/static/images/logo_nabu_casa${this.hass.themes?.darkMode ? "_dark" : ""}.png`} | ||
alt="Nabu Casa logo" | ||
/> | ||
<h1>Sign in</h1> | ||
${this._error | ||
? html`<ha-alert alert-type="error">${this._error}</ha-alert>` | ||
: ""} | ||
<ha-textfield | ||
autofocus | ||
id="email" | ||
name="email" | ||
.label=${this.hass.localize( | ||
"ui.panel.config.cloud.register.email_address" | ||
)} | ||
.disabled=${this._requestInProgress} | ||
type="email" | ||
autocomplete="email" | ||
required | ||
@keydown=${this._keyDown} | ||
validationMessage=${this.hass.localize( | ||
"ui.panel.config.cloud.register.email_error_msg" | ||
)} | ||
></ha-textfield> | ||
<ha-password-field | ||
id="password" | ||
name="password" | ||
.label=${this.hass.localize( | ||
"ui.panel.config.cloud.register.password" | ||
)} | ||
.disabled=${this._requestInProgress} | ||
autocomplete="new-password" | ||
minlength="8" | ||
required | ||
@keydown=${this._keyDown} | ||
validationMessage=${this.hass.localize( | ||
"ui.panel.config.cloud.register.password_error_msg" | ||
)} | ||
></ha-password-field> | ||
</div> | ||
<div class="footer"> | ||
<ha-button | ||
unelevated | ||
@click=${this._handleLogin} | ||
.disabled=${this._requestInProgress} | ||
>Sign in</ha-button | ||
> | ||
</div>`; | ||
} | ||
|
||
private _keyDown(ev: KeyboardEvent) { | ||
if (ev.key === "Enter") { | ||
this._handleLogin(); | ||
} | ||
} | ||
|
||
private async _handleLogin() { | ||
const emailField = this._emailField; | ||
const passwordField = this._passwordField; | ||
|
||
const email = emailField.value; | ||
const password = passwordField.value; | ||
|
||
if (!emailField.reportValidity()) { | ||
passwordField.reportValidity(); | ||
emailField.focus(); | ||
return; | ||
} | ||
|
||
if (!passwordField.reportValidity()) { | ||
passwordField.focus(); | ||
return; | ||
} | ||
|
||
this._requestInProgress = true; | ||
|
||
const doLogin = async (username: string) => { | ||
try { | ||
await cloudLogin(this.hass, username, password); | ||
} catch (err: any) { | ||
const errCode = err && err.body && err.body.code; | ||
|
||
if (errCode === "usernotfound" && username !== username.toLowerCase()) { | ||
await doLogin(username.toLowerCase()); | ||
return; | ||
} | ||
|
||
if (errCode === "PasswordChangeRequired") { | ||
showAlertDialog(this, { | ||
title: this.hass.localize( | ||
"ui.panel.config.cloud.login.alert_password_change_required" | ||
), | ||
}); | ||
navigate("/config/cloud/forgot-password"); | ||
fireEvent(this, "closed"); | ||
return; | ||
} | ||
|
||
this._requestInProgress = false; | ||
|
||
if (errCode === "UserNotConfirmed") { | ||
this._error = this.hass.localize( | ||
"ui.panel.config.cloud.login.alert_email_confirm_necessary" | ||
); | ||
} else { | ||
this._error = | ||
err && err.body && err.body.message | ||
? err.body.message | ||
: "Unknown error"; | ||
} | ||
|
||
emailField.focus(); | ||
} | ||
}; | ||
|
||
await doLogin(email); | ||
} | ||
|
||
static styles = [ | ||
AssistantSetupStyles, | ||
css` | ||
:host { | ||
display: block; | ||
} | ||
ha-textfield, | ||
ha-password-field { | ||
display: block; | ||
} | ||
`, | ||
]; | ||
} | ||
|
||
declare global { | ||
interface HTMLElementTagNameMap { | ||
"cloud-step-signin": CloudStepSignin; | ||
} | ||
} |
Oops, something went wrong.