mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Initial commit Polymer interface
This commit is contained in:
parent
a0c12fe685
commit
8a8097af99
30
homeassistant/components/http/www_static/polymer/bower.json
Normal file
30
homeassistant/components/http/www_static/polymer/bower.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "Home Assistant",
|
||||
"version": "0.1.0",
|
||||
"authors": [
|
||||
"Paulus Schoutsen <Paulus@PaulusSchoutsen.nl>"
|
||||
],
|
||||
"main": "index.htm",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"polymer": "Polymer/polymer#~0.4.2",
|
||||
"font-roboto": "Polymer/font-roboto#~0.4.2",
|
||||
"core-header-panel": "Polymer/core-header-panel#~0.4.2",
|
||||
"core-toolbar": "Polymer/core-toolbar#~0.4.2",
|
||||
"core-icon-button": "Polymer/core-icon-button#~0.4.2",
|
||||
"paper-fab": "Polymer/paper-fab#~0.4.2",
|
||||
"core-ajax": "Polymer/core-ajax#~0.4.2",
|
||||
"paper-toast": "Polymer/paper-toast#~0.4.2",
|
||||
"paper-dialog": "Polymer/paper-dialog#~0.4.2",
|
||||
"paper-button": "Polymer/paper-button#~0.4.2",
|
||||
"core-tooltip": "Polymer/core-tooltip#~0.4.2"
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
<link rel="import" href="bower_components/polymer/polymer.html">
|
||||
|
||||
<polymer-element name="entity-list" attributes="api cbEntityClicked">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.entityContainer {
|
||||
font-size: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template if={{cbEntityClicked}}>
|
||||
<style>
|
||||
a {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</template>
|
||||
|
||||
<div>
|
||||
<template repeat="{{state in states}}">
|
||||
<div class='eventContainer'>
|
||||
<a on-click={{handleClick}}>{{state.entity_id}}</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
Polymer({
|
||||
cbEventClicked: null,
|
||||
states: [],
|
||||
|
||||
domReady: function() {
|
||||
this.api.addEventListener('states-updated', this.statesUpdated.bind(this))
|
||||
this.statesUpdated()
|
||||
},
|
||||
|
||||
statesUpdated: function() {
|
||||
this.states = this.api.states;
|
||||
},
|
||||
|
||||
handleClick: function(ev) {
|
||||
if(this.cbEntityClicked) {
|
||||
this.cbEntityClicked(ev.path[0].innerHTML);
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
</script>
|
||||
</polymer-element>
|
@ -0,0 +1,71 @@
|
||||
<link rel="import" href="bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="bower_components/paper-dialog/paper-dialog.html">
|
||||
<link rel="import" href="bower_components/paper-dialog/paper-dialog-transition.html">
|
||||
<link rel="import" href="bower_components/paper-button/paper-button.html">
|
||||
<link rel="import" href="bower_components/paper-input/paper-input.html">
|
||||
|
||||
<link rel="import" href="events-list.html">
|
||||
|
||||
<polymer-element name="event-fire-dialog" attributes="api">
|
||||
<template>
|
||||
<style>
|
||||
paper-input:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.eventContainer {
|
||||
margin-left: 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<paper-dialog id="dialog" heading="Fire Event" transition="paper-dialog-transition-bottom" backdrop="true">
|
||||
<div layout horizontal>
|
||||
<div>
|
||||
<paper-input id="inputType" label="Event Type" floatingLabel="true" autofocus required></paper-input>
|
||||
<paper-input id="inputData" label="Event Data (JSON, optional)" floatingLabel="true" multiline></paper-input>
|
||||
</div>
|
||||
<div class='eventContainer'>
|
||||
<b>Available events:</b>
|
||||
<events-list api={{api}} cbEventClicked={{eventSelected}}></event-list>
|
||||
</div>
|
||||
</div>
|
||||
<paper-button dismissive>Cancel</paper-button>
|
||||
<paper-button affirmative on-click={{clickFireEvent}}>Fire Event</paper-button>
|
||||
</paper-dialog>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
Polymer({
|
||||
ready: function() {
|
||||
// to ensure callback methods work..
|
||||
this.eventSelected = this.eventSelected.bind(this)
|
||||
},
|
||||
|
||||
show: function(eventType, eventData) {
|
||||
this.setEventType(eventType);
|
||||
this.setEventData(eventData);
|
||||
|
||||
this.$.dialog.toggle();
|
||||
},
|
||||
|
||||
setEventType: function(eventType) {
|
||||
this.$.inputType.value = eventType;
|
||||
},
|
||||
|
||||
setEventData: function(eventData) {
|
||||
this.$.inputData.value = eventData;
|
||||
},
|
||||
|
||||
eventSelected: function(eventType) {
|
||||
this.setEventType(eventType);
|
||||
},
|
||||
|
||||
clickFireEvent: function() {
|
||||
this.api.fire_event(
|
||||
this.$.inputType.value,
|
||||
this.$.inputData.value
|
||||
)
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</polymer-element>
|
@ -0,0 +1,58 @@
|
||||
<link rel="import" href="bower_components/polymer/polymer.html">
|
||||
|
||||
<polymer-element name="events-list" attributes="api cbEventClicked">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.eventContainer {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<template if={{cbEventClicked}}>
|
||||
<style>
|
||||
a {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</template>
|
||||
|
||||
<div>
|
||||
<template repeat="{{event in events}}">
|
||||
<div class='eventContainer'>
|
||||
<a on-click={{handleClick}}>{{event.event}}</a>
|
||||
({{event.listener_count}} listeners)
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
Polymer({
|
||||
cbEventClicked: null,
|
||||
events: [],
|
||||
|
||||
domReady: function() {
|
||||
this.events = this.api.events
|
||||
|
||||
this.api.addEventListener('events-updated', this.eventsUpdated.bind(this))
|
||||
},
|
||||
|
||||
eventsUpdated: function() {
|
||||
this.events = this.api.events;
|
||||
},
|
||||
|
||||
handleClick: function(ev) {
|
||||
if(this.cbEventClicked) {
|
||||
this.cbEventClicked(ev.path[0].innerHTML);
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
</script>
|
||||
</polymer-element>
|
@ -0,0 +1,270 @@
|
||||
<link rel="import" href="bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="bower_components/core-ajax/core-ajax.html">
|
||||
<link rel="import" href="bower_components/paper-toast/paper-toast.html">
|
||||
|
||||
<link rel="import" href="event-fire-dialog.html">
|
||||
<link rel="import" href="service-call-dialog.html">
|
||||
<link rel="import" href="state-set-dialog.html">
|
||||
|
||||
<polymer-element name="home-assistant-api" attributes="auth">
|
||||
<template>
|
||||
<style>
|
||||
core-ajax {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<paper-toast id="toast" role="alert" text=""></paper-toast>
|
||||
<event-fire-dialog id="eventDialog" api={{api}}></event-fire-dialog>
|
||||
<service-call-dialog id="serviceDialog" api={{api}}></service-call-dialog>
|
||||
<state-set-dialog id="stateDialog" api={{api}}></state-set-dialog>
|
||||
|
||||
<core-ajax id="statesAjax"
|
||||
auto
|
||||
method="GET"
|
||||
url="/api/states"
|
||||
headers='{"HA-access": "{{auth}}"}'
|
||||
on-core-response="{{statesLoaded}}"
|
||||
handleAs="json">
|
||||
</core-ajax>
|
||||
|
||||
<core-ajax id="eventsAjax"
|
||||
auto
|
||||
method="GET"
|
||||
url="/api/events"
|
||||
headers='{"HA-access": "{{auth}}"}'
|
||||
on-core-response="{{eventsLoaded}}"
|
||||
handleAs="json">
|
||||
</core-ajax>
|
||||
|
||||
<core-ajax id="servicesAjax"
|
||||
auto
|
||||
method="GET"
|
||||
url="/api/services"
|
||||
headers='{"HA-access": "{{auth}}"}'
|
||||
on-core-response="{{servicesLoaded}}"
|
||||
handleAs="json">
|
||||
</core-ajax>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
Polymer({
|
||||
auth: "",
|
||||
states: [],
|
||||
services: {},
|
||||
events: {},
|
||||
stateUpdateTimeout: null,
|
||||
|
||||
created: function() {
|
||||
this.api = this;
|
||||
|
||||
// so we can pass these methods safely as callbacks
|
||||
this.turn_on = this.turn_on.bind(this);
|
||||
this.turn_off = this.turn_off.bind(this);
|
||||
},
|
||||
|
||||
_laterFetchStates: function() {
|
||||
if(this.stateUpdateTimeout) {
|
||||
clearTimeout(this.stateUpdateTimeout);
|
||||
}
|
||||
|
||||
// update states in 60 seconds
|
||||
this.stateUpdateTimeout = setTimeout(this.fetchStates.bind(this), 60000);
|
||||
},
|
||||
|
||||
_sortStates: function(states) {
|
||||
return states.sort(function(one, two) {
|
||||
if (one.entity_id > two.entity_id) {
|
||||
return 1;
|
||||
} else if (one.entity_id < two.entity_id) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
statesLoaded: function() {
|
||||
// Make a copy of the loaded data
|
||||
this.states = this._sortStates(this.$.statesAjax.response.slice(0));
|
||||
|
||||
this.fire('states-updated')
|
||||
|
||||
this._laterFetchStates();
|
||||
},
|
||||
|
||||
eventsLoaded: function() {
|
||||
// Make a copy of the loaded data
|
||||
this.events = this.$.eventsAjax.response;
|
||||
|
||||
this.fire('events-updated')
|
||||
},
|
||||
|
||||
servicesLoaded: function() {
|
||||
// Make a copy of the loaded data
|
||||
this.services = this.$.servicesAjax.response;
|
||||
|
||||
this.fire('services-updated')
|
||||
},
|
||||
|
||||
_pushNewState: function(new_state) {
|
||||
var state;
|
||||
var stateFound = false;
|
||||
|
||||
for(var i = 0; i < this.states.length; i++) {
|
||||
if(this.states[i].entity_id == new_state.entity_id) {
|
||||
state = this.states[i];
|
||||
state.attributes = new_state.attributes;
|
||||
state.last_changed = new_state.last_changed;
|
||||
state.state = new_state.state;
|
||||
|
||||
stateFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!stateFound) {
|
||||
this.states.push(new_state);
|
||||
this._sortStates(this.states);
|
||||
}
|
||||
},
|
||||
|
||||
fetchState: function(entity_id) {
|
||||
var successStateUpdate = function(new_state) {
|
||||
this._pushNewState(new_state);
|
||||
}
|
||||
|
||||
this.call_api("GET", "states/" + entity_id, null, successStateUpdate.bind(this));
|
||||
},
|
||||
|
||||
fetchStates: function() {
|
||||
this.$.statesAjax.go();
|
||||
},
|
||||
|
||||
getState: function(entityId) {
|
||||
for(var i = 0; i < this.states.length; i++) {
|
||||
if(this.states[i].entity_id == entityId) {
|
||||
return this.states[i];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
turn_on: function(entity_id) {
|
||||
this.call_service("homeassistant", "turn_on", {entity_id: entity_id});
|
||||
},
|
||||
|
||||
turn_off: function(entity_id) {
|
||||
this.call_service("homeassistant", "turn_off", {entity_id: entity_id})
|
||||
},
|
||||
|
||||
set_state: function(entity_id, state, attributes) {
|
||||
var payload = {state: state}
|
||||
|
||||
if(attributes) {
|
||||
payload.attributes = attributes;
|
||||
}
|
||||
|
||||
var successToast = function(new_state) {
|
||||
this.showToast("State of "+entity_id+" successful set to "+state+".");
|
||||
this._pushNewState(new_state);
|
||||
}
|
||||
|
||||
this.call_api("POST", "states/" + entity_id,
|
||||
payload, successToast.bind(this));
|
||||
},
|
||||
|
||||
call_service: function(domain, service, parameters) {
|
||||
var successToast = function() {
|
||||
this.showToast("Service "+domain+"/"+service+" successful called.");
|
||||
}
|
||||
|
||||
this.call_api("POST", "services/" + domain + "/" + service,
|
||||
parameters, successToast.bind(this));
|
||||
},
|
||||
|
||||
fire_event: function(eventType, eventData) {
|
||||
eventData = eventData ? JSON.parse(eventData) : "";
|
||||
|
||||
var successToast = function() {
|
||||
this.showToast("Event "+eventType+" successful fired.");
|
||||
}
|
||||
|
||||
this.call_api("POST", "events/" + eventType,
|
||||
eventData, successToast.bind(this));
|
||||
},
|
||||
|
||||
call_api: function(method, path, parameters, callback) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open(method, "/api/" + path, true)
|
||||
req.setRequestHeader("HA-access", this.auth);
|
||||
|
||||
req.onreadystatechange = function() {
|
||||
|
||||
if(req.readyState == 4 && req.status > 199 && req.status < 300) {
|
||||
|
||||
if(callback) {
|
||||
callback(JSON.parse(req.responseText))
|
||||
}
|
||||
// if we targetted an entity id, update state after 2 seconds
|
||||
if(parameters && parameters.entity_id) {
|
||||
var updateCallback;
|
||||
|
||||
// if a string, update just that entity, otherwise update all
|
||||
if(typeof(parameters.entity_id) == "string") {
|
||||
updateCallback = function() {
|
||||
this.fetchState(parameters.entity_id);
|
||||
}
|
||||
|
||||
} else {
|
||||
updateCallback = this.fetchStates();
|
||||
}
|
||||
|
||||
setTimeout(updateCallback.bind(this), 2000);
|
||||
}
|
||||
}
|
||||
}.bind(this)
|
||||
|
||||
if(parameters) {
|
||||
req.send(JSON.stringify(parameters))
|
||||
} else {
|
||||
req.send()
|
||||
}
|
||||
},
|
||||
|
||||
showEditStateDialog: function(entityId) {
|
||||
var state = this.getState(entityId);
|
||||
|
||||
this.showSetStateDialog(entityId, state.state, state.attributes)
|
||||
},
|
||||
|
||||
showSetStateDialog: function(entityId, state, stateAttributes) {
|
||||
entityId = entityId || "";
|
||||
state = state || "";
|
||||
stateAttributes = stateAttributes || null;
|
||||
|
||||
this.$.stateDialog.show(entityId, state, stateAttributes);
|
||||
},
|
||||
|
||||
showFireEventDialog: function(eventType, eventData) {
|
||||
eventType = eventType || "";
|
||||
eventData = eventData || "";
|
||||
|
||||
this.$.eventDialog.show(eventType, eventData)
|
||||
},
|
||||
|
||||
showCallServiceDialog: function(domain, service, serviceData) {
|
||||
domain = domain || "";
|
||||
service = service || "";
|
||||
serviceData = serviceData || "";
|
||||
|
||||
this.$.serviceDialog.show(domain, service, serviceData);
|
||||
},
|
||||
|
||||
showToast: function(message) {
|
||||
this.$.toast.text = message;
|
||||
this.$.toast.show();
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
</polymer-element>
|
@ -0,0 +1,79 @@
|
||||
<link rel="import" href="bower_components/font-roboto/roboto.html">
|
||||
<link rel="import" href="bower_components/core-header-panel/core-header-panel.html">
|
||||
<link rel="import" href="bower_components/core-toolbar/core-toolbar.html">
|
||||
<link rel="import" href="bower_components/core-icon-button/core-icon-button.html">
|
||||
<link rel="import" href="bower_components/paper-fab/paper-fab.html">
|
||||
|
||||
<link rel="import" href="home-assistant-api.html">
|
||||
<link rel="import" href="states-cards.html">
|
||||
|
||||
<polymer-element name="home-assistant-main" attributes="auth">
|
||||
<template>
|
||||
<style type="text/css">
|
||||
|
||||
:host {
|
||||
font-family: 'RobotoDraft', sans-serif;
|
||||
}
|
||||
|
||||
core-header-panel {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
core-toolbar {
|
||||
background: #03a9f4;
|
||||
font-size: 1.5rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
paper-fab {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<home-assistant-api auth="{{auth}}" id="api"></home-assistant-api>
|
||||
|
||||
<core-header-panel layout>
|
||||
|
||||
<core-toolbar>
|
||||
<div flex>
|
||||
Home Assistant
|
||||
</div>
|
||||
<core-icon-button icon="developer-mode-tv" on-click="{{handleEventClick}}"></core-icon-button>
|
||||
<core-icon-button icon="settings-remote" on-click="{{handleServiceClick}}"></core-icon-button>
|
||||
</core-toolbar>
|
||||
|
||||
<div class="content" flex>
|
||||
<states-cards api="{{api}}"></states-cards>
|
||||
<paper-fab icon="add" on-click={{handleAddStateClick}}></paper-fab>
|
||||
</div>
|
||||
|
||||
</core-header-panel>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
Polymer({
|
||||
|
||||
ready: function() {
|
||||
this.api = this.$.api;
|
||||
},
|
||||
|
||||
handleEventClick: function() {
|
||||
this.api.showFireEventDialog();
|
||||
},
|
||||
|
||||
handleServiceClick: function() {
|
||||
this.api.showCallServiceDialog();
|
||||
},
|
||||
|
||||
handleAddStateClick: function() {
|
||||
this.api.showSetStateDialog();
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
</polymer-element>
|
@ -0,0 +1,69 @@
|
||||
<link rel="import" href="bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="bower_components/paper-dialog/paper-dialog.html">
|
||||
<link rel="import" href="bower_components/paper-dialog/paper-dialog-transition.html">
|
||||
<link rel="import" href="bower_components/paper-button/paper-button.html">
|
||||
<link rel="import" href="bower_components/paper-input/paper-input.html">
|
||||
|
||||
<link rel="import" href="services-list.html">
|
||||
|
||||
<polymer-element name="service-call-dialog" attributes="api">
|
||||
<template>
|
||||
<style>
|
||||
paper-input:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.serviceContainer {
|
||||
margin-left: 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<paper-dialog id="dialog" heading="Call Service" transition="paper-dialog-transition-bottom" backdrop="true">
|
||||
<div layout horizontal>
|
||||
<div>
|
||||
<paper-input id="inputDomain" label="Domain" floatingLabel="true" autofocus required></paper-input>
|
||||
<paper-input id="inputService" label="Service" floatingLabel="true" required></paper-input>
|
||||
<paper-input id="inputData" label="Service Data (JSON, optional)" floatingLabel="true" multiline></paper-input>
|
||||
</div>
|
||||
<div class='serviceContainer'>
|
||||
<b>Available services:</b>
|
||||
<services-list api={{api}} cbServiceClicked={{serviceSelected}}></event-list>
|
||||
</div>
|
||||
</div>
|
||||
<paper-button dismissive>Cancel</paper-button>
|
||||
<paper-button affirmative on-click={{clickCallService}}>Call Service</paper-button>
|
||||
</paper-dialog>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
Polymer({
|
||||
ready: function() {
|
||||
// to ensure callback methods work..
|
||||
this.serviceSelected = this.serviceSelected.bind(this)
|
||||
},
|
||||
|
||||
show: function(domain, service, serviceData) {
|
||||
this.setService(domain, service);
|
||||
this.$.inputData.value = serviceData;
|
||||
this.$.dialog.toggle();
|
||||
},
|
||||
|
||||
setService: function(domain, service) {
|
||||
this.$.inputDomain.value = domain;
|
||||
this.$.inputService.value = service;
|
||||
},
|
||||
|
||||
serviceSelected: function(domain, service) {
|
||||
this.setService(domain, service);
|
||||
},
|
||||
|
||||
clickCallService: function() {
|
||||
this.api.call_service(
|
||||
this.$.inputDomain.value,
|
||||
this.$.inputService.value,
|
||||
this.$.inputData.value
|
||||
)
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</polymer-element>
|
@ -0,0 +1,74 @@
|
||||
<link rel="import" href="bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="bower_components/core-menu/core-menu.html">
|
||||
<link rel="import" href="bower_components/core-menu/core-submenu.html">
|
||||
<link rel="import" href="bower_components/core-item/core-item.html">
|
||||
|
||||
<polymer-element name="services-list" attributes="api cbServiceClicked">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
core-menu {
|
||||
margin-top: 0;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
a {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template if={{cbServiceClicked}}>
|
||||
<style>
|
||||
a {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</template>
|
||||
|
||||
<div>
|
||||
<core-menu selected="0">
|
||||
|
||||
<template repeat="{{serv in services}}">
|
||||
<core-submenu icon="settings" label="{{serv.domain}}">
|
||||
<template repeat="{{service in serv.services}}">
|
||||
<a on-click={{serviceClicked}} data-domain={{serv.domain}}>{{service}}</a>
|
||||
</template>
|
||||
</core-submenu>
|
||||
</template>
|
||||
|
||||
</core-menu>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
Polymer({
|
||||
services: [],
|
||||
cbServiceClicked: null,
|
||||
|
||||
domReady: function() {
|
||||
this.services = this.api.services
|
||||
|
||||
this.api.addEventListener('services-updated', this.servicesUpdated.bind(this))
|
||||
},
|
||||
|
||||
servicesUpdated: function() {
|
||||
this.services = this.api.services;
|
||||
},
|
||||
|
||||
serviceClicked: function(ev) {
|
||||
if(this.cbServiceClicked) {
|
||||
var target = ev.path[0];
|
||||
var domain = target.getAttributeNode("data-domain").value;
|
||||
var service = target.innerHTML;
|
||||
|
||||
this.cbServiceClicked(domain, service);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
</polymer-element>
|
139
homeassistant/components/http/www_static/polymer/state-card.html
Executable file
139
homeassistant/components/http/www_static/polymer/state-card.html
Executable file
@ -0,0 +1,139 @@
|
||||
<script src="bower_components/moment/moment.js"></script>
|
||||
<link rel="import" href="bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="bower_components/core-tooltip/core-tooltip.html">
|
||||
<link rel="import" href="bower_components/paper-button/paper-button.html">
|
||||
|
||||
<polymer-element name="state-card"
|
||||
attributes="entity state last_changed state_attr cb_turn_on, cb_turn_off cb_edit">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
position: relative;
|
||||
background-color: white;
|
||||
padding: 20px 20px 50px 20px;
|
||||
width: 100%;
|
||||
font-weight: 300;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-transform: capitalize;
|
||||
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.subheader {
|
||||
margin-top: -5px;
|
||||
color: darkgrey;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
paper-button.toggle {
|
||||
color: #03a9f4;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="header" horizontal justified layout>
|
||||
<span class="entity_id">{{entity_id | makeReadable}}</span>
|
||||
<span class='state'>{{state | makeReadable}}</span>
|
||||
</div>
|
||||
|
||||
<div class="subheader" horizontal justified layout>
|
||||
<span class="domain">{{domain}}</span>
|
||||
<core-tooltip label="{{last_changed}}" position="bottom">
|
||||
<span class="last_changed_from_now">{{last_changed_from_now}}</span>
|
||||
</core-tooltip>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="content">
|
||||
<template repeat="{{key in objectKeys(state_attr)}}">
|
||||
<div>{{key | makeReadable}}: {{state_attr[key]}}</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<paper-button class='edit' on-click="{{editClicked}}">EDIT</paper-button>
|
||||
|
||||
<template if="{{state == 'on'}}">
|
||||
<paper-button class="toggle" on-click="{{turn_off}}">TURN OFF</paper-button>
|
||||
</template>
|
||||
<template if="{{state == 'off'}}">
|
||||
<paper-button class="toggle" on-click="{{turn_on}}">TURN ON</paper-button>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
Polymer({
|
||||
// attributes
|
||||
entity: "",
|
||||
state: "",
|
||||
last_changed: "never",
|
||||
state_attr: {},
|
||||
cb_turn_on: null,
|
||||
cb_turn_off: null,
|
||||
cb_edit: null,
|
||||
|
||||
// computed
|
||||
domain: "",
|
||||
entity_id: "",
|
||||
|
||||
entityChanged: function(oldVal, newVal) {
|
||||
var parts = newVal.split(".")
|
||||
|
||||
if(parts.length == 1) {
|
||||
this.domain = ""
|
||||
this.entity_id = parts[0]
|
||||
} else {
|
||||
this.domain = parts[0]
|
||||
this.entity_id = parts.slice(1).join('.')
|
||||
}
|
||||
},
|
||||
|
||||
last_changedChanged: function(oldVal, newVal) {
|
||||
this.last_changed_from_now = moment(this.last_changed, "HH:mm:ss DD-MM-YYYY").fromNow()
|
||||
},
|
||||
|
||||
turn_on: function() {
|
||||
if(this.cb_turn_on) {
|
||||
this.cb_turn_on(this.entity);
|
||||
}
|
||||
},
|
||||
|
||||
turn_off: function() {
|
||||
if(this.cb_turn_off) {
|
||||
this.cb_turn_off(this.entity);
|
||||
}
|
||||
},
|
||||
|
||||
editClicked: function() {
|
||||
if(this.cb_edit) {
|
||||
this.cb_edit(this.entity);
|
||||
}
|
||||
},
|
||||
|
||||
// used as filter
|
||||
makeReadable: function(value) {
|
||||
return value.replace("_", " ")
|
||||
},
|
||||
|
||||
objectKeys: function(obj) {
|
||||
return obj ? Object.keys(obj) : [];
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</polymer-element>
|
@ -0,0 +1,84 @@
|
||||
<link rel="import" href="bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="bower_components/paper-dialog/paper-dialog.html">
|
||||
<link rel="import" href="bower_components/paper-dialog/paper-dialog-transition.html">
|
||||
<link rel="import" href="bower_components/paper-button/paper-button.html">
|
||||
<link rel="import" href="bower_components/paper-input/paper-input.html">
|
||||
|
||||
<link rel="import" href="entity-list.html">
|
||||
|
||||
<polymer-element name="state-set-dialog" attributes="api">
|
||||
<template>
|
||||
<style>
|
||||
paper-input:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.stateContainer {
|
||||
margin-left: 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<paper-dialog id="dialog" heading="Set State" transition="paper-dialog-transition-center" backdrop="true">
|
||||
<div layout horizontal>
|
||||
<div>
|
||||
<paper-input id="inputEntityID" label="Entity ID" floatingLabel="true" autofocus required></paper-input>
|
||||
<paper-input id="inputState" label="State" floatingLabel="true" required></paper-input>
|
||||
<paper-input id="inputData" label="State attributes (JSON, optional)" floatingLabel="true" multiline></paper-input>
|
||||
</div>
|
||||
<div class='stateContainer'>
|
||||
<b>Current entities:</b>
|
||||
<entity-list api={{api}} cbEntityClicked={{entitySelected}}></entity-list>
|
||||
</div>
|
||||
</div>
|
||||
<paper-button dismissive>Cancel</paper-button>
|
||||
<paper-button affirmative on-click={{clickSetState}}>Set State</paper-button>
|
||||
</paper-dialog>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
Polymer({
|
||||
ready: function() {
|
||||
// to ensure callback methods work..
|
||||
this.entitySelected = this.entitySelected.bind(this)
|
||||
},
|
||||
|
||||
show: function(entityId, state, stateData) {
|
||||
this.setEntityId(entityId);
|
||||
this.setState(state);
|
||||
this.setStateData(stateData);
|
||||
|
||||
this.$.dialog.toggle();
|
||||
},
|
||||
|
||||
setEntityId: function(entityId) {
|
||||
this.$.inputEntityID.value = entityId;
|
||||
},
|
||||
|
||||
setState: function(state) {
|
||||
this.$.inputState.value = state;
|
||||
},
|
||||
|
||||
setStateData: function(stateData) {
|
||||
var value = stateData ? JSON.stringify(stateData, null, ' ') : "";
|
||||
|
||||
this.$.inputData.value = value;
|
||||
},
|
||||
|
||||
entitySelected: function(entityId) {
|
||||
this.setEntityId(entityId);
|
||||
|
||||
var state = this.api.getState(entityId);
|
||||
this.setState(state.state);
|
||||
this.setStateData(state.attributes);
|
||||
},
|
||||
|
||||
clickSetState: function() {
|
||||
this.api.set_state(
|
||||
this.$.inputEntityID.value,
|
||||
this.$.inputState.value,
|
||||
JSON.parse(this.$.inputData.value)
|
||||
)
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</polymer-element>
|
64
homeassistant/components/http/www_static/polymer/states-cards.html
Executable file
64
homeassistant/components/http/www_static/polymer/states-cards.html
Executable file
@ -0,0 +1,64 @@
|
||||
<link rel="import" href="bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="state-card.html">
|
||||
|
||||
<polymer-element name="states-cards" attributes="api">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
state-card, state-add-card {
|
||||
display: inline-block;
|
||||
width: 350px;
|
||||
margin: 10px 0 0 10px;
|
||||
}
|
||||
|
||||
state-add-card {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div horizontal layout wrap>
|
||||
|
||||
<template repeat="{{state in states}}">
|
||||
<state-card
|
||||
entity="{{state.entity_id}}"
|
||||
state="{{state.state}}"
|
||||
last_changed="{{state.last_changed}}"
|
||||
state_attr="{{state.attributes}}"
|
||||
cb_turn_on="{{api.turn_on}}"
|
||||
cb_turn_off="{{api.turn_off}}"
|
||||
cb_edit={{editCallback}}>
|
||||
</state-card>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
Polymer({
|
||||
states: [],
|
||||
|
||||
ready: function() {
|
||||
this.editCallback = this.editCallback.bind(this);
|
||||
},
|
||||
|
||||
domReady: function() {
|
||||
this.states = this.api.states
|
||||
|
||||
this.api.addEventListener('states-updated', this.statesUpdated.bind(this))
|
||||
},
|
||||
|
||||
statesUpdated: function() {
|
||||
this.states = this.api.states;
|
||||
},
|
||||
|
||||
editCallback: function(entityId) {
|
||||
this.api.showEditStateDialog(entityId);
|
||||
},
|
||||
|
||||
});
|
||||
</script>
|
||||
</polymer-element>
|
Loading…
x
Reference in New Issue
Block a user