mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 01:08:12 +00:00
Polymer .9: foundation + login form
This commit is contained in:
parent
e0d697d0bc
commit
8d6bbb8c1a
@ -11,37 +11,40 @@
|
||||
"bower_components"
|
||||
],
|
||||
"dependencies": {
|
||||
"webcomponentsjs": "Polymer/webcomponentsjs#~0.6",
|
||||
"font-roboto": "Polymer/font-roboto#~0.5.5",
|
||||
"core-header-panel": "polymer/core-header-panel#~0.5.5",
|
||||
"core-toolbar": "polymer/core-toolbar#~0.5.5",
|
||||
"core-tooltip": "Polymer/core-tooltip#~0.5.5",
|
||||
"core-menu": "polymer/core-menu#~0.5.5",
|
||||
"core-item": "Polymer/core-item#~0.5.5",
|
||||
"core-input": "Polymer/core-input#~0.5.5",
|
||||
"core-icons": "polymer/core-icons#~0.5.5",
|
||||
"core-image": "polymer/core-image#~0.5.5",
|
||||
"core-style": "polymer/core-style#~0.5.5",
|
||||
"core-label": "polymer/core-label#~0.5.5",
|
||||
"paper-toast": "Polymer/paper-toast#~0.5.5",
|
||||
"paper-dialog": "Polymer/paper-dialog#~0.5.5",
|
||||
"paper-spinner": "Polymer/paper-spinner#~0.5.5",
|
||||
"paper-button": "Polymer/paper-button#~0.5.5",
|
||||
"paper-input": "Polymer/paper-input#~0.5.5",
|
||||
"paper-toggle-button": "polymer/paper-toggle-button#~0.5.5",
|
||||
"paper-icon-button": "polymer/paper-icon-button#~0.5.5",
|
||||
"paper-menu-button": "polymer/paper-menu-button#~0.5.5",
|
||||
"paper-dropdown": "polymer/paper-dropdown#~0.5.5",
|
||||
"paper-item": "polymer/paper-item#~0.5.5",
|
||||
"paper-slider": "polymer/paper-slider#~0.5.5",
|
||||
"paper-checkbox": "polymer/paper-checkbox#~0.5.5",
|
||||
"webcomponentsjs": "Polymer/webcomponentsjs#~0.7",
|
||||
"font-roboto": "Polymer/font-roboto#~0.5.6",
|
||||
"paper-header-panel": "PolymerElements/paper-header-panel#~0.9",
|
||||
"paper-toolbar": "PolymerElements/paper-toolbar#~0.9",
|
||||
"paper-menu": "PolymerElements/paper-menu#~0.9",
|
||||
"iron-input": "PolymerElements/iron-input#~0.9",
|
||||
"iron-icons": "PolymerElements/iron-icons#~0.9",
|
||||
"iron-image": "PolymerElements/iron-image#~0.9",
|
||||
"paper-toast": "PolymerElements/paper-toast#~0.9",
|
||||
"paper-dialog": "PolymerElements/paper-dialog#~0.9",
|
||||
"paper-spinner": "PolymerElements/paper-spinner#~0.9",
|
||||
"paper-button": "PolymerElements/paper-button#~0.9",
|
||||
"paper-input": "PolymerElements/paper-input#~0.9",
|
||||
"paper-toggle-button": "PolymerElements/paper-toggle-button#~0.9",
|
||||
"paper-icon-button": "PolymerElements/paper-icon-button#~0.9",
|
||||
"paper-item": "PolymerElements/paper-item#~0.9",
|
||||
"paper-slider": "PolymerElements/paper-slider#~0.9",
|
||||
"paper-checkbox": "PolymerElements/paper-checkbox#~0.9",
|
||||
"paper-drawer-panel": "PolymerElements/paper-drawer-panel#~0.9",
|
||||
"moment": "~2.10.3",
|
||||
"layout": "Polymer/layout"
|
||||
},
|
||||
"stillUpgrading": {
|
||||
"core-tooltip": "Polymer/core-tooltip#~0.9",
|
||||
"core-item": "Polymer/core-item#~0.9",
|
||||
"core-style": "polymer/core-style#~0.9",
|
||||
"core-label": "polymer/core-label#~0.9",
|
||||
"paper-dropdown": "PolymerElements/paper-dropdown#~0.9",
|
||||
"color-picker-element": "~0.0.2",
|
||||
"google-apis": "GoogleWebComponents/google-apis#~0.4.4",
|
||||
"core-drawer-panel": "polymer/core-drawer-panel#~0.5.5",
|
||||
"core-scroll-header-panel": "polymer/core-scroll-header-panel#~0.5.5",
|
||||
"moment": "~2.10.2"
|
||||
"core-scroll-header-panel": "polymer/core-scroll-header-panel#~0.9",
|
||||
"paper-menu-button": "PolymerElements/paper-menu-button#~0.9"
|
||||
},
|
||||
"resolutions": {
|
||||
"webcomponentsjs": "~0.6"
|
||||
"polymer": "^0.9.0"
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 69ee1c49af12caf00655c66d56474b5c1bcac1c1
|
||||
Subproject commit dd4cefc7af348dd9a9cfbc99094b73a7ed128621
|
@ -3,45 +3,61 @@
|
||||
|
||||
<link rel="import" href="resources/home-assistant-style.html">
|
||||
<link rel="import" href="resources/home-assistant-js.html">
|
||||
<link rel="import" href="resources/store-listener-behavior.html">
|
||||
|
||||
<link rel="import" href="layouts/login-form.html">
|
||||
<link rel="import" href="layouts/home-assistant-main.html">
|
||||
<!-- <link rel="import" href="layouts/home-assistant-main.html"> -->
|
||||
|
||||
<dom-module id="home-assistant">
|
||||
|
||||
<style>
|
||||
:host {
|
||||
font-family: RobotoDraft, 'Helvetica Neue', Helvetica, Arial;
|
||||
font-weight: 300;
|
||||
}
|
||||
</style>
|
||||
|
||||
<polymer-element name="home-assistant" attributes="auth">
|
||||
<template>
|
||||
<style>
|
||||
|
||||
:host {
|
||||
font-family: RobotoDraft, 'Helvetica Neue', Helvetica, Arial;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<home-assistant-api auth="{{auth}}"></home-assistant-api>
|
||||
|
||||
<template if="{{!loaded}}">
|
||||
<template is="dom-if" if="[[!loaded]]">
|
||||
<login-form></login-form>
|
||||
</template>
|
||||
|
||||
<template if="{{loaded}}">
|
||||
<home-assistant-main></home-assistant-main>
|
||||
<!-- <home-assistant-main></home-assistant-main> -->
|
||||
<template is="dom-if" if="[[loaded]]">
|
||||
Hello HA
|
||||
</template>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
|
||||
var storeListenerMixIn = window.hass.storeListenerMixIn,
|
||||
uiActions = window.hass.uiActions,
|
||||
preferenceStore = window.hass.preferenceStore;
|
||||
|
||||
Polymer(Polymer.mixin({
|
||||
loaded: false,
|
||||
Polymer({
|
||||
is: 'home-assistant',
|
||||
|
||||
hostAttributes: {
|
||||
auth: null,
|
||||
},
|
||||
|
||||
behaviors: [StoreListenerBehavior],
|
||||
|
||||
properties: {
|
||||
loaded: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
|
||||
ready: function() {
|
||||
// remove the HTML init message
|
||||
document.getElementById('init').remove();
|
||||
|
||||
// if auth was given, tell the backend
|
||||
// if auth was given, tell the backend
|
||||
if(this.auth) {
|
||||
uiActions.validateAuth(this.auth, false);
|
||||
} else if (preferenceStore.hasAuthToken) {
|
||||
@ -49,17 +65,10 @@
|
||||
}
|
||||
},
|
||||
|
||||
attached: function() {
|
||||
this.listenToStores(true);
|
||||
},
|
||||
|
||||
detached: function() {
|
||||
this.stopListeningToStores();
|
||||
},
|
||||
|
||||
syncStoreChanged: function(syncStore) {
|
||||
this.loaded = syncStore.initialLoadDone;
|
||||
},
|
||||
}, storeListenerMixIn));
|
||||
</script>
|
||||
</polymer-element>
|
||||
});
|
||||
|
||||
})();
|
||||
</script>
|
||||
|
@ -1,79 +1,80 @@
|
||||
<link rel="import" href="../bower_components/polymer/polymer.html">
|
||||
|
||||
<link rel="import" href="../bower_components/core-label/core-label.html">
|
||||
<link rel="import" href="../bower_components/layout/layout.html">
|
||||
|
||||
<!-- WIP <link rel="import" href="../bower_components/core-label/core-label.html"> -->
|
||||
<link rel="import" href="../bower_components/paper-checkbox/paper-checkbox.html">
|
||||
<link rel="import" href="../bower_components/paper-button/paper-button.html">
|
||||
<link rel="import" href="../bower_components/paper-input/paper-input-decorator.html">
|
||||
<link rel="import" href="../bower_components/core-input/core-input.html">
|
||||
<link rel="import" href="../bower_components/paper-input/paper-input-container.html">
|
||||
<link rel="import" href="../bower_components/paper-input/paper-input-error.html">
|
||||
<link rel="import" href="../bower_components/iron-input/iron-input.html">
|
||||
<link rel="import" href="../bower_components/paper-spinner/paper-spinner.html">
|
||||
|
||||
<polymer-element name="login-form">
|
||||
<link rel="import" href="../resources/store-listener-behavior.html">
|
||||
|
||||
<dom-module id="login-form">
|
||||
<style>
|
||||
#passwordDecorator {
|
||||
display: block;
|
||||
height: 57px;
|
||||
}
|
||||
|
||||
paper-checkbox {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
paper-checkbox::shadow #checkbox.checked {
|
||||
background-color: #03a9f4;
|
||||
border-color: #03a9f4;
|
||||
}
|
||||
|
||||
paper-checkbox::shadow #ink[checked] {
|
||||
color: #03a9f4;
|
||||
}
|
||||
|
||||
paper-button {
|
||||
margin-left: 72px;
|
||||
}
|
||||
|
||||
.interact {
|
||||
height: 125px;
|
||||
}
|
||||
|
||||
#validatebox {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.validatemessage {
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<style>
|
||||
#passwordDecorator {
|
||||
display: block;
|
||||
height: 57px;
|
||||
}
|
||||
|
||||
paper-checkbox {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
paper-checkbox::shadow #checkbox.checked {
|
||||
background-color: #03a9f4;
|
||||
border-color: #03a9f4;
|
||||
}
|
||||
|
||||
paper-checkbox::shadow #ink[checked] {
|
||||
color: #03a9f4;
|
||||
}
|
||||
|
||||
paper-button {
|
||||
margin-left: 72px;
|
||||
}
|
||||
|
||||
.interact {
|
||||
height: 125px;
|
||||
}
|
||||
|
||||
#validatebox {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.validatemessage {
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div layout horizontal center fit class='login' id="splash">
|
||||
<div layout vertical center flex>
|
||||
<div class="layout horizontal center fit login" id="splash">
|
||||
<div class="layout vertical center flex">
|
||||
|
||||
<img src="/static/favicon-192x192.png" />
|
||||
<h1>Home Assistant</h1>
|
||||
|
||||
<a href="#" id="hideKeyboardOnFocus"></a>
|
||||
|
||||
<div class='interact' layout vertical>
|
||||
<div class='interact'>
|
||||
<div id='loginform' hidden$="[[isValidating]]">
|
||||
<paper-input-container id="passwordDecorator" invalid="[[isInvalid]]">
|
||||
<label>Password</label>
|
||||
<input is="iron-input" type="password" id="passwordInput" />
|
||||
<paper-input-error invalid="[[isInvalid]]">[[errorMessage]]</paper-input-error>
|
||||
</paper-input-container>
|
||||
|
||||
<div id='loginform' hidden?="{{isValidating || isLoggedIn}}">
|
||||
<paper-input-decorator label="Password" id="passwordDecorator">
|
||||
<input is="core-input" type="password" id="passwordInput"
|
||||
value="{{authToken}}" on-keyup="{{passwordKeyup}}">
|
||||
</paper-input-decorator>
|
||||
|
||||
<div horizontal center layout>
|
||||
<core-label horizontal layout>
|
||||
<paper-checkbox for checked={{rememberLogin}}></paper-checkbox>
|
||||
Remember
|
||||
</core-label>
|
||||
|
||||
<paper-button on-click={{validatePassword}}>Log In</paper-button>
|
||||
<div class="layout horizontal center">
|
||||
<paper-checkbox for id='rememberLogin'>Remember</paper-checkbox>
|
||||
<paper-button id='loginButton'>Log In</paper-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="validatebox" hidden?="{{!(isValidating || isLoggedIn)}}">
|
||||
<div id="validatebox" hidden$="[[!isValidating]]">
|
||||
<paper-spinner active="true"></paper-spinner><br />
|
||||
<div class="validatemessage">{{spinnerMessage}}</div>
|
||||
<div class="validatemessage">Loading data…</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -81,43 +82,53 @@
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
var storeListenerMixIn = window.hass.storeListenerMixIn;
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var uiActions = window.hass.uiActions;
|
||||
|
||||
Polymer(Polymer.mixin({
|
||||
MSG_VALIDATING: "Validating password…",
|
||||
MSG_LOADING_DATA: "Loading data…",
|
||||
Polymer({
|
||||
is: 'login-form',
|
||||
|
||||
authToken: "",
|
||||
rememberLogin: false,
|
||||
behaviors: [StoreListenerBehavior],
|
||||
|
||||
isValidating: false,
|
||||
isLoggedIn: false,
|
||||
properties: {
|
||||
isValidating: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
spinnerMessage: "",
|
||||
isInvalid: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
errorMessage: {
|
||||
type: String,
|
||||
value: '',
|
||||
}
|
||||
},
|
||||
|
||||
listeners: {
|
||||
'passwordInput.keydown': 'passwordKeyDown',
|
||||
'loginButton.click': 'validatePassword',
|
||||
},
|
||||
|
||||
attached: function() {
|
||||
this.focusPassword();
|
||||
this.listenToStores(true);
|
||||
},
|
||||
|
||||
detached: function() {
|
||||
this.stopListeningToStores();
|
||||
},
|
||||
|
||||
authStoreChanged: function(authStore) {
|
||||
this.isValidating = authStore.isValidating;
|
||||
this.isLoggedIn = authStore.isLoggedIn;
|
||||
this.spinnerMessage = this.isValidating ? this.MSG_VALIDATING : this.MSG_LOADING_DATA;
|
||||
|
||||
if (authStore.lastAttemptInvalid) {
|
||||
this.$.passwordDecorator.error = authStore.lastAttemptMessage;
|
||||
this.$.passwordDecorator.isInvalid = true;
|
||||
this.errorMessage = authStore.lastAttemptMessage;
|
||||
this.isInvalid = true;
|
||||
}
|
||||
|
||||
if (!(this.isValidating && this.isLoggedIn)) {
|
||||
this.job('focusPasswordBox', this.focusPassword.bind(this));
|
||||
if (!this.isValidating) {
|
||||
setTimeout(this.focusPassword.bind(this), 0);
|
||||
}
|
||||
},
|
||||
|
||||
@ -125,23 +136,25 @@
|
||||
this.$.passwordInput.focus();
|
||||
},
|
||||
|
||||
passwordKeyup: function(ev) {
|
||||
passwordKeyDown: function(ev) {
|
||||
// validate on enter
|
||||
if(ev.keyCode === 13) {
|
||||
this.validatePassword();
|
||||
ev.preventDefault();
|
||||
|
||||
// clear error after we start typing again
|
||||
} else if(this.$.passwordDecorator.isInvalid) {
|
||||
this.$.passwordDecorator.isInvalid = false;
|
||||
} else if(this.isInvalid) {
|
||||
this.isInvalid = false;
|
||||
}
|
||||
},
|
||||
|
||||
validatePassword: function() {
|
||||
this.$.hideKeyboardOnFocus.focus();
|
||||
|
||||
uiActions.validateAuth(this.authToken, this.rememberLogin);
|
||||
uiActions.validateAuth(this.$.passwordInput.value, this.$.rememberLogin.checked);
|
||||
},
|
||||
}, storeListenerMixIn));
|
||||
</script>
|
||||
</polymer-element>
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
|
@ -12,24 +12,16 @@
|
||||
// how to render the card for this state
|
||||
cardType: {
|
||||
get: function() {
|
||||
if(DOMAINS_WITH_CARD.indexOf(this.domain) !== -1) {
|
||||
return this.domain;
|
||||
} else if(this.canToggle) {
|
||||
return "toggle";
|
||||
} else {
|
||||
return "display";
|
||||
}
|
||||
console.warning('Deprecated method. Please use hass.uiUtil.stateCardType');
|
||||
return window.hass.uiUtil.stateCardType(this);
|
||||
}
|
||||
},
|
||||
|
||||
// how to render the more info of this state
|
||||
moreInfoType: {
|
||||
get: function() {
|
||||
if(DOMAINS_WITH_MORE_INFO.indexOf(this.domain) !== -1) {
|
||||
return this.domain;
|
||||
} else {
|
||||
return 'default';
|
||||
}
|
||||
console.warning('Deprecated method. Please use hass.uiUtil.stateMoreInfoType');
|
||||
return window.hass.uiUtil.stateMoreInfoType(this);
|
||||
}
|
||||
},
|
||||
});
|
||||
@ -66,7 +58,25 @@
|
||||
};
|
||||
|
||||
// UI specific util methods
|
||||
window.hass.uiUtil = {};
|
||||
window.hass.uiUtil = {
|
||||
stateCardType: function(state) {
|
||||
if(DOMAINS_WITH_CARD.indexOf(state.domain) !== -1) {
|
||||
return state.domain;
|
||||
} else if(state.canToggle) {
|
||||
return "toggle";
|
||||
} else {
|
||||
return "display";
|
||||
}
|
||||
},
|
||||
|
||||
stateMoreInfoType: function(state) {
|
||||
if(DOMAINS_WITH_MORE_INFO.indexOf(state.domain) !== -1) {
|
||||
return state.domain;
|
||||
} else {
|
||||
return 'default';
|
||||
}
|
||||
},
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
@ -1,4 +1,34 @@
|
||||
<link rel="import" href="../bower_components/core-style/core-style.html">
|
||||
<!-- <link rel="import" href="../bower_components/core-style/core-style.html"> -->
|
||||
|
||||
<link rel="import" href="../bower_components/polymer/polymer.html">
|
||||
|
||||
<style is="custom-style">
|
||||
|
||||
* {
|
||||
|
||||
--dark-primary-color: #0288D1;
|
||||
|
||||
--default-primary-color: #03A9F4;
|
||||
|
||||
--light-primary-color: #B3E5FC;
|
||||
|
||||
--text-primary-color: #ffffff;
|
||||
|
||||
--accent-color: #FF9800;
|
||||
|
||||
--primary-background-color: #ffffff;
|
||||
|
||||
--primary-text-color: #212121;
|
||||
|
||||
--secondary-text-color: #727272;
|
||||
|
||||
--disabled-text-color: #bdbdbd;
|
||||
|
||||
--divider-color: #B6B6B6;
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<core-style id='ha-main'>
|
||||
/* Palette generated by Material Palette - materialpalette.com/light-blue/orange */
|
||||
@ -53,11 +83,11 @@ a {
|
||||
}
|
||||
</core-style>
|
||||
<core-style id="ha-headers">
|
||||
core-scroll-header-panel, core-header-panel {
|
||||
core-scroll-header-panel, paper-header-panel {
|
||||
background-color: #E5E5E5;
|
||||
}
|
||||
|
||||
core-toolbar {
|
||||
paper-toolbar {
|
||||
background: #03a9f4;
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
|
@ -17,8 +17,4 @@ window.hass.uiUtil.formatDate = function(dateObj) {
|
||||
return moment(dateObj).format('ll');
|
||||
};
|
||||
|
||||
PolymerExpressions.prototype.formatTime = window.hass.uiUtil.formatTime;
|
||||
PolymerExpressions.prototype.formatDateTime = window.hass.uiUtil.formatDateTime;
|
||||
PolymerExpressions.prototype.formatDate = window.hass.uiUtil.formatDate;
|
||||
|
||||
</script>
|
||||
|
@ -0,0 +1,21 @@
|
||||
<script>
|
||||
|
||||
(function() {
|
||||
|
||||
var StoreListenerMixIn = window.hass.storeListenerMixIn;
|
||||
|
||||
window.StoreListenerBehavior = {
|
||||
|
||||
attached: function() {
|
||||
StoreListenerMixIn.listenToStores(true, this);
|
||||
},
|
||||
|
||||
detached: function() {
|
||||
StoreListenerMixIn.stopListeningToStores(this);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
</script>
|
Loading…
x
Reference in New Issue
Block a user