Add profile badge to sidebar header (#1525)

* Add profile badge to sidebar header

* Lint

* Update ha-sidebar.js

* Address comments
This commit is contained in:
Paulus Schoutsen 2018-07-27 09:12:14 +02:00 committed by GitHub
parent 7ca7d3e12c
commit a8ce5e3e25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 129 additions and 92 deletions

View File

@ -10,12 +10,10 @@ import EventsMixin from '../mixins/events-mixin.js';
class HaMenuButton extends EventsMixin(PolymerElement) { class HaMenuButton extends EventsMixin(PolymerElement) {
static get template() { static get template() {
return html` return html`
<style> <paper-icon-button
.invisible { icon="[[_getIcon(hassio)]]"
visibility: hidden; on-click="toggleMenu"
} ></paper-icon-button>
</style>
<paper-icon-button icon="[[_getIcon(hassio)]]" class$="[[computeMenuButtonClass(narrow, showMenu)]]" on-click="toggleMenu"></paper-icon-button>
`; `;
} }
@ -38,13 +36,9 @@ class HaMenuButton extends EventsMixin(PolymerElement) {
}; };
} }
computeMenuButtonClass(narrow, showMenu) {
return !narrow && showMenu ? 'invisible' : '';
}
toggleMenu(ev) { toggleMenu(ev) {
ev.stopPropagation(); ev.stopPropagation();
this.fire('hass-open-menu'); this.fire(this.showMenu ? 'hass-close-menu' : 'hass-open-menu');
} }
_getIcon(hassio) { _getIcon(hassio) {

View File

@ -9,15 +9,12 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../components/ha-icon.js'; import '../components/ha-icon.js';
import '../util/hass-translation.js'; import '../util/hass-translation.js';
import NavigateMixin from '../mixins/navigate-mixin.js';
import LocalizeMixin from '../mixins/localize-mixin.js'; import LocalizeMixin from '../mixins/localize-mixin.js';
/* /*
* @appliesMixin LocalizeMixin * @appliesMixin LocalizeMixin
* @appliesMixin NavigateMixin
*/ */
class HaSidebar extends class HaSidebar extends LocalizeMixin(PolymerElement) {
LocalizeMixin(NavigateMixin(PolymerElement)) {
static get template() { static get template() {
return html` return html`
<style include="iron-flex iron-flex-alignment iron-positioning"> <style include="iron-flex iron-flex-alignment iron-positioning">
@ -44,21 +41,28 @@ class HaSidebar extends
background-color: var(--primary-background-color); background-color: var(--primary-background-color);
} }
app-toolbar a {
color: var(--primary-text-color);
}
paper-listbox { paper-listbox {
padding-bottom: 0; padding-bottom: 0;
} }
paper-icon-item { paper-listbox > a {
--paper-icon-item: { @apply --sidebar-text;
cursor: pointer; text-decoration: none;
};
--paper-item-icon: { --paper-item-icon: {
color: var(--sidebar-icon-color); color: var(--sidebar-icon-color);
}; };
} }
paper-icon-item.iron-selected { paper-icon-item span {
@apply --sidebar-text;
}
a.iron-selected {
--paper-icon-item: { --paper-icon-item: {
background-color: var(--sidebar-selected-background-color, var(--paper-grey-200)); background-color: var(--sidebar-selected-background-color, var(--paper-grey-200));
}; };
@ -68,11 +72,8 @@ class HaSidebar extends
}; };
} }
paper-icon-item .item-text { a.iron-selected .item-text {
@apply --sidebar-text; color: var(--sidebar-selected-text-color);
}
paper-icon-item.iron-selected .item-text {
color: var(--sidebar-selected-text-color);
} }
paper-icon-item.logout { paper-icon-item.logout {
@ -85,51 +86,70 @@ class HaSidebar extends
margin: 4px 0; margin: 4px 0;
} }
.setting {
@apply --sidebar-text;
}
.subheader { .subheader {
@apply --sidebar-text; @apply --sidebar-text;
padding: 16px; padding: 16px;
} }
.dev-tools { .dev-tools {
color: var(--sidebar-icon-color);
padding: 0 8px; padding: 0 8px;
} }
.dev-tools a {
color: var(--sidebar-icon-color);
}
.profile-badge {
/* for ripple */
position: relative;
box-sizing: border-box;
width: 40px;
line-height: 40px;
border-radius: 50%;
text-align: center;
background-color: var(--light-primary-color);
text-decoration: none;
color: var(--primary-text-color);
}
.profile-badge.long {
font-size: 80%;
}
</style> </style>
<app-toolbar> <app-toolbar>
<div main-title="">Home Assistant</div> <div main-title=>Home Assistant</div>
<paper-icon-button icon="hass:chevron-left" hidden$="[[narrow]]" on-click="toggleMenu"></paper-icon-button> <template is='dom-if' if='[[hass.user]]'>
<a href='/profile' class$='[[_computeBadgeClass(_initials)]]'>
<paper-ripple></paper-ripple>
[[_initials]]
</a>
</template>
</app-toolbar> </app-toolbar>
<paper-listbox attr-for-selected="data-panel" selected="[[hass.panelUrl]]"> <paper-listbox attr-for-selected="data-panel" selected="[[hass.panelUrl]]">
<paper-icon-item on-click="menuClicked" data-panel$="[[defaultPage]]"> <a href='[[_computeUrl(defaultPage)]]' data-panel$="[[defaultPage]]">
<ha-icon slot="item-icon" icon="hass:apps"></ha-icon> <paper-icon-item>
<span class="item-text">[[localize('panel.states')]]</span> <ha-icon slot="item-icon" icon="hass:apps"></ha-icon>
</paper-icon-item> <span class="item-text">[[localize('panel.states')]]</span>
</paper-icon-item>
</a>
<template is="dom-repeat" items="[[panels]]"> <template is="dom-repeat" items="[[panels]]">
<paper-icon-item on-click="menuClicked"> <a href='[[_computeUrl(item.url_path)]]' data-panel$='[[item.url_path]]'>
<ha-icon slot="item-icon" icon="[[item.icon]]"></ha-icon> <paper-icon-item>
<span class="item-text">[[computePanelName(localize, item)]]</span> <ha-icon slot="item-icon" icon="[[item.icon]]"></ha-icon>
</paper-icon-item> <span class="item-text">[[_computePanelName(localize, item)]]</span>
</paper-icon-item>
</a>
</template> </template>
<template is='dom-if' if='[[!hass.user]]'> <template is='dom-if' if='[[!hass.user]]'>
<paper-icon-item on-click="menuClicked" data-panel="logout" class="logout"> <paper-icon-item on-click='_handleLogOut' class="logout">
<ha-icon slot="item-icon" icon="hass:exit-to-app"></ha-icon> <ha-icon slot="item-icon" icon="hass:exit-to-app"></ha-icon>
<span class="item-text">[[localize('ui.sidebar.log_out')]]</span> <span class="item-text">[[localize('ui.sidebar.log_out')]]</span>
</paper-icon-item> </paper-icon-item>
</template> </template>
<template is='dom-if' if='[[hass.user]]'>
<paper-icon-item on-click="menuClicked" data-panel="profile">
<ha-icon slot="item-icon" icon="hass:account"></ha-icon>
<span class="item-text">[[_computeUserName(hass.user)]]</span>
</paper-icon-item>
</template>
</paper-listbox> </paper-listbox>
<div> <div>
@ -138,14 +158,54 @@ class HaSidebar extends
<div class="subheader">[[localize('ui.sidebar.developer_tools')]]</div> <div class="subheader">[[localize('ui.sidebar.developer_tools')]]</div>
<div class="dev-tools layout horizontal justified"> <div class="dev-tools layout horizontal justified">
<paper-icon-button icon="hass:remote" data-panel="dev-service" alt="[[localize('panel.dev-services')]]" title="[[localize('panel.dev-services')]]" on-click="menuClicked"></paper-icon-button> <a href="/dev-service">
<paper-icon-button icon="hass:code-tags" data-panel="dev-state" alt="[[localize('panel.dev-states')]]" title="[[localize('panel.dev-states')]]" on-click="menuClicked"></paper-icon-button> <paper-icon-button
<paper-icon-button icon="hass:radio-tower" data-panel="dev-event" alt="[[localize('panel.dev-events')]]" title="[[localize('panel.dev-events')]]" on-click="menuClicked"></paper-icon-button> icon="hass:remote"
<paper-icon-button icon="hass:file-xml" data-panel="dev-template" alt="[[localize('panel.dev-templates')]]" title="[[localize('panel.dev-templates')]]" on-click="menuClicked"></paper-icon-button> alt="[[localize('panel.dev-services')]]"
title="[[localize('panel.dev-services')]]"
></paper-icon-button>
</a>
<a href="/dev-state/">
<paper-icon-button
icon="hass:code-tags"
alt="[[localize('panel.dev-states')]]"
title="[[localize('panel.dev-states')]]"
></paper-icon-button>
</a>
<a href="/dev-event/">
<paper-icon-button
icon="hass:radio-tower"
alt="[[localize('panel.dev-events')]]"
title="[[localize('panel.dev-events')]]"
></paper-icon-button>
</a>
<a href="/dev-template/">
<paper-icon-button
icon="hass:file-xml"
alt="[[localize('panel.dev-templates')]]"
title="[[localize('panel.dev-templates')]]"
></paper-icon-button>
</a>
<template is="dom-if" if="[[_mqttLoaded(hass)]]"> <template is="dom-if" if="[[_mqttLoaded(hass)]]">
<paper-icon-button icon="hass:altimeter" data-panel="dev-mqtt" alt="[[localize('panel.dev-mqtt')]]" title="[[localize('panel.dev-mqtt')]]" on-click="menuClicked"></paper-icon-button> <a href="/dev-mqtt/">
<paper-icon-button
icon="hass:altimeter"
alt="[[localize('panel.dev-mqtt')]]"
title="[[localize('panel.dev-mqtt')]]"
></paper-icon-button>
</a>
</template> </template>
<paper-icon-button icon="hass:information-outline" data-panel="dev-info" alt="[[localize('panel.dev-info')]]" title="[[localize('panel.dev-info')]]" on-click="menuClicked"></paper-icon-button> <a href="/dev-info/">
<paper-icon-button
icon="hass:information-outline"
alt="[[localize('panel.dev-info')]]"
title="[[localize('panel.dev-info')]]"
></paper-icon-button>
</a>
</div> </div>
</div> </div>
`; `;
@ -168,9 +228,27 @@ class HaSidebar extends
computed: 'computePanels(hass)', computed: 'computePanels(hass)',
}, },
defaultPage: String, defaultPage: String,
_initials: {
type: String,
computed: '_computeUserInitials(hass.user.name)',
},
}; };
} }
_computeUserInitials(name) {
if (!name) return 'user';
return name.trim()
// Split by space and take first 3 words
.split(' ').slice(0, 3)
// Of each word, take first letter
.map(s => s.substr(0, 1))
.join('');
}
_computeBadgeClass(initials) {
return `profile-badge ${initials.length > 2 ? 'long' : ''}`;
}
_mqttLoaded(hass) { _mqttLoaded(hass) {
return hass.config.core.components.indexOf('mqtt') !== -1; return hass.config.core.components.indexOf('mqtt') !== -1;
} }
@ -179,7 +257,7 @@ class HaSidebar extends
return user && (user.name || 'Unnamed User'); return user && (user.name || 'Unnamed User');
} }
computePanelName(localize, panel) { _computePanelName(localize, panel) {
return localize(`panel.${panel.title}`) || panel.title; return localize(`panel.${panel.title}`) || panel.title;
} }
@ -222,45 +300,11 @@ class HaSidebar extends
return result; return result;
} }
menuClicked(ev) { _computeUrl(urlPath) {
// Selection made inside dom-repeat return `/${urlPath}`;
if (ev.model) {
this.selectPanel(ev.model.item.url_path);
return;
}
let target = ev.target;
let checks = 5;
let attr;
do {
attr = target.getAttribute('data-panel');
target = target.parentElement;
checks--;
} while (checks > 0 && target !== null && !attr);
if (checks > 0 && target !== null) {
this.selectPanel(attr);
}
} }
toggleMenu() { _handleLogOut() {
this.fire('hass-close-menu');
}
selectPanel(newChoice) {
if (newChoice === 'logout') {
this.handleLogOut();
return;
}
var path = '/' + newChoice;
if (path === document.location.pathname) {
return;
}
this.navigate(path);
}
handleLogOut() {
this.fire('hass-logout'); this.fire('hass-logout');
} }
} }

View File

@ -40,7 +40,6 @@ class HaChangePasswordCard extends PolymerElement {
<div class="status">[[_statusMsg]]</div> <div class="status">[[_statusMsg]]</div>
</template> </template>
<paper-input <paper-input
autofocus
class='currentPassword' class='currentPassword'
label='Current Password' label='Current Password'
type='password' type='password'