mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-13 04:16:34 +00:00
Add initial cloud login (#411)
This commit is contained in:
parent
894a84ba77
commit
b3995e63be
63
panels/config/cloud/ha-config-cloud-account.html
Normal file
63
panels/config/cloud/ha-config-cloud-account.html
Normal file
@ -0,0 +1,63 @@
|
||||
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
|
||||
<link rel="import" href='../../../bower_components/paper-card/paper-card.html'>
|
||||
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
|
||||
<link rel="import" href="../../../bower_components/paper-item/paper-item-body.html">
|
||||
<link rel="import" href='../../../bower_components/paper-button/paper-button.html'>
|
||||
|
||||
<link rel="import" href='../../../src/resources/ha-style.html'>
|
||||
|
||||
<dom-module id="ha-config-cloud-account">
|
||||
<template>
|
||||
<style include="iron-flex ha-style">
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.account {
|
||||
display: flex;
|
||||
padding: 0 16px;
|
||||
}
|
||||
paper-button {
|
||||
align-self: center;
|
||||
}
|
||||
.soon {
|
||||
font-style: italic;
|
||||
margin-top: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
<paper-card>
|
||||
<div class='account'>
|
||||
<paper-item-body two-line>
|
||||
[[account.first_name]] [[account.last_name]]
|
||||
<div secondary>[[account.email]]</div>
|
||||
</paper-item-body>
|
||||
<paper-button
|
||||
class='warning'
|
||||
on-tap='handleLogout'
|
||||
>Sign out</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
|
||||
<div class='soon'>More configuration options coming soon.</div>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
class HaConfigCloudAccount extends window.hassMixins.EventsMixin(Polymer.Element) {
|
||||
static get is() { return 'ha-config-cloud-account'; }
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
account: Object,
|
||||
};
|
||||
}
|
||||
|
||||
handleLogout() {
|
||||
this.hass.callApi('post', 'cloud/logout').then(
|
||||
() => this.fire('ha-account-refreshed', { account: null }));
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(HaConfigCloudAccount.is, HaConfigCloudAccount);
|
||||
</script>
|
92
panels/config/cloud/ha-config-cloud-login.html
Normal file
92
panels/config/cloud/ha-config-cloud-login.html
Normal file
@ -0,0 +1,92 @@
|
||||
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
|
||||
<link rel="import" href='../../../bower_components/paper-card/paper-card.html'>
|
||||
<link rel="import" href='../../../bower_components/paper-button/paper-button.html'>
|
||||
<link rel="import" href='../../../bower_components/paper-input/paper-input.html'>
|
||||
|
||||
<link rel="import" href='../../../src/resources/ha-style.html'>
|
||||
|
||||
<dom-module id="ha-config-cloud-login">
|
||||
<template>
|
||||
<style include="iron-flex ha-style">
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
h1 {
|
||||
@apply(--paper-font-headline);
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
<paper-card>
|
||||
<div class='card-content'>
|
||||
<h1>Sign In</h1>
|
||||
<paper-input
|
||||
label='Username'
|
||||
value='{{username}}'
|
||||
error-message='Failed to login'
|
||||
invalid='[[error]]'
|
||||
on-keydown='_keyDown'
|
||||
></paper-input>
|
||||
<paper-input
|
||||
label='Password'
|
||||
value='{{password}}'
|
||||
type='password'
|
||||
on-keydown='_keyDown'
|
||||
></paper-input>
|
||||
</div>
|
||||
<div class='card-actions'>
|
||||
<paper-button
|
||||
on-tap='_handleLogin'
|
||||
>Sign in</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
class HaConfigCloudLogin extends window.hassMixins.EventsMixin(Polymer.Element) {
|
||||
static get is() { return 'ha-config-cloud-login'; }
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
username: String,
|
||||
password: String,
|
||||
};
|
||||
}
|
||||
|
||||
static get observers() {
|
||||
return [
|
||||
'_inputChanged(username, password)'
|
||||
];
|
||||
}
|
||||
|
||||
_inputChanged() {
|
||||
this.error = false;
|
||||
}
|
||||
|
||||
_keyDown(ev) {
|
||||
// validate on enter
|
||||
if (ev.keyCode === 13) {
|
||||
this._handleLogin();
|
||||
ev.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
_handleLogin() {
|
||||
this.hass.callApi('post', 'cloud/login', {
|
||||
username: this.username,
|
||||
password: this.password,
|
||||
}).then(
|
||||
(account) => {
|
||||
this.fire('ha-account-refreshed', { account: account });
|
||||
this.username = '';
|
||||
this.password = '';
|
||||
}, () => {
|
||||
this.password = '';
|
||||
this.error = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(HaConfigCloudLogin.is, HaConfigCloudLogin);
|
||||
</script>
|
90
panels/config/cloud/ha-config-cloud.html
Normal file
90
panels/config/cloud/ha-config-cloud.html
Normal file
@ -0,0 +1,90 @@
|
||||
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
|
||||
<link rel="import" href="../../../bower_components/app-layout/app-header-layout/app-header-layout.html">
|
||||
<link rel="import" href="../../../bower_components/app-layout/app-header/app-header.html">
|
||||
<link rel="import" href="../../../bower_components/app-layout/app-toolbar/app-toolbar.html">
|
||||
|
||||
<link rel="import" href="../ha-config-section.html">
|
||||
|
||||
<link rel="import" href="./ha-config-cloud-login.html">
|
||||
<link rel="import" href="./ha-config-cloud-account.html">
|
||||
|
||||
<dom-module id="ha-config-cloud">
|
||||
<template>
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
icon='mdi:arrow-left'
|
||||
on-tap='_backTapped'
|
||||
></paper-icon-button>
|
||||
<div main-title>Cloud</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<div class$='[[computeClasses(isWide)]]'>
|
||||
<ha-config-section
|
||||
is-wide='[[isWide]]'
|
||||
>
|
||||
<span slot='header'>Home Assistant Cloud</span>
|
||||
<span slot='introduction'>
|
||||
The Home Assistant Cloud allows you to opt-in to functions that will bring your Home Assistant experience to the next level.
|
||||
|
||||
<p><i>
|
||||
Home Assistant will never share information with our cloud without your prior permission.
|
||||
</i></p>
|
||||
</span>
|
||||
|
||||
<template is='dom-if' if='[[account]]'>
|
||||
<ha-config-cloud-account
|
||||
hass='[[hass]]'
|
||||
account='[[account]]'
|
||||
></ha-config-cloud-account>
|
||||
</template>
|
||||
|
||||
<template is='dom-if' if='[[!account]]'>
|
||||
<ha-config-cloud-login
|
||||
hass='[[hass]]'
|
||||
></ha-config-cloud-login>
|
||||
</template>
|
||||
</ha-config-section>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
class HaConfigCloud extends Polymer.Element {
|
||||
static get is() { return 'ha-config-cloud'; }
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
isWide: Boolean,
|
||||
loadingAccount: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
account: {
|
||||
type: Object,
|
||||
value: null,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
computeClasses(isWide) {
|
||||
return isWide ? 'content' : 'content narrow';
|
||||
}
|
||||
|
||||
_backTapped() {
|
||||
history.back();
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(HaConfigCloud.is, HaConfigCloud);
|
||||
</script>
|
52
panels/config/dashboard/ha-config-cloud-menu.html
Normal file
52
panels/config/dashboard/ha-config-cloud-menu.html
Normal file
@ -0,0 +1,52 @@
|
||||
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
|
||||
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
|
||||
<link rel="import" href="../../../bower_components/paper-item/paper-item.html">
|
||||
<link rel="import" href="../../../bower_components/paper-item/paper-item-body.html">
|
||||
<link rel="import" href="../../../bower_components/iron-icon/iron-icon.html">
|
||||
|
||||
<dom-module id="ha-config-cloud-menu">
|
||||
<template>
|
||||
<style include="iron-flex">
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<paper-card>
|
||||
<paper-item on-tap='_navigate'>
|
||||
<paper-item-body two-line>
|
||||
Home Assistant Cloud
|
||||
<template is='dom-if' if='[[account]]'>
|
||||
<div secondary>Logged in as [[account.first_name]] [[account.last_name]]</div>
|
||||
</template>
|
||||
<template is='dom-if' if='[[!account]]'>
|
||||
<div secondary>Not logged in</div>
|
||||
</template>
|
||||
</paper-item-body>
|
||||
<iron-icon icon='mdi:chevron-right'></iron-icon>
|
||||
</paper-item>
|
||||
</paper-card>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
class HaConfigCloudMenu extends window.hassMixins.NavigateMixin(Polymer.Element) {
|
||||
static get is() { return 'ha-config-cloud-menu'; }
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
isWide: Boolean,
|
||||
account: Object,
|
||||
};
|
||||
}
|
||||
|
||||
_navigate() {
|
||||
this.navigate('/config/cloud');
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(HaConfigCloudMenu.is, HaConfigCloudMenu);
|
||||
</script>
|
@ -1,11 +1,13 @@
|
||||
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
|
||||
<link rel="import" href="../../../bower_components/app-layout/app-header-layout/app-header-layout.html">
|
||||
<link rel="import" href="../../../bower_components/app-layout/app-header/app-header.html">
|
||||
<link rel="import" href="../../../bower_components/app-layout/app-toolbar/app-toolbar.html">
|
||||
|
||||
<link rel="import" href="../../../src/components/ha-menu-button.html">
|
||||
<link rel="import" href="../ha-config-section.html">
|
||||
|
||||
<link rel="import" href="./ha-config-navigation.html">
|
||||
<link rel="import" href="./ha-config-cloud-menu.html">
|
||||
|
||||
<dom-module id="ha-config-dashboard">
|
||||
<template>
|
||||
@ -13,16 +15,6 @@
|
||||
.content {
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
.border {
|
||||
margin: 32px auto 0;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
||||
max-width: 1040px;
|
||||
}
|
||||
|
||||
.narrow .border {
|
||||
max-width: 640px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<app-header-layout has-scrolling-region>
|
||||
@ -34,31 +26,53 @@
|
||||
</app-header>
|
||||
|
||||
<div class$='[[computeClasses(isWide)]]'>
|
||||
<ha-config-navigation
|
||||
<ha-config-section
|
||||
is-wide='[[isWide]]'
|
||||
hass='[[hass]]'
|
||||
></ha-config-navigation>
|
||||
>
|
||||
<span slot='header'>Configure Home Assistant</span>
|
||||
<span slot='introduction'>
|
||||
Here it is possible to configure your components and Home Assistant. Not everything is possible to configure from the UI yet, but we're working on it.
|
||||
</span>
|
||||
|
||||
<template is='dom-if' if='[[computeIsCloudLoaded(hass)]]'>
|
||||
<ha-config-cloud-menu
|
||||
hass='[[hass]]'
|
||||
account='[[account]]'
|
||||
></ha-config-cloud-menu>
|
||||
</template>
|
||||
|
||||
<ha-config-navigation
|
||||
hass='[[hass]]'
|
||||
></ha-config-navigation>
|
||||
</ha-config-section>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'ha-config-dashboard',
|
||||
class HaConfigDashboard extends Polymer.Element {
|
||||
static get is() { return 'ha-config-dashboard'; }
|
||||
|
||||
properties: {
|
||||
hass: Object,
|
||||
isWide: Boolean,
|
||||
},
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
isWide: Boolean,
|
||||
account: {
|
||||
type: Object,
|
||||
value: null,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
computeClasses: function (isWide) {
|
||||
computeClasses(isWide) {
|
||||
return isWide ? 'content' : 'content narrow';
|
||||
},
|
||||
}
|
||||
|
||||
computeIsThemesLoaded: function (hass) {
|
||||
return hass.themes && hass.themes.themes &&
|
||||
Object.keys(hass.themes.themes).length;
|
||||
},
|
||||
});
|
||||
computeIsCloudLoaded(hass) {
|
||||
return window.hassUtil.isComponentLoaded(hass, 'cloud');
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(HaConfigDashboard.is, HaConfigDashboard);
|
||||
</script>
|
||||
|
@ -4,39 +4,29 @@
|
||||
<link rel="import" href="../../../bower_components/paper-item/paper-item-body.html">
|
||||
<link rel="import" href="../../../bower_components/iron-icon/iron-icon.html">
|
||||
|
||||
<link rel="import" href="../../../src/resources/ha-style.html">
|
||||
|
||||
<link rel="import" href="../ha-config-section.html">
|
||||
|
||||
<dom-module id="ha-config-navigation">
|
||||
<template>
|
||||
<style include="iron-flex ha-style">
|
||||
<style include="iron-flex">
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<ha-config-section
|
||||
is-wide='[[isWide]]'
|
||||
>
|
||||
<span slot='header'>Configure Home Assistant</span>
|
||||
<span slot='introduction'>
|
||||
Here it is possible to configure your components and Home Assistant. Not everything is possible to configure from the UI yet, but we're working on it.
|
||||
</span>
|
||||
|
||||
<paper-card>
|
||||
<template is='dom-repeat' items='[[pages]]'>
|
||||
<template is='dom-if' if='[[_computeLoaded(hass, item)]]'>
|
||||
<paper-item on-tap='_navigate'>
|
||||
<paper-item-body two-line>
|
||||
[[_computeCaption(item)]]
|
||||
<div secondary>[[_computeDescription(item)]]</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon='mdi:chevron-right'></iron-icon>
|
||||
</paper-item>
|
||||
</template>
|
||||
<paper-card>
|
||||
<template is='dom-repeat' items='[[pages]]'>
|
||||
<template is='dom-if' if='[[_computeLoaded(hass, item)]]'>
|
||||
<paper-item on-tap='_navigate'>
|
||||
<paper-item-body two-line>
|
||||
[[_computeCaption(item)]]
|
||||
<div secondary>[[_computeDescription(item)]]</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon='mdi:chevron-right'></iron-icon>
|
||||
</paper-item>
|
||||
</template>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
</template>
|
||||
</paper-card>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
@ -49,11 +39,6 @@ Polymer({
|
||||
type: Object,
|
||||
},
|
||||
|
||||
isWide: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
pages: {
|
||||
type: Array,
|
||||
value: [
|
||||
|
@ -1,4 +1,4 @@
|
||||
<link rel="import" href="../../bower_components/polymer/polymer.html">
|
||||
<link rel="import" href='../../bower_components/polymer/polymer-element.html'>
|
||||
<link rel='import' href='../../bower_components/iron-media-query/iron-media-query.html'>
|
||||
<link rel='import' href='../../bower_components/app-route/app-route.html'>
|
||||
<link rel="import" href="../../bower_components/iron-pages/iron-pages.html">
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
<link rel="import" href="./dashboard/ha-config-dashboard.html">
|
||||
<link rel="import" href="./core/ha-config-core.html">
|
||||
<link rel="import" href="./cloud/ha-config-cloud.html">
|
||||
<link rel="import" href="./automation/ha-config-automation.html">
|
||||
<link rel="import" href="./script/ha-config-script.html">
|
||||
<link rel="import" href="./zwave/ha-config-zwave.html">
|
||||
@ -36,10 +37,24 @@
|
||||
fallback-selection='not-found'
|
||||
selected-attribute='visible'
|
||||
>
|
||||
<ha-config-core
|
||||
page-name='core'
|
||||
hass='[[hass]]'
|
||||
is-wide='[[isWide]]'
|
||||
></ha-config-core>
|
||||
|
||||
<ha-config-cloud
|
||||
page-name='cloud'
|
||||
hass='[[hass]]'
|
||||
is-wide='[[isWide]]'
|
||||
account='[[account]]'
|
||||
></ha-config-cloud>
|
||||
|
||||
<ha-config-dashboard
|
||||
page-name='dashboard'
|
||||
hass='[[hass]]'
|
||||
is-wide='[[isWide]]'
|
||||
account='[[account]]'
|
||||
></ha-config-dashboard>
|
||||
|
||||
<ha-config-automation
|
||||
@ -62,12 +77,6 @@
|
||||
is-wide='[[isWide]]'
|
||||
></ha-config-zwave>
|
||||
|
||||
<ha-config-core
|
||||
page-name='core'
|
||||
hass='[[hass]]'
|
||||
is-wide='[[isWide]]'
|
||||
></ha-config-core>
|
||||
|
||||
<hass-error-screen
|
||||
page-name='not-found'
|
||||
error='Page not found.'
|
||||
@ -78,40 +87,57 @@
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'ha-panel-config',
|
||||
class HaPanelConfig extends window.hassMixins.EventsMixin(Polymer.Element) {
|
||||
static get is() { return 'ha-panel-config'; }
|
||||
|
||||
properties: {
|
||||
hass: Object,
|
||||
narrow: Boolean,
|
||||
showMenu: Boolean,
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
narrow: Boolean,
|
||||
showMenu: Boolean,
|
||||
account: Object,
|
||||
|
||||
route: {
|
||||
type: Object,
|
||||
observer: '_routeChanged',
|
||||
},
|
||||
route: {
|
||||
type: Object,
|
||||
observer: '_routeChanged',
|
||||
},
|
||||
|
||||
_routeData: Object,
|
||||
_routeTail: Object,
|
||||
_routeData: Object,
|
||||
_routeTail: Object,
|
||||
|
||||
wide: Boolean,
|
||||
wideSidebar: Boolean,
|
||||
wide: Boolean,
|
||||
wideSidebar: Boolean,
|
||||
|
||||
isWide: {
|
||||
type: Boolean,
|
||||
computed: 'computeIsWide(showMenu, wideSidebar, wide)'
|
||||
},
|
||||
},
|
||||
isWide: {
|
||||
type: Boolean,
|
||||
computed: 'computeIsWide(showMenu, wideSidebar, wide)'
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
computeIsWide: function (showMenu, wideSidebar, wide) {
|
||||
ready() {
|
||||
super.ready();
|
||||
if (window.hassUtil.isComponentLoaded(this.hass, 'cloud')) {
|
||||
this.hass.callApi('get', 'cloud/account').then(
|
||||
(account) => { this.account = account; }
|
||||
);
|
||||
}
|
||||
this.addEventListener('ha-account-refreshed', (ev) => {
|
||||
this.account = ev.detail.account;
|
||||
});
|
||||
}
|
||||
|
||||
computeIsWide(showMenu, wideSidebar, wide) {
|
||||
return showMenu ? wideSidebar : wide;
|
||||
},
|
||||
}
|
||||
|
||||
_routeChanged: function (route) {
|
||||
_routeChanged(route) {
|
||||
if (route.path === '' && route.prefix === '/config') {
|
||||
history.replaceState(null, null, '/config/dashboard');
|
||||
this.fire('location-changed');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
customElements.define(HaPanelConfig.is, HaPanelConfig);
|
||||
</script>
|
||||
|
@ -66,4 +66,14 @@ window.hassMixins.EventsMixin = Polymer.dedupingMixin(
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/* @polymerMixin */
|
||||
window.hassMixins.NavigateMixin = Polymer.dedupingMixin(
|
||||
superClass => class extends window.hassMixins.EventsMixin(superClass) {
|
||||
navigate(path) {
|
||||
history.pushState(null, null, path);
|
||||
this.fire('location-changed');
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user