mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 09:16:38 +00:00
Add map section
This commit is contained in:
parent
68f6c6ae5d
commit
f354b72a8d
@ -36,7 +36,8 @@
|
|||||||
"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.3",
|
"pikaday": "~1.3.3",
|
||||||
"iron-media-query": "polymerelements/iron-media-query#~1.0.2"
|
"iron-media-query": "polymerelements/iron-media-query#~1.0.2",
|
||||||
|
"leaflet-map": "~1.1.0"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"polymer": "^1.0.0",
|
"polymer": "^1.0.0",
|
||||||
|
@ -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#95b238ca6e548a8d8d998cfa6a55e85b95b4147d",
|
"home-assistant-js": "git+https://github.com/balloob/home-assistant-js.git#bb8bd7bd19cae511e43d4815191921c78c6f00fb",
|
||||||
"lodash": "^3.10.1",
|
"lodash": "^3.10.1",
|
||||||
"moment": "^2.10.6"
|
"moment": "^2.10.6"
|
||||||
},
|
},
|
||||||
|
38
src/components/entity/ha-entity-marker.html
Normal file
38
src/components/entity/ha-entity-marker.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<link rel='import' href='../../../bower_components/polymer/polymer.html'>
|
||||||
|
<link rel='import' href='../../../bower_components/iron-image/iron-image.html'>
|
||||||
|
<link rel='import' href='../../../bower_components/iron-icon/iron-icon.html'>
|
||||||
|
|
||||||
|
<dom-module id='ha-entity-marker'>
|
||||||
|
<style>
|
||||||
|
.marker {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: top;
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 2.5em;
|
||||||
|
text-align: center;
|
||||||
|
height: 2.5em;
|
||||||
|
line-height: 2.5em;
|
||||||
|
font-size: 1.5em;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 0.1em solid var(--ha-marker-color, --default-primary-color);
|
||||||
|
color: rgb(76, 76, 76);
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
iron-image {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<template>
|
||||||
|
<div class='marker'>
|
||||||
|
<template is='dom-if' if='[[icon]]'>
|
||||||
|
<iron-icon icon='[[icon]]'></iron-icon>
|
||||||
|
</template>
|
||||||
|
<template is='dom-if' if='[[image]]'>
|
||||||
|
<iron-image sizing='cover' class='fit'src='[[image]]'></iron-image>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
61
src/components/entity/ha-entity-marker.js
Normal file
61
src/components/entity/ha-entity-marker.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import Polymer from '../../polymer';
|
||||||
|
import {
|
||||||
|
reactor,
|
||||||
|
entityGetters,
|
||||||
|
moreInfoActions,
|
||||||
|
} from '../../util/home-assistant-js-instance';
|
||||||
|
import domainIcon from '../../util/domain-icon';
|
||||||
|
|
||||||
|
require('../../components/ha-label-badge');
|
||||||
|
|
||||||
|
export default new Polymer({
|
||||||
|
is: 'ha-entity-marker',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
entityId: {
|
||||||
|
type: String,
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
state: {
|
||||||
|
type: Object,
|
||||||
|
computed: 'computeState(entityId)',
|
||||||
|
},
|
||||||
|
|
||||||
|
icon: {
|
||||||
|
type: Object,
|
||||||
|
computed: 'computeIcon(state)',
|
||||||
|
},
|
||||||
|
|
||||||
|
image: {
|
||||||
|
type: Object,
|
||||||
|
computed: 'computeImage(state)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
listeners: {
|
||||||
|
'click': 'badgeTap',
|
||||||
|
},
|
||||||
|
|
||||||
|
badgeTap(ev) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
if (this.entityId) {
|
||||||
|
this.async(() => moreInfoActions.selectEntity(this.entityId), 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computeState(entityId) {
|
||||||
|
return entityId && reactor.evaluate(entityGetters.byId(entityId));
|
||||||
|
},
|
||||||
|
|
||||||
|
computeIcon(state) {
|
||||||
|
return state ?
|
||||||
|
!state.attributes.entity_picture && domainIcon(state.domain) :
|
||||||
|
'home';
|
||||||
|
},
|
||||||
|
|
||||||
|
computeImage(state) {
|
||||||
|
return state && state.attributes.entity_picture;
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
@ -77,14 +77,12 @@ export default new Polymer({
|
|||||||
|
|
||||||
computeIcon(state) {
|
computeIcon(state) {
|
||||||
switch (state.domain) {
|
switch (state.domain) {
|
||||||
case 'alarm_control_panel':
|
|
||||||
return state.state === 'disarmed' ?
|
|
||||||
'icons:lock-open' : 'icons:lock';
|
|
||||||
case 'device_tracker':
|
case 'device_tracker':
|
||||||
return !state.attributes.entity_picture && domainIcon(state.domain);
|
return !state.attributes.entity_picture && domainIcon(state.domain);
|
||||||
|
case 'alarm_control_panel':
|
||||||
case 'scene':
|
case 'scene':
|
||||||
case 'script':
|
case 'script':
|
||||||
return domainIcon(state.domain);
|
return domainIcon(state.domain, state.state);
|
||||||
case 'sensor':
|
case 'sensor':
|
||||||
return !state.attributes.unit_of_measurement && domainIcon(state.domain);
|
return !state.attributes.unit_of_measurement && domainIcon(state.domain);
|
||||||
case 'sun':
|
case 'sun':
|
||||||
|
@ -88,6 +88,11 @@
|
|||||||
</paper-icon-item>
|
</paper-icon-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<paper-icon-item on-click='menuClicked' data-panel='map'>
|
||||||
|
<iron-icon item-icon icon='maps:person-pin'></iron-icon>
|
||||||
|
Map
|
||||||
|
</paper-icon-item>
|
||||||
|
|
||||||
<paper-icon-item on-click='menuClicked' data-panel='logout' class='logout'>
|
<paper-icon-item on-click='menuClicked' data-panel='logout' class='logout'>
|
||||||
<iron-icon item-icon icon='exit-to-app'></iron-icon>
|
<iron-icon item-icon icon='exit-to-app'></iron-icon>
|
||||||
Log Out
|
Log Out
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
<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'>
|
||||||
|
<link rel='import' href='../layouts/partial-map.html'>
|
||||||
<link rel='import' href='../layouts/partial-dev-call-service.html'>
|
<link rel='import' href='../layouts/partial-dev-call-service.html'>
|
||||||
<link rel='import' href='../layouts/partial-dev-fire-event.html'>
|
<link rel='import' href='../layouts/partial-dev-fire-event.html'>
|
||||||
<link rel='import' href='../layouts/partial-dev-set-state.html'>
|
<link rel='import' href='../layouts/partial-dev-set-state.html'>
|
||||||
@ -20,7 +21,10 @@
|
|||||||
<iron-media-query query="(max-width: 870px)" query-matches="{{narrow}}">
|
<iron-media-query query="(max-width: 870px)" query-matches="{{narrow}}">
|
||||||
</iron-media-query>
|
</iron-media-query>
|
||||||
|
|
||||||
<paper-drawer-panel id='drawer' force-narrow='[[computeForceNarrow(narrow, showSidebar)]]' responsive-width='0'>
|
<paper-drawer-panel id='drawer'
|
||||||
|
force-narrow='[[computeForceNarrow(narrow, showSidebar)]]'
|
||||||
|
responsive-width='0' disable-swipe='[[isSelectedMap]]'
|
||||||
|
disable-edge-swipe='[[isSelectedMap]]'>
|
||||||
<ha-sidebar drawer></ha-sidebar>
|
<ha-sidebar drawer></ha-sidebar>
|
||||||
|
|
||||||
<template is='dom-if' if='[[isSelectedStates]]'>
|
<template is='dom-if' if='[[isSelectedStates]]'>
|
||||||
@ -32,6 +36,9 @@
|
|||||||
<template is='dom-if' if='[[isSelectedHistory]]'>
|
<template is='dom-if' if='[[isSelectedHistory]]'>
|
||||||
<partial-history main narrow='[[narrow]]' show-menu='[[showSidebar]]'></partial-history>
|
<partial-history main narrow='[[narrow]]' show-menu='[[showSidebar]]'></partial-history>
|
||||||
</template>
|
</template>
|
||||||
|
<template is='dom-if' if='[[isSelectedMap]]'>
|
||||||
|
<partial-map main narrow='[[narrow]]' show-menu='[[showSidebar]]'></partial-map>
|
||||||
|
</template>
|
||||||
<template is='dom-if' if='[[isSelectedDevService]]'>
|
<template is='dom-if' if='[[isSelectedDevService]]'>
|
||||||
<partial-dev-call-service main narrow='[[narrow]]' show-menu='[[showSidebar]]'></partial-dev-call-service>
|
<partial-dev-call-service main narrow='[[narrow]]' show-menu='[[showSidebar]]'></partial-dev-call-service>
|
||||||
</template>
|
</template>
|
||||||
|
@ -11,6 +11,7 @@ require('../components/ha-sidebar');
|
|||||||
require('../layouts/partial-zone');
|
require('../layouts/partial-zone');
|
||||||
require('../layouts/partial-logbook');
|
require('../layouts/partial-logbook');
|
||||||
require('../layouts/partial-history');
|
require('../layouts/partial-history');
|
||||||
|
require('../layouts/partial-map');
|
||||||
require('../layouts/partial-dev-call-service');
|
require('../layouts/partial-dev-call-service');
|
||||||
require('../layouts/partial-dev-fire-event');
|
require('../layouts/partial-dev-fire-event');
|
||||||
require('../layouts/partial-dev-set-state');
|
require('../layouts/partial-dev-set-state');
|
||||||
@ -44,6 +45,11 @@ export default new Polymer({
|
|||||||
bindNuclear: navigationGetters.isActivePane('history'),
|
bindNuclear: navigationGetters.isActivePane('history'),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isSelectedMap: {
|
||||||
|
type: Boolean,
|
||||||
|
bindNuclear: navigationGetters.isActivePane('map'),
|
||||||
|
},
|
||||||
|
|
||||||
isSelectedLogbook: {
|
isSelectedLogbook: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
bindNuclear: navigationGetters.isActivePane('logbook'),
|
bindNuclear: navigationGetters.isActivePane('logbook'),
|
||||||
|
59
src/layouts/partial-map.html
Normal file
59
src/layouts/partial-map.html
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<link rel="import" href="../../bower_components/polymer/polymer.html">
|
||||||
|
<link rel='import' href='../../bower_components/paper-toolbar/paper-toolbar.html'>
|
||||||
|
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
|
||||||
|
|
||||||
|
<link rel="import" href="../../bower_components/leaflet-map/leaflet-map.html">
|
||||||
|
|
||||||
|
<link rel="import" href="../components/entity/ha-entity-marker.html">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Otherwise they go through overlays. */
|
||||||
|
.leaflet-top, .leaflet-bottom {
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<dom-module id="partial-map">
|
||||||
|
<style>
|
||||||
|
.map {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<template>
|
||||||
|
<div class='layout vertical fit'>
|
||||||
|
<paper-toolbar>
|
||||||
|
<paper-icon-button icon='menu' class$='[[computeMenuButtonClass(narrow, showMenu)]]' on-tap='toggleMenu'></paper-icon-button>
|
||||||
|
<div class='title'>Map</div>
|
||||||
|
</paper-toolbar>
|
||||||
|
|
||||||
|
<div class="flex map">
|
||||||
|
<leaflet-map class="fit" fit-to-markers max-zoom="18">
|
||||||
|
<leaflet-divicon id="home" icon-height="45" icon-width="45">
|
||||||
|
<ha-entity-marker></ha-entity-marker>
|
||||||
|
</leaflet-divicon>
|
||||||
|
|
||||||
|
<leaflet-marker latitude="[[locationGPS.latitude]]" icon="home"
|
||||||
|
longitude="[[locationGPS.longitude]]" title="[[locationName]]"
|
||||||
|
></leaflet-marker>
|
||||||
|
|
||||||
|
<template is='dom-repeat' items='[[locationEntities]]'>
|
||||||
|
<leaflet-divicon id="[[item.entityId]]" icon-height="45" icon-width="45">
|
||||||
|
<ha-entity-marker entity-id$="[[item.entityId]]"></ha-entity-marker>
|
||||||
|
</leaflet-divicon>
|
||||||
|
|
||||||
|
<leaflet-marker latitude="[[item.attributes.latitude]]" icon="[[item.entityId]]"
|
||||||
|
longitude="[[item.attributes.longitude]]" title="[[item.entityDisplay]]"
|
||||||
|
></leaflet-marker>
|
||||||
|
|
||||||
|
<template is='dom-if' if='[[item.attributes.gps_accuracy]]'>
|
||||||
|
<leaflet-circle latitude="[[item.attributes.latitude]]"
|
||||||
|
longitude="[[item.attributes.longitude]]"
|
||||||
|
radius="[[item.attributes.gps_accuracy]]" color="#d00">
|
||||||
|
</leaflet-circle>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</leaflet-map>
|
||||||
|
</div>
|
||||||
|
</partial-base>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
61
src/layouts/partial-map.js
Normal file
61
src/layouts/partial-map.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import {
|
||||||
|
configGetters,
|
||||||
|
entityGetters,
|
||||||
|
} from '../util/home-assistant-js-instance';
|
||||||
|
|
||||||
|
import Polymer from '../polymer';
|
||||||
|
import nuclearObserver from '../util/bound-nuclear-behavior';
|
||||||
|
|
||||||
|
require('../components/entity/ha-entity-marker');
|
||||||
|
|
||||||
|
L.Icon.Default.imagePath = '/static/images/leaflet';
|
||||||
|
|
||||||
|
export default new Polymer({
|
||||||
|
is: 'partial-map',
|
||||||
|
|
||||||
|
behaviors: [nuclearObserver],
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
locationGPS: {
|
||||||
|
type: Number,
|
||||||
|
bindNuclear: configGetters.locationGPS,
|
||||||
|
},
|
||||||
|
|
||||||
|
locationName: {
|
||||||
|
type: String,
|
||||||
|
bindNuclear: configGetters.locationName,
|
||||||
|
},
|
||||||
|
|
||||||
|
locationEntities: {
|
||||||
|
type: Array,
|
||||||
|
bindNuclear: [
|
||||||
|
entityGetters.visibleEntityMap,
|
||||||
|
entities => entities.valueSeq().filter(
|
||||||
|
entity => entity.attributes.latitude && entity.state !== 'home'
|
||||||
|
).toArray(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
narrow: {
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
|
|
||||||
|
showMenu: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
attached() {
|
||||||
|
window.el = this;
|
||||||
|
},
|
||||||
|
|
||||||
|
computeMenuButtonClass(narrow, showMenu) {
|
||||||
|
return !narrow && showMenu ? 'invisible' : '';
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleMenu() {
|
||||||
|
this.fire('open-menu');
|
||||||
|
},
|
||||||
|
});
|
@ -5,6 +5,7 @@
|
|||||||
<link rel="import" href="../../bower_components/iron-icons/image-icons.html">
|
<link rel="import" href="../../bower_components/iron-icons/image-icons.html">
|
||||||
<link rel="import" href="../../bower_components/iron-icons/hardware-icons.html">
|
<link rel="import" href="../../bower_components/iron-icons/hardware-icons.html">
|
||||||
<link rel="import" href="../../bower_components/iron-icons/av-icons.html">
|
<link rel="import" href="../../bower_components/iron-icons/av-icons.html">
|
||||||
|
<link rel="import" href="../../bower_components/iron-icons/maps-icons.html">
|
||||||
|
|
||||||
<iron-iconset-svg name="homeassistant-100" size="100">
|
<iron-iconset-svg name="homeassistant-100" size="100">
|
||||||
<svg><defs>
|
<svg><defs>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user