From 8a8097af99dd971d4e698fcf2d7986e972c8a7ea Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> Date: Wed, 22 Oct 2014 00:02:18 -0700 Subject: [PATCH] Initial commit Polymer interface --- .../http/www_static/polymer/bower.json | 30 ++ .../http/www_static/polymer/entity-list.html | 55 ++++ .../www_static/polymer/event-fire-dialog.html | 71 +++++ .../http/www_static/polymer/events-list.html | 58 ++++ .../polymer/home-assistant-api.html | 270 ++++++++++++++++++ .../polymer/home-assistant-main.html | 79 +++++ .../polymer/service-call-dialog.html | 69 +++++ .../www_static/polymer/services-list.html | 74 +++++ .../http/www_static/polymer/state-card.html | 139 +++++++++ .../www_static/polymer/state-set-dialog.html | 84 ++++++ .../http/www_static/polymer/states-cards.html | 64 +++++ 11 files changed, 993 insertions(+) create mode 100644 homeassistant/components/http/www_static/polymer/bower.json create mode 100644 homeassistant/components/http/www_static/polymer/entity-list.html create mode 100644 homeassistant/components/http/www_static/polymer/event-fire-dialog.html create mode 100644 homeassistant/components/http/www_static/polymer/events-list.html create mode 100644 homeassistant/components/http/www_static/polymer/home-assistant-api.html create mode 100644 homeassistant/components/http/www_static/polymer/home-assistant-main.html create mode 100644 homeassistant/components/http/www_static/polymer/service-call-dialog.html create mode 100644 homeassistant/components/http/www_static/polymer/services-list.html create mode 100755 homeassistant/components/http/www_static/polymer/state-card.html create mode 100644 homeassistant/components/http/www_static/polymer/state-set-dialog.html create mode 100755 homeassistant/components/http/www_static/polymer/states-cards.html diff --git a/homeassistant/components/http/www_static/polymer/bower.json b/homeassistant/components/http/www_static/polymer/bower.json new file mode 100644 index 00000000000..f83f815face --- /dev/null +++ b/homeassistant/components/http/www_static/polymer/bower.json @@ -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" + } +} diff --git a/homeassistant/components/http/www_static/polymer/entity-list.html b/homeassistant/components/http/www_static/polymer/entity-list.html new file mode 100644 index 00000000000..a76d6a82432 --- /dev/null +++ b/homeassistant/components/http/www_static/polymer/entity-list.html @@ -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> diff --git a/homeassistant/components/http/www_static/polymer/event-fire-dialog.html b/homeassistant/components/http/www_static/polymer/event-fire-dialog.html new file mode 100644 index 00000000000..9a132769329 --- /dev/null +++ b/homeassistant/components/http/www_static/polymer/event-fire-dialog.html @@ -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> diff --git a/homeassistant/components/http/www_static/polymer/events-list.html b/homeassistant/components/http/www_static/polymer/events-list.html new file mode 100644 index 00000000000..bd08b5e3003 --- /dev/null +++ b/homeassistant/components/http/www_static/polymer/events-list.html @@ -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> diff --git a/homeassistant/components/http/www_static/polymer/home-assistant-api.html b/homeassistant/components/http/www_static/polymer/home-assistant-api.html new file mode 100644 index 00000000000..8bad3463f9e --- /dev/null +++ b/homeassistant/components/http/www_static/polymer/home-assistant-api.html @@ -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> diff --git a/homeassistant/components/http/www_static/polymer/home-assistant-main.html b/homeassistant/components/http/www_static/polymer/home-assistant-main.html new file mode 100644 index 00000000000..1f068b9eb93 --- /dev/null +++ b/homeassistant/components/http/www_static/polymer/home-assistant-main.html @@ -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> diff --git a/homeassistant/components/http/www_static/polymer/service-call-dialog.html b/homeassistant/components/http/www_static/polymer/service-call-dialog.html new file mode 100644 index 00000000000..4429623081e --- /dev/null +++ b/homeassistant/components/http/www_static/polymer/service-call-dialog.html @@ -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> diff --git a/homeassistant/components/http/www_static/polymer/services-list.html b/homeassistant/components/http/www_static/polymer/services-list.html new file mode 100644 index 00000000000..715e5b6a9bf --- /dev/null +++ b/homeassistant/components/http/www_static/polymer/services-list.html @@ -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> diff --git a/homeassistant/components/http/www_static/polymer/state-card.html b/homeassistant/components/http/www_static/polymer/state-card.html new file mode 100755 index 00000000000..ad618a7372d --- /dev/null +++ b/homeassistant/components/http/www_static/polymer/state-card.html @@ -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> diff --git a/homeassistant/components/http/www_static/polymer/state-set-dialog.html b/homeassistant/components/http/www_static/polymer/state-set-dialog.html new file mode 100644 index 00000000000..acdac30b3b8 --- /dev/null +++ b/homeassistant/components/http/www_static/polymer/state-set-dialog.html @@ -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> diff --git a/homeassistant/components/http/www_static/polymer/states-cards.html b/homeassistant/components/http/www_static/polymer/states-cards.html new file mode 100755 index 00000000000..d650aae0671 --- /dev/null +++ b/homeassistant/components/http/www_static/polymer/states-cards.html @@ -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> -- GitLab