Polymer .9: foundation + login form

This commit is contained in:
Paulus Schoutsen 2015-05-16 02:24:06 -07:00
parent e0d697d0bc
commit 8d6bbb8c1a
8 changed files with 249 additions and 167 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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