mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-13 20:36:35 +00:00
Add cloud signup to voice flow (#22941)
This commit is contained in:
parent
3e02d95e01
commit
f8fb5d7bf2
174
src/dialogs/voice-assistant-setup/cloud/cloud-step-intro.ts
Normal file
174
src/dialogs/voice-assistant-setup/cloud/cloud-step-intro.ts
Normal file
@ -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
src/dialogs/voice-assistant-setup/cloud/cloud-step-signin.ts
Normal file
167
src/dialogs/voice-assistant-setup/cloud/cloud-step-signin.ts
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
212
src/dialogs/voice-assistant-setup/cloud/cloud-step-signup.ts
Normal file
212
src/dialogs/voice-assistant-setup/cloud/cloud-step-signup.ts
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
import { LitElement, css, html } from "lit";
|
||||||
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
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,
|
||||||
|
cloudRegister,
|
||||||
|
cloudResendVerification,
|
||||||
|
} from "../../../data/cloud";
|
||||||
|
import type { HomeAssistant } from "../../../types";
|
||||||
|
import { AssistantSetupStyles } from "../styles";
|
||||||
|
|
||||||
|
@customElement("cloud-step-signup")
|
||||||
|
export class CloudStepSignup extends LitElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@state() private _requestInProgress = false;
|
||||||
|
|
||||||
|
@state() private _email?: string;
|
||||||
|
|
||||||
|
@state() private _password?: string;
|
||||||
|
|
||||||
|
@state() private _error?: string;
|
||||||
|
|
||||||
|
@state() private _state?: "VERIFY";
|
||||||
|
|
||||||
|
@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 up</h1>
|
||||||
|
${this._error
|
||||||
|
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||||
|
: ""}
|
||||||
|
${this._state === "VERIFY"
|
||||||
|
? html`<p>
|
||||||
|
Check the email we just sent to ${this._email} and click the
|
||||||
|
confirmation link to continue.
|
||||||
|
</p>`
|
||||||
|
: html`<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 side-by-side">
|
||||||
|
${this._state === "VERIFY"
|
||||||
|
? html`<ha-button
|
||||||
|
@click=${this._handleResendVerifyEmail}
|
||||||
|
.disabled=${this._requestInProgress}
|
||||||
|
>Send the email again</ha-button
|
||||||
|
><ha-button
|
||||||
|
unelevated
|
||||||
|
@click=${this._login}
|
||||||
|
.disabled=${this._requestInProgress}
|
||||||
|
>I clicked the link</ha-button
|
||||||
|
>`
|
||||||
|
: html`<ha-button
|
||||||
|
@click=${this._signIn}
|
||||||
|
.disabled=${this._requestInProgress}
|
||||||
|
>Sign in</ha-button
|
||||||
|
>
|
||||||
|
<ha-button
|
||||||
|
unelevated
|
||||||
|
@click=${this._handleRegister}
|
||||||
|
.disabled=${this._requestInProgress}
|
||||||
|
>Next</ha-button
|
||||||
|
>`}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _signIn() {
|
||||||
|
fireEvent(this, "cloud-step", { step: "SIGNIN" });
|
||||||
|
}
|
||||||
|
|
||||||
|
private _keyDown(ev: KeyboardEvent) {
|
||||||
|
if (ev.key === "Enter") {
|
||||||
|
this._handleRegister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _handleRegister() {
|
||||||
|
const emailField = this._emailField;
|
||||||
|
const passwordField = this._passwordField;
|
||||||
|
|
||||||
|
if (!emailField.reportValidity()) {
|
||||||
|
passwordField.reportValidity();
|
||||||
|
emailField.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!passwordField.reportValidity()) {
|
||||||
|
passwordField.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const email = emailField.value.toLowerCase();
|
||||||
|
const password = passwordField.value;
|
||||||
|
|
||||||
|
this._requestInProgress = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await cloudRegister(this.hass, email, password);
|
||||||
|
this._email = email;
|
||||||
|
this._password = password;
|
||||||
|
this._verificationEmailSent();
|
||||||
|
} catch (err: any) {
|
||||||
|
this._password = "";
|
||||||
|
this._error =
|
||||||
|
err && err.body && err.body.message
|
||||||
|
? err.body.message
|
||||||
|
: "Unknown error";
|
||||||
|
} finally {
|
||||||
|
this._requestInProgress = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _handleResendVerifyEmail() {
|
||||||
|
if (!this._email) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await cloudResendVerification(this.hass, this._email);
|
||||||
|
this._verificationEmailSent();
|
||||||
|
} catch (err: any) {
|
||||||
|
this._error =
|
||||||
|
err && err.body && err.body.message
|
||||||
|
? err.body.message
|
||||||
|
: "Unknown error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _verificationEmailSent() {
|
||||||
|
this._state = "VERIFY";
|
||||||
|
|
||||||
|
setTimeout(() => this._login(), 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _login() {
|
||||||
|
if (!this._email || !this._password) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await cloudLogin(this.hass, this._email, this._password);
|
||||||
|
fireEvent(this, "cloud-step", { step: "DONE" });
|
||||||
|
} catch (e: any) {
|
||||||
|
if (e?.body?.code === "usernotconfirmed") {
|
||||||
|
this._verificationEmailSent();
|
||||||
|
} else {
|
||||||
|
this._error = "Something went wrong. Please try again.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static styles = [
|
||||||
|
AssistantSetupStyles,
|
||||||
|
css`
|
||||||
|
.content {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
ha-textfield,
|
||||||
|
ha-password-field {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"cloud-step-signup": CloudStepSignup;
|
||||||
|
}
|
||||||
|
}
|
@ -1,171 +1,54 @@
|
|||||||
import { mdiEarth, mdiMicrophoneMessage, mdiOpenInNew } from "@mdi/js";
|
import { html, LitElement } from "lit";
|
||||||
import { css, html, LitElement } from "lit";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
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 type { HomeAssistant } from "../../types";
|
||||||
import { brandsUrl } from "../../util/brands-url";
|
import "./cloud/cloud-step-intro";
|
||||||
import { AssistantSetupStyles } from "./styles";
|
import "./cloud/cloud-step-signin";
|
||||||
|
import "./cloud/cloud-step-signup";
|
||||||
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
|
import { STEP } from "./voice-assistant-setup-dialog";
|
||||||
|
|
||||||
@customElement("ha-voice-assistant-setup-step-cloud")
|
@customElement("ha-voice-assistant-setup-step-cloud")
|
||||||
export class HaVoiceAssistantSetupStepCloud extends LitElement {
|
export class HaVoiceAssistantSetupStepCloud extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@state() private _state: "SIGNUP" | "SIGNIN" | "INTRO" = "INTRO";
|
||||||
|
|
||||||
protected override render() {
|
protected override render() {
|
||||||
return html`<div class="content">
|
if (this._state === "SIGNUP") {
|
||||||
<img
|
return html`<cloud-step-signup
|
||||||
src=${`/static/images/logo_nabu_casa${this.hass.themes?.darkMode ? "_dark" : ""}.png`}
|
.hass=${this.hass}
|
||||||
alt="Nabu Casa logo"
|
@cloud-step=${this._cloudStep}
|
||||||
/>
|
></cloud-step-signup>`;
|
||||||
<h1>The power of Home Assistant Cloud</h1>
|
}
|
||||||
<div class="features">
|
if (this._state === "SIGNIN") {
|
||||||
<div class="feature speech">
|
return html`<cloud-step-signin
|
||||||
<div class="logos">
|
.hass=${this.hass}
|
||||||
<div class="round-icon">
|
@cloud-step=${this._cloudStep}
|
||||||
<ha-svg-icon .path=${mdiMicrophoneMessage}></ha-svg-icon>
|
></cloud-step-signin>`;
|
||||||
</div>
|
}
|
||||||
</div>
|
return html`<cloud-step-intro
|
||||||
<h2>
|
.hass=${this.hass}
|
||||||
${this.hass.localize(
|
@cloud-step=${this._cloudStep}
|
||||||
"ui.panel.config.voice_assistants.assistants.cloud.features.speech.title"
|
></cloud-step-intro>`;
|
||||||
)}
|
|
||||||
<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>
|
|
||||||
<a href="/config/cloud/register" @click=${this._close}
|
|
||||||
><ha-button unelevated>Try 1 month for free</ha-button></a
|
|
||||||
>
|
|
||||||
</div>`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _close() {
|
private _cloudStep(ev) {
|
||||||
fireEvent(this, "closed");
|
if (ev.detail.step === "DONE") {
|
||||||
|
fireEvent(this, "next-step", {
|
||||||
|
step: STEP.PIPELINE,
|
||||||
|
noPrevious: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
this._state = ev.detail.step;
|
||||||
static styles = [
|
|
||||||
AssistantSetupStyles,
|
|
||||||
css`
|
|
||||||
.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 {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"ha-voice-assistant-setup-step-cloud": HaVoiceAssistantSetupStepCloud;
|
"ha-voice-assistant-setup-step-cloud": HaVoiceAssistantSetupStepCloud;
|
||||||
}
|
}
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"cloud-step": { step: "SIGNUP" | "SIGNIN" | "DONE" };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user