Change how sidebar behaves

This commit is contained in:
Paulus Schoutsen 2015-08-29 18:15:58 -07:00
parent 28d1be0cf8
commit c3b9a55d68
24 changed files with 181 additions and 70 deletions

View File

@ -35,7 +35,8 @@
"google-apis": "GoogleWebComponents/google-apis#0.8-preview",
"layout": "Polymer/layout",
"paper-styles": "polymerelements/paper-styles#^1.0.11",
"pikaday": "~1.3.2"
"pikaday": "~1.3.3",
"iron-media-query": "polymerelements/iron-media-query#~1.0.2"
},
"resolutions": {
"polymer": "^1.0.0",

View File

@ -16,7 +16,7 @@
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
"license": "MIT",
"dependencies": {
"home-assistant-js": "git+https://github.com/balloob/home-assistant-js.git#979f600b1b2424550f0c7badb7d78d60a7341948",
"home-assistant-js": "git+https://github.com/balloob/home-assistant-js.git#9ed05c6a05cff59cb35e265d2acdab4e99783c3a",
"lodash": "^3.10.1",
"moment": "^2.10.6"
},

View File

@ -13,32 +13,33 @@
<dom-module id='ha-sidebar'>
<style>
.sidenav {
background: #fafafa;
box-shadow: 1px 0 1px rgba(0, 0, 0, 0.1);
overflow: hidden;
white-space: nowrap;
-ms-user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
}
paper-toolbar {
--paper-toolbar-background: #fff;
--paper-toolbar-color: #000;
}
div.title {
text-align: left;
}
div.menu {
color: var(--secondary-text-color);
background-color: #fafafa;
margin-top: 8px;
}
paper-icon-item {
cursor: pointer;
font-weight: 500;
}
paper-icon-item.selected {
font-weight: bold;
color: var(--default-primary-color);
background-color: #f0f0f0;
}
paper-icon-item.logout {
@ -52,6 +53,7 @@
.text {
padding: 16px;
font-size: 14px;
font-weight: 500;
}
.dev-tools {
@ -63,7 +65,7 @@
<paper-header-panel mode='scroll' class='sidenav fit'>
<paper-toolbar>
<!-- forces paper toolbar to style title appropriate -->
<paper-icon-button hidden></paper-icon-button>
<paper-icon-button icon='menu' hidden$='[[!narrow]]' on-tap='toggleMenu'></paper-icon-button>
<div class="title">Home Assistant</div>
</paper-toolbar>
<div class='menu'>

View File

@ -16,6 +16,10 @@ export default new Polymer({
behaviors: [nuclearObserver],
properties: {
menuShown: {
type: Boolean,
},
menuSelected: {
type: String,
},
@ -70,6 +74,10 @@ export default new Polymer({
this.menuClicked(ev);
},
toggleMenu() {
this.fire('close-menu');
},
selectPanel(newChoice) {
if (newChoice === this.selected) {
return;

View File

@ -6,14 +6,14 @@ require('../cards/ha-domain-card');
require('../cards/ha-introduction-card');
const PRIORITY = {
configurator: -20,
group: -10,
a: -1,
sun: 0,
device_tracker: 1,
sensor: 2,
scene: 3,
script: 4,
configurator: 10,
group: 20,
thermostat: 40,
media_player: 50,
camera: 60,
@ -23,8 +23,8 @@ function getPriority(domain) {
return (domain in PRIORITY) ? PRIORITY[domain] : 30;
}
function entityDomainMap(entityMap) {
return entityMap.groupBy(entity => entity.domain);
function entitySortBy(entity) {
return entity.entityDisplay.toLowerCase();
}
export default new Polymer({
@ -47,12 +47,12 @@ export default new Polymer({
cards: {
type: Object,
computed: 'computeDomains(columns, states)',
computed: 'computeDomains(columns, states, showIntroduction)',
},
},
computeDomains(columns, states) {
const byDomain = entityDomainMap(states);
computeDomains(columns, states, showIntroduction) {
const byDomain = states.groupBy(entity => entity.domain);
const hasGroup = {};
const cards = {
@ -62,38 +62,51 @@ export default new Polymer({
};
for (let i = 0; i < columns; i++) { cards._columns[i] = []; }
function filterGrouped(entities) {
return entities.filter(entity => !(entity.entityId in hasGroup));
}
let index = 0;
function pushCard(name, entities, filterGrouped = true) {
const filtered = filterGrouped ?
entities.filter(entity => !(entity.entityId in hasGroup)) :
entities;
if (filtered.length === 0) {
function increaseIndex() {
const old = index;
index = (index + 1) % columns;
return old;
}
if (showIntroduction) {
increaseIndex();
}
function pushCard(name, entities) {
if (entities.length === 0) {
return;
}
cards._columns[index].push(name);
index = (index + 1) % columns;
cards[name] = filtered;
cards._columns[increaseIndex()].push(name);
cards[name] = entities;
}
byDomain.keySeq().sortBy(domain => getPriority(domain))
.forEach(domain => {
if (domain === 'a') {
cards._demo = true;
} else if (getPriority(domain) < 10) {
return;
}
const priority = getPriority(domain);
if (priority >= 0 && priority < 10) {
cards._badges.push.apply(
cards._badges, byDomain.get(domain).sortBy(
entity => entity.entityDisplay).toArray());
cards._badges, filterGrouped(byDomain.get(domain)).sortBy(
entitySortBy).toArray());
} else if (domain === 'group') {
byDomain.get(domain).filter(st => !st.attributes.auto)
byDomain.get(domain).filter(st => !st.attributes.auto).sortBy(entitySortBy)
.forEach(groupState => {
const entities = util.expandGroup(groupState, states);
entities.forEach(entity => hasGroup[entity.entityId] = true);
pushCard(groupState.entityDisplay, entities.toArray(), false);
pushCard(groupState.entityDisplay, entities.toArray());
}
);
} else {
pushCard(domain, byDomain.get(domain).sortBy(
entity => entity.entityDisplay).toArray());
pushCard(domain, filterGrouped(byDomain.get(domain)).sortBy(entitySortBy).toArray());
}
}
);

View File

@ -3,11 +3,12 @@
<link rel='import' href='../bower_components/paper-styles/typography.html'>
<link rel='import' href='resources/home-assistant-icons.html'>
<link rel='import' href='resources/home-assistant-style.html'>
<link rel='import' href='layouts/login-form.html'>
<link rel='import' href='layouts/home-assistant-main.html'>
<link rel='import' href='resources/home-assistant-style.html'>
<dom-module id='home-assistant'>
<style>
:host {

View File

@ -1,9 +1,11 @@
import Polymer from './polymer';
import {
syncGetters,
localStoragePreferences,
startLocalStoragePreferencesSync
navigationActions,
reactor,
startLocalStoragePreferencesSync,
syncGetters
} from './util/home-assistant-js-instance';
import nuclearObserver from './util/bound-nuclear-behavior';
@ -32,17 +34,20 @@ export default new Polymer({
},
ready() {
reactor.batch(() => {
// if auth was given, tell the backend
if (this.auth) {
validateAuth(this.auth, false);
} else if (localStoragePreferences.authToken) {
validateAuth(localStoragePreferences.authToken, true);
}
navigationActions.showSidebar(localStoragePreferences.showSidebar);
});
startLocalStoragePreferencesSync();
// remove the HTML init message
const initMsg = document.getElementById('init');
initMsg.parentElement.removeChild(initMsg);
// if auth was given, tell the backend
if (this.auth) {
validateAuth(this.auth, false);
} else if (localStoragePreferences.authToken) {
validateAuth(localStoragePreferences.authToken, true);
}
startLocalStoragePreferencesSync();
},
});

View File

@ -1,7 +1,7 @@
<link rel='import' href='../../bower_components/polymer/polymer.html'>
<link rel='import' href='../../bower_components/layout/layout.html'>
<link rel='import' href='../../bower_components/paper-drawer-panel/paper-drawer-panel.html'>
<link rel='import' href='../../bower_components/iron-media-query/iron-media-query.html'>
<link rel='import' href='../layouts/partial-zone.html'>
<link rel='import' href='../layouts/partial-logbook.html'>
<link rel='import' href='../layouts/partial-history.html'>
@ -17,27 +17,29 @@
<template>
<notification-manager></notification-manager>
<more-info-dialog></more-info-dialog>
<iron-media-query query="(max-width: 600px)" query-matches="{{narrow}}">
</iron-media-query>
<paper-drawer-panel id='drawer' narrow='{{narrow}}'>
<paper-drawer-panel id='drawer' force-narrow='[[computeForceNarrow(narrow, showSidebar)]]'>
<ha-sidebar drawer></ha-sidebar>
<template is='dom-if' if='[[isSelectedStates]]'>
<partial-zone main narrow='[[narrow]]'></partial-zone>
<partial-zone main narrow='[[narrow]]' show-menu='[[showSidebar]]'></partial-zone>
</template>
<template is='dom-if' if='[[isSelectedLogbook]]'>
<partial-logbook main narrow='[[narrow]]'></partial-logbook>
<partial-logbook main narrow='[[narrow]]' show-menu='[[showSidebar]]'></partial-logbook>
</template>
<template is='dom-if' if='[[isSelectedHistory]]'>
<partial-history main narrow='[[narrow]]'></partial-history>
<partial-history main narrow='[[narrow]]' show-menu='[[showSidebar]]'></partial-history>
</template>
<template is='dom-if' if='[[isSelectedDevService]]'>
<partial-dev-call-service main narrow='[[narrow]]'></partial-dev-call-service>
<partial-dev-call-service main narrow='[[narrow]]' show-menu='[[showSidebar]]'></partial-dev-call-service>
</template>
<template is='dom-if' if='[[isSelectedDevEvent]]'>
<partial-dev-fire-event main narrow='[[narrow]]'></partial-dev-fire-event>
<partial-dev-fire-event main narrow='[[narrow]]' show-menu='[[showSidebar]]'></partial-dev-fire-event>
</template>
<template is='dom-if' if='[[isSelectedDevState]]'>
<partial-dev-set-state main narrow='[[narrow]]'></partial-dev-set-state>
<partial-dev-set-state main narrow='[[narrow]]' show-menu='[[showSidebar]]'></partial-dev-set-state>
</template>
</paper-drawer-panel>

View File

@ -1,4 +1,5 @@
import {
navigationActions,
navigationGetters,
startUrlSync,
stopUrlSync,
@ -24,6 +25,7 @@ export default new Polymer({
properties: {
narrow: {
type: Boolean,
value: false,
},
activePane: {
@ -61,24 +63,47 @@ export default new Polymer({
type: Boolean,
bindNuclear: navigationGetters.isActivePane('devService'),
},
showSidebar: {
type: Boolean,
bindNuclear: navigationGetters.showSidebar,
},
},
listeners: {
'open-menu': 'openDrawer',
'open-menu': 'openMenu',
'close-menu': 'closeMenu',
},
openDrawer() {
this.$.drawer.openDrawer();
openMenu() {
if (this.narrow) {
this.$.drawer.openDrawer();
} else {
navigationActions.showSidebar(true);
}
},
closeMenu() {
this.$.drawer.closeDrawer();
if (this.showSidebar) {
navigationActions.showSidebar(false);
}
},
activePaneChanged() {
this.$.drawer.closeDrawer();
if (this.narrow) {
this.$.drawer.closeDrawer();
}
},
attached() {
startUrlSync();
},
computeForceNarrow(narrow, showSidebar) {
return narrow || !showSidebar;
},
detached() {
stopUrlSync();
},

View File

@ -12,15 +12,11 @@
-webkit-user-select: none;
-moz-user-select: none;
}
.title {
text-align: left;
}
</style>
<template>
<paper-scroll-header-panel class='fit'>
<paper-toolbar>
<paper-icon-button icon='menu' hidden$='[[!narrow]]' on-click='toggleMenu'></paper-icon-button>
<paper-icon-button icon='menu' class$='[[computeMenuButtonClass(narrow, showMenu)]]' on-tap='toggleMenu'></paper-icon-button>
<div class="title">
<content select='[header-title]'></content>
</div>

View File

@ -8,6 +8,15 @@ export default new Polymer({
type: Boolean,
value: false,
},
showMenu: {
type: Boolean,
value: false,
},
},
computeMenuButtonClass(narrow, showMenu) {
return !narrow && showMenu ? 'invisible' : '';
},
toggleMenu() {

View File

@ -20,7 +20,7 @@
}
</style>
<template>
<partial-base narrow="[[narrow]]">
<partial-base narrow="[[narrow]]" show-menu='[[showMenu]]'>
<span header-title>Call Service</span>
<div class='form fit'>

View File

@ -14,6 +14,11 @@ export default new Polymer({
value: false,
},
showMenu: {
type: Boolean,
value: false,
},
domain: {
type: String,
value: '',

View File

@ -21,7 +21,7 @@
</style>
<template>
<partial-base narrow="{{narrow}}">
<partial-base narrow="{{narrow}}" show-menu='[[showMenu]]'>
<span header-title>Fire Event</span>
<div class='form fit'>

View File

@ -9,6 +9,16 @@ export default new Polymer({
is: 'partial-dev-fire-event',
properties: {
narrow: {
type: Boolean,
value: false,
},
showMenu: {
type: Boolean,
value: false,
},
eventType: {
type: String,
value: '',

View File

@ -21,7 +21,7 @@
</style>
<template>
<partial-base narrow="[[narrow]]">
<partial-base narrow="[[narrow]]" show-menu='[[showMenu]]'>
<span header-title>Set State</span>
<div class='form fit'>

View File

@ -9,6 +9,16 @@ export default new Polymer({
is: 'partial-dev-set-state',
properties: {
narrow: {
type: Boolean,
value: false,
},
showMenu: {
type: Boolean,
value: false,
},
entityId: {
type: String,
value: '',

View File

@ -27,7 +27,7 @@
}
</style>
<template>
<partial-base narrow="[[narrow]]">
<partial-base narrow="[[narrow]]" show-menu='[[showMenu]]'>
<span header-title>History</span>
<paper-icon-button icon="refresh" header-buttons

View File

@ -19,6 +19,11 @@ export default new Polymer({
type: Boolean,
},
showMenu: {
type: Boolean,
value: false,
},
isDataLoaded: {
type: Boolean,
bindNuclear: entityHistoryGetters.hasDataForCurrentDate,

View File

@ -21,7 +21,7 @@
}
</style>
<template>
<partial-base narrow="[[narrow]]">
<partial-base narrow="[[narrow]]" show-menu='[[showMenu]]'>
<span header-title>Logbook</span>
<paper-icon-button icon="refresh" header-buttons

View File

@ -18,6 +18,11 @@ export default new Polymer({
value: false,
},
showMenu: {
type: Boolean,
value: false,
},
selectedDate: {
type: String,
bindNuclear: logbookGetters.currentDate,

View File

@ -31,8 +31,8 @@
<template>
<paper-header-panel mode="waterfall">
<paper-toolbar>
<paper-icon-button icon='menu' hidden$='[[!narrow]]' on-tap='toggleMenu'></paper-icon-button>
<div class='title'>States</div>
<paper-icon-button icon='menu' class$='[[computeMenuButtonClass(narrow, showMenu)]]' on-tap='toggleMenu'></paper-icon-button>
<div class='title'>[[locationName]]</div>
<paper-icon-button
icon="refresh"

View File

@ -64,6 +64,16 @@ export default new Polymer({
bindNuclear: configGetters.isComponentLoaded('introduction'),
},
locationName: {
type: String,
bindNuclear: configGetters.locationName,
},
showMenu: {
type: Boolean,
value: false,
},
states: {
type: Object,
bindNuclear: entityGetters.visibleEntityMap,
@ -115,6 +125,10 @@ export default new Polymer({
return states.keySeq().toArray();
},
computeMenuButtonClass(narrow, showMenu) {
return !narrow && showMenu ? 'invisible' : '';
},
computeStatesOfDomain(states, domain) {
return states.get(domain).toArray();
},

View File

@ -43,7 +43,7 @@
}
}
body /deep/ .ha-spin {
.ha-spin {
-webkit-animation: ha-spin 2s infinite linear;
animation: ha-spin 2s infinite linear;
}