mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-18 23:06:40 +00:00
Use app-route for routing (#328)
* Use app-route for routing * Fix bower * Fix default route * Add back button support back
This commit is contained in:
parent
33ee6a9075
commit
10d5a05d1f
@ -9,6 +9,7 @@
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"app-layout": "^2.0.0",
|
||||
"app-route": "PolymerElements/app-route#^2.0.0",
|
||||
"app-storage": "^2.0.2",
|
||||
"fecha": "~2.3.0",
|
||||
"font-roboto-local": "~1.0.1",
|
||||
@ -70,6 +71,7 @@
|
||||
"iron-input": "^2.0.0",
|
||||
"iron-jsonp-library": "^2.0.0",
|
||||
"iron-list": "^2.0.0",
|
||||
"iron-location": "^2.0.1",
|
||||
"iron-media-query": "^2.0.0",
|
||||
"iron-menu-behavior": "^2.0.0",
|
||||
"iron-meta": "^2.0.0",
|
||||
@ -103,7 +105,6 @@
|
||||
"paper-scroll-header-panel": "^2.0.0",
|
||||
"paper-slider": "^2.0.0",
|
||||
"paper-spinner": "^2.0.0",
|
||||
"paper-styles": "2.0.0",
|
||||
"paper-styles": "^2.0.0",
|
||||
"paper-tabs": "^2.0.0",
|
||||
"paper-toast": "^2.0.0",
|
||||
|
@ -99,7 +99,7 @@
|
||||
<paper-icon-button icon='mdi:chevron-left' hidden$='[[narrow]]' on-tap='toggleMenu'></paper-icon-button>
|
||||
</app-toolbar>
|
||||
|
||||
<paper-listbox attr-for-selected='data-panel' selected='[[hass.currentPanel]]' on-iron-select='menuSelect'>
|
||||
<paper-listbox attr-for-selected='data-panel' selected='[[route.panel]]'>
|
||||
<paper-icon-item on-tap='menuClicked' data-panel='states'>
|
||||
<iron-icon slot="item-icon" icon='mdi:apps'></iron-icon>
|
||||
<span class='item-text'>States</span>
|
||||
@ -178,9 +178,9 @@ Polymer({
|
||||
type: String,
|
||||
},
|
||||
|
||||
narrow: {
|
||||
type: Boolean,
|
||||
},
|
||||
narrow: Boolean,
|
||||
|
||||
route: Object,
|
||||
|
||||
panels: {
|
||||
type: Array,
|
||||
@ -193,10 +193,6 @@ Polymer({
|
||||
},
|
||||
},
|
||||
|
||||
created: function () {
|
||||
this._boundUpdateStyles = this.updateStyles.bind(this);
|
||||
},
|
||||
|
||||
computePanels: function (hass) {
|
||||
var panels = hass.config.panels;
|
||||
var sortValue = {
|
||||
@ -236,10 +232,6 @@ Polymer({
|
||||
return result;
|
||||
},
|
||||
|
||||
menuSelect: function () {
|
||||
this.debounce('updateStyles', this._boundUpdateStyles, 1);
|
||||
},
|
||||
|
||||
menuClicked: function (ev) {
|
||||
var target = ev.target;
|
||||
var checks = 5;
|
||||
@ -262,14 +254,16 @@ Polymer({
|
||||
},
|
||||
|
||||
selectPanel: function (newChoice) {
|
||||
if (newChoice === this.hass.currentPanel) {
|
||||
return;
|
||||
} else if (newChoice === 'logout') {
|
||||
if (newChoice === 'logout') {
|
||||
this.handleLogOut();
|
||||
return;
|
||||
}
|
||||
this.fire('hass-navigate', { panel: newChoice });
|
||||
this.debounce('updateStyles', this._boundUpdateStyles, 1);
|
||||
var path = '/' + newChoice;
|
||||
if (path === document.location.pathname) {
|
||||
return;
|
||||
}
|
||||
history.pushState(null, null, path);
|
||||
this.fire('location-changed');
|
||||
},
|
||||
|
||||
handleLogOut: function () {
|
||||
|
@ -25,7 +25,6 @@
|
||||
<template is='dom-if' if='[[showMain]]' restamp>
|
||||
<home-assistant-main
|
||||
on-hass-more-info='handleMoreInfo'
|
||||
on-hass-navigate='handleNavigate'
|
||||
on-hass-dock-sidebar='handleDockSidebar'
|
||||
on-hass-notification='handleNotification'
|
||||
on-hass-logout='handleLogout'
|
||||
@ -127,8 +126,6 @@ Polymer({
|
||||
states: null,
|
||||
config: null,
|
||||
dockedSidebar: false,
|
||||
currentPanel: 'states',
|
||||
currentView: null,
|
||||
moreInfoEntityId: null,
|
||||
callService: function (domain, service, serviceData) {
|
||||
return conn.callService(domain, service, serviceData || {})
|
||||
@ -217,22 +214,6 @@ Polymer({
|
||||
{ moreInfoEntityId: ev.detail.entityId });
|
||||
},
|
||||
|
||||
handleNavigate: function (ev) {
|
||||
ev.stopPropagation();
|
||||
|
||||
var hass = Object.assign({}, this.hass);
|
||||
|
||||
if ('panel' in ev.detail) {
|
||||
hass.currentPanel = ev.detail.panel;
|
||||
}
|
||||
|
||||
if ('view' in ev.detail) {
|
||||
hass.currentView = ev.detail.view;
|
||||
}
|
||||
|
||||
this.hass = hass;
|
||||
},
|
||||
|
||||
handleDockSidebar: function (ev) {
|
||||
ev.stopPropagation();
|
||||
this.hass = Object.assign(
|
||||
|
@ -3,6 +3,10 @@
|
||||
<link rel='import' href='../../bower_components/iron-media-query/iron-media-query.html'>
|
||||
<link rel='import' href='../../bower_components/iron-pages/iron-pages.html'>
|
||||
|
||||
<link rel='import' href='../../bower_components/app-route/app-route.html'>
|
||||
<link rel='import' href='../../bower_components/app-route/app-location.html'>
|
||||
|
||||
|
||||
<link rel='import' href='../layouts/partial-cards.html'>
|
||||
<link rel='import' href='../layouts/partial-panel-resolver.html'>
|
||||
<link rel="import" href="../dialogs/more-info-dialog.html">
|
||||
@ -15,6 +19,13 @@
|
||||
<template>
|
||||
<more-info-dialog hass='[[hass]]'></more-info-dialog>
|
||||
<ha-url-sync hass='[[hass]]'></ha-url-sync>
|
||||
<app-location route="{{route}}"></app-location>
|
||||
<app-route
|
||||
route="{{route}}"
|
||||
pattern="/:panel"
|
||||
data="{{routeData}}"
|
||||
tail="{{routeTail}}"
|
||||
></app-route>
|
||||
<ha-voice-command-dialog
|
||||
hass='[[hass]]'
|
||||
id='voiceDialog'
|
||||
@ -26,13 +37,18 @@
|
||||
force-narrow='[[computeForceNarrow(narrow, dockedSidebar)]]'
|
||||
responsive-width='0' disable-swipe='[[isSelectedMap]]'
|
||||
disable-edge-swipe='[[isSelectedMap]]'>
|
||||
<ha-sidebar slot="drawer" narrow='[[narrow]]' hass='[[hass]]'></ha-sidebar>
|
||||
<ha-sidebar
|
||||
slot="drawer"
|
||||
narrow='[[narrow]]'
|
||||
hass='[[hass]]'
|
||||
route='[[routeData]]'
|
||||
></ha-sidebar>
|
||||
|
||||
<iron-pages
|
||||
slot="main"
|
||||
attr-for-selected='id'
|
||||
fallback-selection='panel-resolver'
|
||||
selected='[[currentPanel]]'
|
||||
selected='[[_computeSelected(routeData)]]'
|
||||
selected-attribute='panel-visible'
|
||||
>
|
||||
<partial-cards
|
||||
@ -40,12 +56,14 @@
|
||||
narrow='[[narrow]]'
|
||||
hass='[[hass]]'
|
||||
show-menu='[[dockedSidebar]]'
|
||||
route='[[routeTail]]'
|
||||
></partial-cards>
|
||||
|
||||
<partial-panel-resolver
|
||||
id='panel-resolver'
|
||||
narrow='[[narrow]]'
|
||||
hass='[[hass]]'
|
||||
route='[[route]]'
|
||||
show-menu='[[dockedSidebar]]'
|
||||
></partial-panel-resolver>
|
||||
|
||||
@ -60,19 +78,16 @@ Polymer({
|
||||
is: 'home-assistant-main',
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
hass: Object,
|
||||
|
||||
narrow: Boolean,
|
||||
|
||||
route: {
|
||||
type: Object,
|
||||
value: null,
|
||||
observer: 'hassChanged',
|
||||
},
|
||||
|
||||
narrow: {
|
||||
type: Boolean,
|
||||
},
|
||||
|
||||
currentPanel: {
|
||||
type: String,
|
||||
observer: '_routeChanged',
|
||||
},
|
||||
routeData: Object,
|
||||
routeTail: Object,
|
||||
|
||||
dockedSidebar: {
|
||||
type: Boolean,
|
||||
@ -86,14 +101,10 @@ Polymer({
|
||||
'hass-start-voice': 'handleStartVoice',
|
||||
},
|
||||
|
||||
hassChanged: function (hass) {
|
||||
if (this.currentPanel !== hass.currentPanel) {
|
||||
this.currentPanel = hass.currentPanel;
|
||||
|
||||
_routeChanged: function () {
|
||||
if (this.narrow) {
|
||||
this.$.drawer.closeDrawer();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleStartVoice: function (ev) {
|
||||
@ -127,5 +138,9 @@ Polymer({
|
||||
computeDockedSidebar: function (hass) {
|
||||
return hass.dockedSidebar;
|
||||
},
|
||||
|
||||
_computeSelected: function (routeData) {
|
||||
return routeData.panel || 'states';
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -11,6 +11,7 @@
|
||||
<link rel="import" href="../../bower_components/app-layout/app-scroll-effects/effects/waterfall.html">
|
||||
<link rel="import" href="../../bower_components/app-layout/app-header/app-header.html">
|
||||
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
|
||||
<link rel='import' href='../../bower_components/app-route/app-route.html'>
|
||||
|
||||
<link rel="import" href="../components/ha-menu-button.html">
|
||||
<link rel="import" href="../components/ha-start-voice-button.html">
|
||||
@ -35,7 +36,12 @@
|
||||
text-transform: uppercase;
|
||||
}
|
||||
</style>
|
||||
|
||||
<app-route
|
||||
route="{{route}}"
|
||||
pattern="/:view"
|
||||
data="{{routeData}}"
|
||||
active="{{routeMatch}}"
|
||||
></app-route>
|
||||
<app-header-layout has-scrolling-region id='layout'>
|
||||
<app-header effects="waterfall" condenses fixed slot="header">
|
||||
<app-toolbar>
|
||||
@ -49,7 +55,7 @@
|
||||
scrollable
|
||||
selected='[[currentView]]'
|
||||
attr-for-selected='data-entity'
|
||||
on-iron-select='handleViewSelected'
|
||||
on-iron-activate='handleViewSelected'
|
||||
>
|
||||
<paper-tab
|
||||
data-entity=''
|
||||
@ -59,10 +65,19 @@
|
||||
[[locationName]]
|
||||
</template>
|
||||
<template is='dom-if' if='[[defaultView]]'>
|
||||
<template is='dom-if' if='[[defaultView.attributes.icon]]'>
|
||||
<iron-icon title$='[[computeStateName(defaultView)]]' icon='[[defaultView.attributes.icon]]'></iron-icon>
|
||||
<template
|
||||
is='dom-if'
|
||||
if='[[defaultView.attributes.icon]]'
|
||||
>
|
||||
<iron-icon
|
||||
title$='[[computeStateName(defaultView)]]'
|
||||
icon='[[defaultView.attributes.icon]]'
|
||||
></iron-icon>
|
||||
</template>
|
||||
<template is='dom-if' if='[[!defaultView.attributes.icon]]'>
|
||||
<template
|
||||
is='dom-if'
|
||||
if='[[!defaultView.attributes.icon]]'
|
||||
>
|
||||
[[computeStateName(defaultView)]]
|
||||
</template>
|
||||
</template>
|
||||
@ -101,7 +116,6 @@
|
||||
<template is='dom-repeat' items='[[views]]'>
|
||||
<ha-cards
|
||||
data-view$='[[item.entity_id]]'
|
||||
show-introduction='[[computeShowIntroduction(currentView, introductionLoaded, viewStates)]]'
|
||||
states='[[viewStates]]'
|
||||
columns='[[_columns]]'
|
||||
hass='[[hass]]'
|
||||
@ -144,6 +158,10 @@ Polymer({
|
||||
value: false,
|
||||
},
|
||||
|
||||
route: Object,
|
||||
routeData: Object,
|
||||
routeMatch: Boolean,
|
||||
|
||||
_columns: {
|
||||
type: Number,
|
||||
value: 1,
|
||||
@ -162,6 +180,7 @@ Polymer({
|
||||
|
||||
currentView: {
|
||||
type: String,
|
||||
computed: '_computeCurrentView(routeMatch, routeData)',
|
||||
},
|
||||
|
||||
views: {
|
||||
@ -242,10 +261,20 @@ Polymer({
|
||||
|
||||
handleViewSelected: function (ev) {
|
||||
var view = ev.detail.item.getAttribute('data-entity') || null;
|
||||
var current = this.currentView || null;
|
||||
var current = this.currentView;
|
||||
|
||||
if (view !== current) {
|
||||
this.fire('hass-navigate', { view: view });
|
||||
var path = this.route.prefix;
|
||||
if (view) {
|
||||
path += '/' + view;
|
||||
}
|
||||
history.pushState(null, null, path);
|
||||
this.fire('location-changed');
|
||||
}
|
||||
},
|
||||
|
||||
_computeCurrentView: function (routeMatch, routeData) {
|
||||
return routeMatch ? routeData.view : '';
|
||||
},
|
||||
|
||||
computeTitle: function (views, locationName) {
|
||||
@ -276,12 +305,6 @@ Polymer({
|
||||
},
|
||||
|
||||
hassChanged: function (hass) {
|
||||
var newView = hass.currentView || '';
|
||||
|
||||
if (newView !== this.currentView) {
|
||||
this.currentView = newView;
|
||||
}
|
||||
|
||||
var views = window.HAWS.extractViews(hass.states);
|
||||
// If default view present, it's in first index.
|
||||
if (views.length > 0 && views[0].entity_id === this.DEFAULT_VIEW_ENTITY_ID) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
<link rel='import' href='../../bower_components/polymer/polymer.html'>
|
||||
<link rel='import' href='../../bower_components/app-route/app-route.html'>
|
||||
|
||||
<link rel="import" href="./hass-loading-screen.html">
|
||||
|
||||
@ -9,6 +10,12 @@
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
<app-route
|
||||
route="{{route}}"
|
||||
pattern="/:panel"
|
||||
data="{{routeData}}"
|
||||
tail="{{routeTail}}"
|
||||
></app-route>
|
||||
|
||||
<template is='dom-if' if='[[!resolved]]'>
|
||||
<hass-loading-screen
|
||||
@ -43,6 +50,15 @@ Polymer({
|
||||
observer: 'updateAttributes',
|
||||
},
|
||||
|
||||
route: Object,
|
||||
|
||||
routeData: Object,
|
||||
|
||||
routeTail: {
|
||||
type: Object,
|
||||
observer: 'updateAttributes',
|
||||
},
|
||||
|
||||
resolved: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
@ -55,13 +71,13 @@ Polymer({
|
||||
|
||||
panel: {
|
||||
type: Object,
|
||||
computed: 'computeCurrentPanel(hass)',
|
||||
computed: 'computeCurrentPanel(hass, routeData)',
|
||||
observer: 'panelChanged',
|
||||
},
|
||||
},
|
||||
|
||||
computeCurrentPanel: function (hass) {
|
||||
return hass.config.panels[hass.currentPanel];
|
||||
computeCurrentPanel: function (hass, routeData) {
|
||||
return hass.config.panels[routeData.panel];
|
||||
},
|
||||
|
||||
panelChanged: function (panel) {
|
||||
@ -102,6 +118,7 @@ Polymer({
|
||||
customEl.hass = this.hass;
|
||||
customEl.narrow = this.narrow;
|
||||
customEl.showMenu = this.showMenu;
|
||||
customEl.route = this.routeTail;
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,19 +1,7 @@
|
||||
<script>
|
||||
(function () {
|
||||
var PAGE_TITLE = 'Home Assistant';
|
||||
|
||||
function pageState(panel, view) {
|
||||
var state = { panel: panel };
|
||||
if (panel === 'states') {
|
||||
state.view = view || null;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
function pageUrl(pane, view) {
|
||||
return pane === 'states' && view ?
|
||||
'/' + pane + '/' + view : '/' + pane;
|
||||
}
|
||||
/* eslint-disable no-console */
|
||||
var DEBUG = false;
|
||||
|
||||
Polymer({
|
||||
is: 'ha-url-sync',
|
||||
@ -26,63 +14,49 @@
|
||||
},
|
||||
|
||||
hassChanged: function (newHass, oldHass) {
|
||||
if (!oldHass) {
|
||||
if (this.ignoreNextHassChange) {
|
||||
if (DEBUG) console.log('ignore hasschange');
|
||||
this.ignoreNextHassChange = false;
|
||||
return;
|
||||
} else if (newHass.currentPanel === oldHass.currentPanel &&
|
||||
newHass.currentView === oldHass.currentView) {
|
||||
// did the more info entity change?
|
||||
if (oldHass.moreInfoEntityId !== newHass.moreInfoEntityId) {
|
||||
} else if (!oldHass || oldHass.moreInfoEntityId === newHass.moreInfoEntityId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newHass.moreInfoEntityId) {
|
||||
// push same state so that back button works.
|
||||
history.pushState(history.state, PAGE_TITLE, window.location.pathname);
|
||||
} else if (this.ignoreNextDeselectEntity) {
|
||||
this.ignoreNextDeselectEntity = false;
|
||||
if (DEBUG) console.log('pushing state');
|
||||
history.pushState(null, null, window.location.pathname);
|
||||
} else {
|
||||
if (DEBUG) console.log('history back');
|
||||
this.ignoreNextPopstate = true;
|
||||
history.back();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (this.ignoreNextNav) {
|
||||
this.ignoreNextNav = false;
|
||||
return;
|
||||
}
|
||||
|
||||
history.pushState(
|
||||
pageState(newHass.currentPanel, newHass.currentView), PAGE_TITLE,
|
||||
pageUrl(newHass.currentPanel, newHass.currentView));
|
||||
},
|
||||
|
||||
popstateChangeListener: function (ev) {
|
||||
if (this.ignoreNextPopstate) {
|
||||
if (DEBUG) console.log('ignore popstate');
|
||||
this.ignoreNextPopstate = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG) console.log('popstate', ev);
|
||||
|
||||
if (this.hass.moreInfoEntityId) {
|
||||
this.ignoreNextDeselectEntity = true;
|
||||
if (DEBUG) console.log('deselect entity');
|
||||
this.ignoreNextHassChange = true;
|
||||
this.fire('hass-more-info', { entityId: null });
|
||||
} else if (this.hass.currentPanel !== ev.state.panel ||
|
||||
this.hass.currentView !== ev.state.view) {
|
||||
this.ignoreNextNav = true;
|
||||
this.fire('hass-navigate', ev.state);
|
||||
}
|
||||
},
|
||||
|
||||
// initial url sync
|
||||
attached: function () {
|
||||
this.ignoreNextPopstate = false;
|
||||
this.ignoreNextHassChange = false;
|
||||
this.popstateChangeListener = this.popstateChangeListener.bind(this);
|
||||
|
||||
// keep state in sync when url changes via forward/back buttons
|
||||
window.addEventListener('popstate', this.popstateChangeListener);
|
||||
},
|
||||
|
||||
// store current view / panel
|
||||
if (window.location.pathname === '/') {
|
||||
var currentPanel = this.hass.currentPanel;
|
||||
var currentView = this.hass.currentView;
|
||||
|
||||
history.replaceState(
|
||||
pageState(currentPanel, currentView), PAGE_TITLE,
|
||||
pageUrl(currentPanel, currentView));
|
||||
} else {
|
||||
var parts = window.location.pathname.substr(1).split('/');
|
||||
this.fire('hass-navigate', pageState(parts[0], parts[1]));
|
||||
}
|
||||
detached: function () {
|
||||
window.removeEventListener('popstate', this.popstateChangeListener);
|
||||
}
|
||||
});
|
||||
}());
|
||||
|
Loading…
x
Reference in New Issue
Block a user