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", "google-apis": "GoogleWebComponents/google-apis#0.8-preview",
"layout": "Polymer/layout", "layout": "Polymer/layout",
"paper-styles": "polymerelements/paper-styles#^1.0.11", "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": { "resolutions": {
"polymer": "^1.0.0", "polymer": "^1.0.0",

View File

@ -16,7 +16,7 @@
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)", "author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
"license": "MIT", "license": "MIT",
"dependencies": { "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", "lodash": "^3.10.1",
"moment": "^2.10.6" "moment": "^2.10.6"
}, },

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
<link rel='import' href='../../bower_components/polymer/polymer.html'> <link rel='import' href='../../bower_components/polymer/polymer.html'>
<link rel='import' href='../../bower_components/layout/layout.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/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-zone.html'>
<link rel='import' href='../layouts/partial-logbook.html'> <link rel='import' href='../layouts/partial-logbook.html'>
<link rel='import' href='../layouts/partial-history.html'> <link rel='import' href='../layouts/partial-history.html'>
@ -17,27 +17,29 @@
<template> <template>
<notification-manager></notification-manager> <notification-manager></notification-manager>
<more-info-dialog></more-info-dialog> <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> <ha-sidebar drawer></ha-sidebar>
<template is='dom-if' if='[[isSelectedStates]]'> <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>
<template is='dom-if' if='[[isSelectedLogbook]]'> <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>
<template is='dom-if' if='[[isSelectedHistory]]'> <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>
<template is='dom-if' if='[[isSelectedDevService]]'> <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>
<template is='dom-if' if='[[isSelectedDevEvent]]'> <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>
<template is='dom-if' if='[[isSelectedDevState]]'> <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> </template>
</paper-drawer-panel> </paper-drawer-panel>

View File

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

View File

@ -12,15 +12,11 @@
-webkit-user-select: none; -webkit-user-select: none;
-moz-user-select: none; -moz-user-select: none;
} }
.title {
text-align: left;
}
</style> </style>
<template> <template>
<paper-scroll-header-panel class='fit'> <paper-scroll-header-panel class='fit'>
<paper-toolbar> <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"> <div class="title">
<content select='[header-title]'></content> <content select='[header-title]'></content>
</div> </div>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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