diff --git a/front/build/asset-manifest.json b/front/build/asset-manifest.json index c3063771f..e2794c36f 100644 --- a/front/build/asset-manifest.json +++ b/front/build/asset-manifest.json @@ -1,14 +1,14 @@ { "files": { "main.css": "/static/css/main.2d15d020.chunk.css", - "main.js": "/static/js/main.f5e71cab.chunk.js", - "main.js.map": "/static/js/main.f5e71cab.chunk.js.map", + "main.js": "/static/js/main.6564749c.chunk.js", + "main.js.map": "/static/js/main.6564749c.chunk.js.map", "runtime-main.js": "/static/js/runtime-main.db8f2875.js", "runtime-main.js.map": "/static/js/runtime-main.db8f2875.js.map", "static/js/2.b6bfd886.chunk.js": "/static/js/2.b6bfd886.chunk.js", "static/js/2.b6bfd886.chunk.js.map": "/static/js/2.b6bfd886.chunk.js.map", "index.html": "/index.html", - "precache-manifest.f6516c056036507f2e00fe494f9e0d7a.js": "/precache-manifest.f6516c056036507f2e00fe494f9e0d7a.js", + "precache-manifest.92352c6ecf63a4676b0a3ef3a7b5b2a8.js": "/precache-manifest.92352c6ecf63a4676b0a3ef3a7b5b2a8.js", "service-worker.js": "/service-worker.js", "static/css/main.2d15d020.chunk.css.map": "/static/css/main.2d15d020.chunk.css.map", "static/js/2.b6bfd886.chunk.js.LICENSE.txt": "/static/js/2.b6bfd886.chunk.js.LICENSE.txt" @@ -17,6 +17,6 @@ "static/js/runtime-main.db8f2875.js", "static/js/2.b6bfd886.chunk.js", "static/css/main.2d15d020.chunk.css", - "static/js/main.f5e71cab.chunk.js" + "static/js/main.6564749c.chunk.js" ] } \ No newline at end of file diff --git a/front/build/index.html b/front/build/index.html index a4761d85f..f3f47d644 100644 --- a/front/build/index.html +++ b/front/build/index.html @@ -1 +1 @@ -Homeware-LAN
\ No newline at end of file +Homeware-LAN
\ No newline at end of file diff --git a/front/build/precache-manifest.f6516c056036507f2e00fe494f9e0d7a.js b/front/build/precache-manifest.92352c6ecf63a4676b0a3ef3a7b5b2a8.js similarity index 72% rename from front/build/precache-manifest.f6516c056036507f2e00fe494f9e0d7a.js rename to front/build/precache-manifest.92352c6ecf63a4676b0a3ef3a7b5b2a8.js index caa089a76..afd0ffd68 100644 --- a/front/build/precache-manifest.f6516c056036507f2e00fe494f9e0d7a.js +++ b/front/build/precache-manifest.92352c6ecf63a4676b0a3ef3a7b5b2a8.js @@ -1,10 +1,10 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([ { - "revision": "272c561c9c54b570ba6ff4ee01d5fc9d", + "revision": "0e341a28acee7a6a5733c503eaca59bf", "url": "/index.html" }, { - "revision": "c7b8bd7a8e25bf695c7a", + "revision": "bdca616ef5c466f85a3d", "url": "/static/css/main.2d15d020.chunk.css" }, { @@ -16,8 +16,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([ "url": "/static/js/2.b6bfd886.chunk.js.LICENSE.txt" }, { - "revision": "c7b8bd7a8e25bf695c7a", - "url": "/static/js/main.f5e71cab.chunk.js" + "revision": "bdca616ef5c466f85a3d", + "url": "/static/js/main.6564749c.chunk.js" }, { "revision": "ef13c11e300e1acbb1b7", diff --git a/front/build/service-worker.js b/front/build/service-worker.js index 9f2dc17dc..11e5ff24c 100644 --- a/front/build/service-worker.js +++ b/front/build/service-worker.js @@ -14,7 +14,7 @@ importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); importScripts( - "/precache-manifest.f6516c056036507f2e00fe494f9e0d7a.js" + "/precache-manifest.92352c6ecf63a4676b0a3ef3a7b5b2a8.js" ); self.addEventListener('message', (event) => { diff --git a/front/build/static/js/main.6564749c.chunk.js b/front/build/static/js/main.6564749c.chunk.js new file mode 100644 index 000000000..db588a4b7 --- /dev/null +++ b/front/build/static/js/main.6564749c.chunk.js @@ -0,0 +1,2 @@ +(this.webpackJsonpHomeware=this.webpackJsonpHomeware||[]).push([[0],{13:function(e,t,a){},139:function(e,t,a){"use strict";a.r(t);var i=a(0),n=a.n(i),s=a(40),r=a.n(s),c=(a(48),a(1)),l=a(2),o=a(5),d=a(4),m=a(3),u=(a(49),a(41)),p=a(7);var v=function(e){for(var t=e+"=",a=decodeURIComponent(document.cookie).split(";"),i=0;i"),n.a.createElement("option",null,"<="),n.a.createElement("option",null,">=")))),i,n.a.createElement("div",{className:"trigger_assisstant_buttons_container"},n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.addTriggerOperation},"Save"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button red_button",onClick:this.props.closeTriggerAssistant},"Cancel")))}}]),a}(n.a.Component),Ae=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={device_a:"",device_b:""},i.updateDependencies=i.updateDependencies.bind(Object(o.a)(i)),i.addTriggerOperation=i.addTriggerOperation.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"updateDependencies",value:function(e){var t=this.state;t[e.target.id]=e.target.value,this.setState(t)}},{key:"addTriggerOperation",value:function(){var e=document.getElementById("device_a").value+":"+document.getElementById("param_a").value+":"+document.getElementById("comparator").value+":"+document.getElementById("device_b").value+":"+document.getElementById("param_b").value;this.props.addTriggerOperation("d2d",e),this.props.closeTriggerAssistant()}},{key:"render",value:function(){var e=this,t=Object.keys(this.props.devices).map((function(t){return n.a.createElement("option",{key:t,value:t},e.props.devices[t])})),a=""===this.state.device_a?"":Object.keys(this.props.status[this.state.device_a]).map((function(e){return n.a.createElement("option",{key:e,value:e},b.params[e]?b.params[e].name:e+" - Not supported yet")})),i=""===this.state.device_b?"":Object.keys(this.props.status[this.state.device_b]).map((function(e){return n.a.createElement("option",{key:e,value:e},b.params[e]?b.params[e].name:e+" - Not supported yet")}));return n.a.createElement("div",{className:"trigger_assistant_container"},n.a.createElement("h2",{className:"trigger_assistant_title"},"Compare two devices"),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Device A*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"device_a",onChange:this.updateDependencies},n.a.createElement("option",{value:""},"Select a device"),t))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Param A*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"param_a",onChange:this.updateDependencies},n.a.createElement("option",{value:""},"Select a param"),a))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Comparator*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"comparator"},n.a.createElement("option",null,"="),n.a.createElement("option",null,"<"),n.a.createElement("option",null,">"),n.a.createElement("option",null,"<="),n.a.createElement("option",null,">=")))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Device B*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"device_b",onChange:this.updateDependencies},n.a.createElement("option",{value:""},"Select a device"),t))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Param B*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"param_b",onChange:this.updateDependencies},n.a.createElement("option",{value:""},"Select a param"),i))),n.a.createElement("div",{className:"trigger_assisstant_buttons_container"},n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.addTriggerOperation},"Save"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button red_button",onClick:this.props.closeTriggerAssistant},"Cancel")))}}]),a}(n.a.Component),De=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={type:""},i.timeTigger=i.timeTigger.bind(Object(o.a)(i)),i.deiceTrigger=i.deiceTrigger.bind(Object(o.a)(i)),i.deviceToDeviceTrigger=i.deviceToDeviceTrigger.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"timeTigger",value:function(){this.setState({type:"time"})}},{key:"deiceTrigger",value:function(){this.setState({type:"device"})}},{key:"deviceToDeviceTrigger",value:function(){this.setState({type:"device2device"})}},{key:"render",value:function(){return""===this.state.type?n.a.createElement("div",{className:"trigger_assistant_container"},n.a.createElement("h2",{className:"trigger_assistant_title"},"Add a new trigger"),n.a.createElement("div",{className:"trigger_assisstant_buttons_container"},n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.timeTigger},"Time"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.deiceTrigger},"Device"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.deviceToDeviceTrigger},"Device to device"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button red_button",onClick:this.props.closeTriggerAssistant},"Cancel"))):"time"===this.state.type?n.a.createElement(Me,{closeTriggerAssistant:this.props.closeTriggerAssistant,addTriggerOperation:this.props.addTriggerOperation}):"device"===this.state.type?n.a.createElement(Le,{devices:this.props.devices,status:this.props.status,closeTriggerAssistant:this.props.closeTriggerAssistant,addTriggerOperation:this.props.addTriggerOperation}):"device2device"===this.state.type?n.a.createElement(Ae,{devices:this.props.devices,status:this.props.status,closeTriggerAssistant:this.props.closeTriggerAssistant,addTriggerOperation:this.props.addTriggerOperation}):void 0}}]),a}(n.a.Component),Ie=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).delete=i.delete.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"delete",value:function(){this.props.delete(this.props.id)}},{key:"render",value:function(){return n.a.createElement("div",{className:"trigger_device_container",style:{marginBottom:"10px"}},n.a.createElement("span",null,(this.props.devices[this.props.target.device]?this.props.devices[this.props.target.device]:this.props.target.device)+" ("+(b.params[this.props.target.param]?b.params[this.props.target.param].name:this.props.target.param)+") = "+this.props.target.value),n.a.createElement("img",{src:"/global/bin_icon.png",alt:"Delete icon",className:"trigger_delete",onClick:this.delete}))}}]),a}(n.a.Component),He=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={device:""},i.updateDevice=i.updateDevice.bind(Object(o.a)(i)),i.updateParam=i.updateParam.bind(Object(o.a)(i)),i.addTarget=i.addTarget.bind(Object(o.a)(i)),i.typeConversion=i.typeConversion.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"updateDevice",value:function(e){this.setState({device:e.target.value})}},{key:"updateParam",value:function(e){this.setState({param:e.target.value})}},{key:"addTarget",value:function(){var e={device:document.getElementById("device").value,param:document.getElementById("param").value,value:document.getElementById("value").value};this.props.addTarget(e),document.getElementById("device").value="",document.getElementById("param").value="",this.setState({param:""})}},{key:"typeConversion",value:function(e){return{int:"d2i",list:"d2l",bool:"d2b",string:"d2s",color:"d2c"}[e]}},{key:"render",value:function(){var e=this,t=Object.keys(this.props.devices).map((function(t){return n.a.createElement("option",{key:t,value:t},e.props.devices[t])})),a=""===this.state.device?"":Object.keys(this.props.status[this.state.device]).map((function(e){return n.a.createElement("option",{key:e,value:e},b.params[e]?b.params[e].name:e+" - Not supported yet")})),i="";if(b.params[this.state.param]){var s=this.typeConversion(b.params[this.state.param].type);if("d2i"===s)i=n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Value*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"number",className:"",id:"value"})));else if("d2s"===s)i=n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Value*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"",id:"value"})));else if("d2b"===s||"d2l"===s){var r=b.params[this.state.param].select.map((function(e){return n.a.createElement("option",{key:e,value:e},e)}));i=n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Value*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"value"},r)))}}return n.a.createElement("div",{className:"trigger_assistant_container"},n.a.createElement("h2",{className:"trigger_assistant_title"},"New target"),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Device*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"device",onChange:this.updateDevice},n.a.createElement("option",{value:""},"Select a device"),t))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Param*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"param",onChange:this.updateParam},n.a.createElement("option",{value:""},"Select a param"),a))),i,n.a.createElement("div",{className:"trigger_assisstant_buttons_container"},n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.addTarget},"Add")))}}]),a}(n.a.Component),Pe=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;Object(c.a)(this,a),i=t.call(this,e);var n=window.location.pathname.split("/")[3],s=!1;return""===n&&(s=!0),i.state={id:n,create:s,save_status:"",trigger_assistant_parent:0,task:{title:"",description:"",triggers:{},target:[]},devices:[],status:{}},i.update=i.update.bind(Object(o.a)(i)),i.save=i.save.bind(Object(o.a)(i)),i.delete=i.delete.bind(Object(o.a)(i)),i.deleteTrigger=i.deleteTrigger.bind(Object(o.a)(i)),i.addTriggerLogic=i.addTriggerLogic.bind(Object(o.a)(i)),i.openTriggerAssistant=i.openTriggerAssistant.bind(Object(o.a)(i)),i.addTriggerOperation=i.addTriggerOperation.bind(Object(o.a)(i)),i.closeTriggerAssistant=i.closeTriggerAssistant.bind(Object(o.a)(i)),i.addTarget=i.addTarget.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"componentDidMount",value:function(){var e=new XMLHttpRequest;if(e.onload=function(t){if(4===e.readyState)if(200===e.status){var a=JSON.parse(e.responseText),i={};a.devices.forEach((function(e){i[e.id]=e.name.name})),this.setState({devices:i,status:a.status})}else console.error(e.statusText)}.bind(this),e.open("GET",h+"api/global/get/"),e.setRequestHeader("authorization","baerer "+v("token")),e.send(),!this.state.create){var t=new XMLHttpRequest;t.onload=function(e){if(4===t.readyState)if(200===t.status){var a=JSON.parse(t.responseText);console.log(a),this.setState({task:a})}else console.error(t.statusText)}.bind(this),t.open("GET",h+"api/tasks/get/"+this.state.id+"/"),t.setRequestHeader("authorization","baerer "+v("token")),t.send()}}},{key:"update",value:function(e){var t=this.state.task;t[e.target.id]=e.target.value,this.setState({task:t})}},{key:"save",value:function(){var e=new XMLHttpRequest;e.onload=function(t){4===e.readyState&&(200===e.status?(JSON.parse(e.responseText),this.state.create?window.location.href="/tasks":this.setState({save_status:"Saved correctly."})):(console.error(e.statusText),this.setState({save_status:"Error, the changes haven't been saved."})),setTimeout(function(){this.setState({save_status:""})}.bind(this),5e3))}.bind(this);var t={task:this.state.task};this.state.create?e.open("POST",h+"api/tasks/create/"):(e.open("POST",h+"api/tasks/update/"),t.id=this.state.id),e.setRequestHeader("Content-Type","application/json;charset=UTF-8"),e.setRequestHeader("authorization","baerer "+v("token")),e.send(JSON.stringify(t))}},{key:"delete",value:function(){if(window.confirm("Do you want to delete the task?")){var e=new XMLHttpRequest;e.onload=function(t){4===e.readyState&&(200===e.status?window.location.href="/tasks/":(console.error(e.statusText),this.setState({save_status:"Error, the device hasn't been deleted."})),setTimeout(function(){this.setState({save_status:""})}.bind(this),5e3))}.bind(this),e.open("GET",h+"api/tasks/delete/"+this.state.id+"/"),e.setRequestHeader("authorization","baerer "+v("token")),e.send()}else this.setState({save_status:"Ok. The device is save."})}},{key:"deleteTrigger",value:function(e){var t=this.state.task,a=t.triggers,i=a[e].parent;if("triggers"!==i){var n=a[i].operation.indexOf(e);a[i].operation.splice(n,1),delete a[e],t.triggers=a}else t.triggers={};this.setState({task:t})}},{key:"addTriggerLogic",value:function(e,t){var a=this.state.task;if("triggers"!==t){var i=Date.now();a.triggers[i]={operation:[],parent:t,type:e},a.triggers[t].operation.push(i)}else a.triggers.trigger={operation:[],parent:"triggers",type:e};this.setState({task:a})}},{key:"openTriggerAssistant",value:function(e){this.setState({trigger_assistant_parent:e})}},{key:"addTriggerOperation",value:function(e,t){var a=this.state.task,i=this.state.trigger_assistant_parent;if("triggers"!==i){var n=Date.now();a.triggers[n]={operation:t,parent:i,type:e},a.triggers[i].operation.push(n)}else a.triggers.trigger={operation:t,parent:"triggers",type:e};this.setState({task:a})}},{key:"closeTriggerAssistant",value:function(){this.setState({trigger_assistant_parent:0})}},{key:"addTarget",value:function(e){var t=this.state.task;t.target.push(e),this.setState({task:t})}},{key:"render",value:function(){var e=this,t=this.state.task.target.map((function(t,a){return n.a.createElement(Ie,{key:a,target:t,devices:e.state.devices})}));return n.a.createElement("div",{className:"page_block_container"},n.a.createElement("h2",null,"Task"),n.a.createElement("hr",{style:{width:"70%"}}),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Name*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"title",defaultValue:this.state.task.title,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Description*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"description",defaultValue:this.state.task.description,onChange:this.update}))),n.a.createElement("hr",null),n.a.createElement("h2",null,"Triggers"),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null)),0!==this.state.trigger_assistant_parent?n.a.createElement(De,{devices:this.state.devices,status:this.state.status,closeTriggerAssistant:this.closeTriggerAssistant,addTriggerOperation:this.addTriggerOperation}):n.a.createElement(Re,{id:"trigger",triggers:this.state.task.triggers,devices:this.state.devices,delete:this.deleteTrigger,addTriggerLogic:this.addTriggerLogic,openTriggerAssistant:this.openTriggerAssistant}),n.a.createElement("hr",null),n.a.createElement("h2",null,"Targets"),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null)),t,n.a.createElement(He,{devices:this.state.devices,status:this.state.status,addTarget:this.addTarget}),n.a.createElement("hr",null),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("button",{type:"button",style:this.state.create?{backgroundColor:"red",opacity:"0.2"}:{backgroundColor:"red"},onClick:this.delete,disabled:!!this.state.create},"Delete"),n.a.createElement("button",{type:"button",onClick:this.save},"Save"),n.a.createElement("span",null,this.state.save_status))))}}]),a}(n.a.Component),Fe=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={settings:{google:{},ddns:{},mqtt:{},apikey:""},save_status:"",url:{auth:"",token:"",fulfillment:""}},i.update=i.update.bind(Object(o.a)(i)),i.enableDdnsProvider=i.enableDdnsProvider.bind(Object(o.a)(i)),i.save=i.save.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"componentDidMount",value:function(){if(!this.state.create){var e=new XMLHttpRequest;e.onload=function(t){if(4===e.readyState)if(200===e.status){var a=JSON.parse(e.responseText);this.setState({settings:a,url:{auth:"https://"+a.ddns.hostname+"/auth/",token:"https://"+a.ddns.hostname+"/token/",fulfillment:"https://"+a.ddns.hostname+"/smarthome/"}})}else console.error(e.statusText)}.bind(this),e.open("GET",h+"api/settings/get/"),e.setRequestHeader("authorization","baerer "+v("token")),e.send()}}},{key:"update",value:function(e){var t=e.target.id.split("/"),a=this.state.settings;1===t.length?a[t[0]]=e.target.value:2===t.length&&(a[t[0]][t[1]]=e.target.value),this.setState({settings:a})}},{key:"enableDdnsProvider",value:function(e){var t=this.state.settings;t.ddns.enabled=e,this.setState({settings:t})}},{key:"save",value:function(){var e=new XMLHttpRequest;e.onload=function(t){4===e.readyState&&(200===e.status?(JSON.parse(e.responseText),this.setState({save_status:"Saved correctly."})):this.setState({save_status:"Error, the changes haven't been saved."}),setTimeout(function(){this.setState({save_status:""})}.bind(this),5e3))}.bind(this),e.open("POST",h+"api/settings/update/"),e.setRequestHeader("Content-Type","application/json;charset=UTF-8"),e.setRequestHeader("authorization","baerer "+v("token")),e.send(JSON.stringify(this.state.settings))}},{key:"render",value:function(){return n.a.createElement("div",null,n.a.createElement("div",{className:"page_block_container"},n.a.createElement("h2",null,"Actions on Google"),n.a.createElement("hr",null),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Client ID"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"google/client_id",defaultValue:this.state.settings.google.client_id,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Client Secret"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"google/client_secret",defaultValue:this.state.settings.google.client_secret,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Authorization URL"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",defaultValue:this.state.url.auth,disabled:!0}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Token URL"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",defaultValue:this.state.url.token,disabled:!0}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Fulfillment URL"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",defaultValue:this.state.url.fulfillment,disabled:!0})))),n.a.createElement("div",{className:"page_block_buttons_container"},n.a.createElement("button",{type:"button",onClick:this.save},"Save"),n.a.createElement("span",null,this.state.save_status)),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null,"Actions on Google settings. It is used to authenticate with Google. If you change it here, you must change it on the Actions Console > Develop > Account Linking."))),n.a.createElement("div",{className:"page_block_container"},n.a.createElement("h2",null,"MQTT"),n.a.createElement("hr",null),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"User"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"mqtt/user",defaultValue:this.state.settings.mqtt.user,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Password"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"mqtt/password",defaultValue:this.state.settings.mqtt.password,onChange:this.update})))),n.a.createElement("div",{className:"page_block_buttons_container"},n.a.createElement("button",{type:"button",onClick:this.save},"Save"),n.a.createElement("span",null,this.state.save_status)),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null,"Important. You must configure the username and password into Mosquitto manually from a terminal. This is only for telling Homeware its credentials. Clear both if you don't use credentials."))),n.a.createElement("div",{className:"page_block_container"},n.a.createElement("h2",null,"DDNS provider"),n.a.createElement("hr",null),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Status:"),n.a.createElement("div",{className:"two_table_cel"},this.state.settings.ddns.status)),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"IP and time:"),n.a.createElement("div",{className:"two_table_cel"},this.state.settings.ddns.ip+" updated at "+this.state.settings.ddns.last))),n.a.createElement("hr",null),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Enable"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement(ie.a,{onChange:this.enableDdnsProvider,checked:this.state.settings.ddns.enabled}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Provider"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"settings_select",id:"ddns/provider",value:this.state.settings.ddns.provider,onChange:this.update},n.a.createElement("option",{value:"noip"},"Noip")))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Username"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"ddns/username",defaultValue:this.state.settings.ddns.username,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Password"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"ddns/password",defaultValue:this.state.settings.ddns.password,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Hostname"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"ddns/hostname",defaultValue:this.state.settings.ddns.hostname,onChange:this.update})))),n.a.createElement("div",{className:"page_block_buttons_container"},n.a.createElement("button",{type:"button",onClick:this.save},"Save"),n.a.createElement("span",null,this.state.save_status)),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null,"Set up the access data to the DDNS provider account. Open an issue on Github if you want a DDNS provider that is not listed."))))}}]),a}(n.a.Component);var qe=function(e){return n.a.createElement("div",{style:{marginTop:"5px",width:"100%",display:"grid",gridTemplateColumns:"70% 30%"}},n.a.createElement("div",{style:{textAlign:"left",paddingTop:"4px"}},n.a.createElement("span",{style:{fontSize:"18px"}},e.title)),n.a.createElement("div",{style:{textAlign:"right",paddingTop:"4px"}},n.a.createElement("span",{style:"Running"===e.status?{fontSize:"12px",fontWeight:"bold",color:"white",backgroundColor:"green",padding:"5px",paddingLeft:"10px",paddingRight:"10px",borderRadius:"5px"}:{fontSize:"12px",fontWeight:"bold",color:"white",backgroundColor:"red",padding:"5px",paddingLeft:"10px",paddingRight:"10px",borderRadius:"5px"}},e.status)))},Ge=a(54),Ue=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={components:[],git:{version:"",description:"",code:0},version:"",upgrading:!1,show_system_message:!1,system_message:""},i.loadComponents=i.loadComponents.bind(Object(o.a)(i)),i.upgrade=i.upgrade.bind(Object(o.a)(i)),i.areYouAwake=i.areYouAwake.bind(Object(o.a)(i)),i.restart=i.restart.bind(Object(o.a)(i)),i.reboot=i.reboot.bind(Object(o.a)(i)),i.shutdown=i.shutdown.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"componentDidMount",value:function(){this.loadComponents(),setInterval(this.loadComponents,3e3);var e=new XMLHttpRequest;e.onload=function(t){if(4===e.readyState)if(200===e.status){var a=JSON.parse(e.responseText);this.setState({version:a.version})}else console.error(e.statusText)}.bind(this),e.open("GET",h+"api/global/version/"),e.setRequestHeader("authorization","baerer "+v("token")),e.send();var t=new XMLHttpRequest;t.onload=function(e){if(4===t.readyState)if(200===t.status){var a=JSON.parse(t.responseText),i=a.body;this.setState({git:{version:a.tag_name,description:i,code:200}})}else 403===t.status?this.setState({git:{version:"GitHub rate limit exceeded. You have reloaded so many times. It will reset after some time.",code:403}}):console.error(t.statusText)}.bind(this),t.open("GET","https://api.github.com/repos/kikeelectronico/Homeware-LAN/releases/latest"),t.send()}},{key:"loadComponents",value:function(){var e=new XMLHttpRequest;e.onload=function(t){if(4===e.readyState)if(200===e.status){for(var a=JSON.parse(e.responseText),i=[],n=Object.keys(a),s=0;s1&&this.setState({page:this.state.page-1})}},{key:"nextPage",value:function(){this.state.page\n
\n {\n
\n
\n { props.title }\n
\n \n );\n}\n\nexport default Menu\n","import React from 'react';\nimport getCookieValue from '../../../functions'\nimport { root } from '../../../constants'\n\nclass OnOff extends React.Component {\n constructor(props) {\n super(props);\n this.toggle = this.toggle.bind(this);\n }\n\n toggle(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n this.props.reload();\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this)\n http.open(\"POST\", root + \"api/status/update/\");\n http.setRequestHeader(\"Content-Type\", \"application/json;charset=UTF-8\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send(JSON.stringify({\n \"id\": this.props.id,\n \"param\": \"on\",\n \"value\": !this.props.on\n }));\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n return (\n
\n {\n
\n );\n }\n}\n\nexport default OnOff\n","import React from 'react';\n\nclass Information extends React.Component {\n constructor(props) {\n super(props);\n this.go = this.go.bind(this);\n }\n\n go(){\n window.location.href = \"/devices/info/\" + this.props.id + \"/\"\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n return (\n
\n {\n
\n );\n }\n}\n\nexport default Information\n","import React from 'react';\n\nclass Connecting extends React.Component {\n constructor(props) {\n super(props);\n this.go = this.go.bind(this);\n }\n\n go(){\n window.location.href = \"/devices/connecting/\" + this.props.id + \"/\"\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n return (\n
\n {\n
\n );\n }\n}\n\nexport default Connecting\n","import React from 'react';\n\nclass Edit extends React.Component {\n constructor(props) {\n super(props);\n this.go = this.go.bind(this);\n }\n\n go(){\n window.location.href = \"/devices/editor/\" + this.props.id + \"/\"\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n return (\n
\n {\n
\n );\n }\n}\n\nexport default Edit\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Light extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\" && Object.keys(this.props.status).includes(\"color\"))){\n if (Object.keys(this.props.status.color).includes(\"spectrumRgb\"))\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n else\n color = \"#\" + this.props.status.color.spectrumRGB.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Light\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Outlet extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'blue',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Outlet\n","import React from 'react';\nimport getCookieValue from '../../../functions'\nimport { root } from '../../../constants'\n\nclass TemperatureSetting extends React.Component {\n constructor(props) {\n super(props);\n this.up = this.up.bind(this);\n this.down = this.down.bind(this);\n this.update = this.update.bind(this);\n }\n\n up(){\n var temperature = this.props.status.thermostatTemperatureSetpoint + 1;\n this.update(temperature)\n }\n\n down(){\n var temperature = this.props.status.thermostatTemperatureSetpoint - 1;\n this.update(temperature)\n }\n\n update(temperature){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n this.props.reload();\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this)\n http.open(\"POST\", root + \"api/status/update/\");\n http.setRequestHeader(\"Content-Type\", \"application/json;charset=UTF-8\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send(JSON.stringify({\n \"id\": this.props.id,\n \"param\": \"thermostatTemperatureSetpoint\",\n \"value\": temperature\n }));\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n const temperature = {\n fontSize: '30px',\n marginLeft: '5px',\n marginRight: '5px',\n color: '#777'\n }\n\n return (\n
\n Arrow up\n {this.props.status.thermostatTemperatureSetpoint}\n Arrow down\n
\n );\n }\n}\n\nexport default TemperatureSetting\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport TemperatureSetting from './traits/TemperatureSetting'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass AcUnit extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.status.thermostatMode === 'off')\n color = \"#666\";\n else if (this.props.status.thermostatMode === 'heat')\n color = \"red\";\n else if (this.props.status.thermostatMode === 'cool')\n color = \"lightblue\";\n else if (this.props.status.thermostatMode === 'on')\n color = \"yellow\";\n else if (this.props.status.thermostatMode === 'heatcool')\n color = \"#DC97FF\";\n else if (this.props.status.thermostatMode === 'auto')\n color = \"#EE357E\";\n else if (this.props.status.thermostatMode === 'fan-only')\n color = \"blue\";\n else if (this.props.status.thermostatMode === 'purifier')\n color = \"#F3882E\";\n else if (this.props.status.thermostatMode === 'eco')\n color = \"green\";\n else if (this.props.status.thermostatMode === 'dry')\n color = \"#753500\";\n\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default AcUnit\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass AirFreshener extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default AirFreshener\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass AirPurifier extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default AirPurifier\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Bed extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Bed\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Fan extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Fan\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Fireplace extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Fireplace\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Radiator extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Radiator\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Switch extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Switch\n","import React from 'react';\nimport TemperatureSetting from './traits/TemperatureSetting'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Thermostat extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.status.thermostatMode === 'off')\n color = \"#666\";\n else if (this.props.status.thermostatMode === 'heat')\n color = \"red\";\n else if (this.props.status.thermostatMode === 'cool')\n color = \"lightblue\";\n else if (this.props.status.thermostatMode === 'on')\n color = \"yellow\";\n else if (this.props.status.thermostatMode === 'heatcool')\n color = \"#DC97FF\";\n else if (this.props.status.thermostatMode === 'auto')\n color = \"#EE357E\";\n else if (this.props.status.thermostatMode === 'fan-only')\n color = \"blue\";\n else if (this.props.status.thermostatMode === 'purifier')\n color = \"#F3882E\";\n else if (this.props.status.thermostatMode === 'eco')\n color = \"green\";\n else if (this.props.status.thermostatMode === 'dry')\n color = \"#753500\";\n\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Thermostat\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass AirCooler extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default AirCooler\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Bathtub extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Bathtub\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Awing extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Awing\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Blinds extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Blinds\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Closet extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Closet\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Curtain extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Curtain\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Door extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Door\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Drawer extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Drawer\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Garage extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Garage\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Pergola extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Pergola\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Shutter extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Shutter\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Valve extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Valve\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Window extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Window\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Lock extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Lock\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Gate extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Gate\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Heater extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Heater\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Hood extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Hood\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass SecuritySystem extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default SecuritySystem\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Blender extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Blender\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Global extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'white';\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color\n }\n\n return (\n
\n
\n
\n

{ this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Global\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Scene extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'white';\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color\n }\n\n return (\n
\n
\n
\n

Scene: { this.props.device.name.name }

\n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Scene\n","import React from 'react';\nimport Light from '../devices/Light'\nimport Outlet from '../devices/Outlet'\nimport AcUnit from '../devices/AcUnit'\nimport AirFreshener from '../devices/AirFreshener'\nimport AirPurifier from '../devices/AirPurifier'\nimport Bed from '../devices/Bed'\nimport Fan from '../devices/Fan'\nimport Fireplace from '../devices/Fireplace'\nimport Radiator from '../devices/Radiator'\nimport Switch from '../devices/Switch'\nimport Thermostat from '../devices/Thermostat'\nimport AirCooler from '../devices/AirCooler'\nimport Bathtub from '../devices/Bathtub'\nimport Awing from '../devices/Awing'\nimport Blinds from '../devices/Blinds'\nimport Closet from '../devices/Closet'\nimport Curtain from '../devices/Curtain'\nimport Door from '../devices/Door'\nimport Drawer from '../devices/Drawer'\nimport Garage from '../devices/Garage'\nimport Pergola from '../devices/Pergola'\nimport Shutter from '../devices/Shutter'\nimport Valve from '../devices/Valve'\nimport Window from '../devices/Window'\nimport Lock from '../devices/Lock'\nimport Gate from '../devices/Gate'\nimport Heater from '../devices/Heater'\nimport Hood from '../devices/Hood'\nimport SecuritySystem from '../devices/SecuritySystem'\nimport Blender from '../devices/Blender'\nimport Global from '../devices/Global'\nimport Scene from '../devices/Scene'\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nimport './Devices.css';\n\nclass Devices extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n data: {},\n devices: []\n }\n this.loadData = this.loadData.bind(this);\n this.newDevice = this.newDevice.bind(this);\n }\n\n componentDidMount() {\n this.loadData();\n setInterval(this.loadData,3000);\n }\n\n loadData(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({\n data: data,\n devices: data.devices\n });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/global/get/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n\n newDevice(){\n window.location.href = '/devices/editor/'\n }\n\n render() {\n\n const devices = this.state.devices.map((device) => {\n if(device.type === 'action.devices.types.LIGHT')\n return \n else if(device.type === 'action.devices.types.OUTLET')\n return \n else if(device.type === 'action.devices.types.AC_UNIT')\n return \n else if(device.type === 'action.devices.types.AIRFRESHENER')\n return \n else if(device.type === 'action.devices.types.AIRPURIFIER')\n return \n else if(device.type === 'action.devices.types.BED')\n return \n else if(device.type === 'action.devices.types.FAN')\n return \n else if(device.type === 'action.devices.types.FIREPLACE')\n return \n else if(device.type === 'action.devices.types.RADIATOR')\n return \n else if(device.type === 'action.devices.types.SWITCH')\n return \n else if(device.type === 'action.devices.types.THERMOSTAT')\n return \n else if(device.type === 'action.devices.types.AIRCOOLER')\n return \n else if(device.type === 'action.devices.types.BATHTUB')\n return \n else if(device.type === 'action.devices.types.AWING')\n return \n else if(device.type === 'action.devices.types.AIRCOOLER')\n return \n else if(device.type === 'action.devices.types.BLINDS')\n return \n else if(device.type === 'action.devices.types.CLOSET')\n return \n else if(device.type === 'action.devices.types.CURTAIN')\n return \n else if(device.type === 'action.devices.types.DOOR')\n return \n else if(device.type === 'action.devices.types.DRAWER')\n return \n else if(device.type === 'action.devices.types.GARAGE')\n return \n else if(device.type === 'action.devices.types.GATE')\n return \n else if(device.type === 'action.devices.types.PERGOLA')\n return \n else if(device.type === 'action.devices.types.SHUTTER')\n return \n else if(device.type === 'action.devices.types.VALVE')\n return \n else if(device.type === 'action.devices.types.WINDOW')\n return \n else if(device.type === 'action.devices.types.LOCK')\n return \n else if(device.type === 'action.devices.types.HEATER')\n return \n else if(device.type === 'action.devices.types.HOOD')\n return \n else if(device.type === 'action.devices.types.SECURITYSYSTEM')\n return \n else if(device.type === 'action.devices.types.BLENDER')\n return \n else if(device.type === 'action.devices.types.SCENE')\n return \n else\n return \n });\n\n return (\n
\n
\n

Devices and scences

\n
\n\n
\n { devices }\n
\n\n
\n \n
\n
\n );\n }\n}\n\nexport default Devices\n","import React from 'react';\n\nimport '../pages/Editor.css';\n\nclass Text extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n }\n\n\n update(event){\n this.props.update(this.props.data,event.target.value);\n }\n\n render() {\n return (\n
\n
\n {this.props.name}\n
\n
\n \n
\n
\n );\n }\n}\n\nexport default Text\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Scene extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n\n\n return (\n
\n
\n
\n sceneReversible\n
\n
\n {this.updateCheckbox(checked,\"sceneReversible\")}} checked={this.props.attributes.sceneReversible} />\n
\n
\n Enable it if the scene can be desabled.\n
\n
\n
\n );\n }\n}\n\nexport default Scene\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass OnOff extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n
\n
\n
\n commandOnlyOnOff\n
\n
\n {this.updateCheckbox(checked,\"commandOnlyOnOff\")}} checked={this.props.attributes.commandOnlyOnOff} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the state.\n
\n
\n
\n
\n queryOnlyOnOff\n
\n
\n {this.updateCheckbox(checked,\"queryOnlyOnOff\")}} checked={this.props.attributes.queryOnlyOnOff} />\n
\n
\n Enable it if Google shouldn't change the device state.\n
\n
\n
\n );\n }\n}\n\nexport default OnOff\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Brightness extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n\n\n return (\n
\n
\n
\n commandOnlyBrightness\n
\n
\n {this.updateCheckbox(checked,\"commandOnlyBrightness\")}} checked={this.props.commandOnlyBrightness} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the brightness.\n
\n
\n
\n );\n }\n}\n\nexport default Brightness\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass FanSpeed extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.updateFanSpeeds = this.updateFanSpeeds.bind(this);\n this.addFanSpeed = this.addFanSpeed.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n updateFanSpeeds(event){\n const id = event.target.id.split('_')\n const speed_id = id[1]\n //Process the attribute and value depending of the attribute\n const speed_attribute = id[0] === 'lang' ? id[0] : 'speed_synonym';\n const value = id[0] === 'lang' ? event.target.value : event.target.value.split(',')\n //Update the temporal data and update it\n var temp_availableFanSpeeds = this.props.attributes.availableFanSpeeds\n temp_availableFanSpeeds.speeds[speed_id].speed_values[0][speed_attribute] = value\n if (id[0] === 'names') temp_availableFanSpeeds.speeds[speed_id].speed_name = value[0]\n this.props.update('attributes/availableFanSpeeds', temp_availableFanSpeeds);\n }\n\n addFanSpeed(){\n var temp_availableFanSpeeds = this.props.attributes.availableFanSpeeds\n temp_availableFanSpeeds.speeds.push({\n \"speed_name\": \"\",\n \"speed_values\": [\n {\n \"speed_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ]\n });\n this.props.update('attributes/availableFanSpeeds', temp_availableFanSpeeds);\n }\n\n render() {\n\n const names_box = {\n width: '150px'\n }\n\n const speeds = this.props.attributes.availableFanSpeeds.speeds.map((speed, i) => {\n return (\n
\n
\n
\n
\n
\n \n \n
\n
\n
\n )\n });\n\n return (\n
\n\n
\n
\n reversible\n
\n
\n {this.updateCheckbox(checked,\"reversible\")}} checked={this.props.attributes.reversible} />\n
\n
\n Enable it if the fan supports blowing in both directions.\n
\n
\n\n
\n
\n supportsFanSpeedPercent\n
\n
\n {this.updateCheckbox(checked,\"supportsFanSpeedPercent\")}} checked={this.props.attributes.supportsFanSpeedPercent} />\n
\n
\n Enable it if the speed can be controlled with a number from 0 to 100.\n
\n
\n\n
\n
\n commandOnlyFanSpeed\n
\n
\n {this.updateCheckbox(checked,\"commandOnlyFanSpeed\")}} checked={this.props.attributes.commandOnlyFanSpeed} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the fan speed.\n
\n
\n\n
\n
\n Add a speed\n
\n
\n \n
\n
\n\n {speeds}\n\n
\n );\n }\n}\n\nexport default FanSpeed\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass ColorSetting extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n
\n
\n
\n Color type\n
\n
\n \n
\n
\n \n
\n
\n
\n
\n Minimum temperature\n
\n
\n \n
\n
\n Minimum color temperature (in Kelvin) supported by the device.\n
\n
\n
\n
\n Maximum temperature\n
\n
\n \n
\n
\n Maximum color temperature (in Kelvin) supported by the device.\n
\n
\n
\n
\n commandOnlyColorSetting\n
\n
\n {this.updateCheckbox(checked,\"commandOnlyColorSetting\")}} checked={this.props.attributes.commandOnlyColorSetting} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the color.\n
\n
\n\n
\n );\n }\n}\n\nexport default ColorSetting\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass TemperatureSetting extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateMode = this.updateMode.bind(this);\n this.addMode = this.addMode.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateMode(event){\n const id = event.target.id.split('_')\n const mode_id = id[1]\n var temp_availableThermostatModes = this.props.attributes.availableThermostatModes.split(',')\n\n if (event.target.value === 'delete'){\n temp_availableThermostatModes.splice(mode_id, 1)\n } else if (event.target.value !== 'select') {\n temp_availableThermostatModes[mode_id] = event.target.value;\n }\n\n this.props.update('attributes/availableThermostatModes', temp_availableThermostatModes.join(','));\n }\n\n addMode(){\n var temp_availableThermostatModes = this.props.attributes.availableThermostatModes\n temp_availableThermostatModes += \",\"\n this.props.update('attributes/availableThermostatModes', temp_availableThermostatModes);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n\n render() {\n\n const modes = this.props.attributes.availableThermostatModes.split(',').map((mode, i) => {\n\n return (\n
\n
\n
\n
\n
\n \n
\n
\n
\n\n )\n });\n\n return (\n
\n\n
\n
\n Add a thermostat mode\n
\n
\n \n
\n
\n\n {modes}\n\n
\n
\n commandOnlyTemperatureSetting\n
\n
\n {this.updateCheckbox(checked,\"commandOnlyTemperatureSetting\")}} checked={this.props.attributes.commandOnlyTemperatureSetting} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the temperature.\n
\n
\n\n
\n
\n queryOnlyTemperatureSetting\n
\n
\n {this.updateCheckbox(checked,\"queryOnlyTemperatureSetting\")}} checked={this.props.attributes.queryOnlyTemperatureSetting} />\n
\n
\n Enable it if Google shouldn't change the device temperature settings.\n
\n
\n\n
\n
\n Minimum temperature\n
\n
\n \n
\n
\n Minimum temperature (in Celsius) supported by the device.\n
\n
\n\n
\n
\n Maximum temperature\n
\n
\n \n
\n
\n Maximum temperature (in Celsius) supported by the device.\n
\n
\n\n
\n
\n Range\n
\n
\n \n
\n
\n Specifies the minimum offset between heat-cool setpoints in Celsius.\n
\n
\n\n
\n
\n Units\n
\n
\n \n
\n
\n\n\n\n
\n );\n }\n}\n\nexport default TemperatureSetting\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Toggles extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.updatetoggle = this.updatetoggle.bind(this);\n this.addToggle = this.addToggle.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n updatetoggle(event){\n const id = event.target.id.split('_')\n const toggle_id = id[1]\n //Process the attribute and value depending of the attribute\n const toggle_attribute = id[0] === 'lang' ? id[0] : 'name_synonym';\n const value = id[0] === 'lang' ? event.target.value : event.target.value.split(',')\n //Update the temporal data and update it\n var temp_availableToggles = this.props.attributes.availableToggles\n temp_availableToggles[toggle_id].name_values[0][toggle_attribute] = value\n if (id[0] === 'names') temp_availableToggles[toggle_id].name = value[0]\n this.props.update('attributes/availableToggles', temp_availableToggles);\n }\n\n addToggle(){\n var temp_availableToggles = this.props.attributes.availableToggles\n temp_availableToggles.push({\n \"name\": \"\",\n \"name_values\": [\n {\n \"name_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ]\n });\n this.props.update('attributes/availableToggles', temp_availableToggles);\n }\n\n render() {\n\n const names_box = {\n marginLeft: '20px',\n width: '150px'\n }\n\n const toggles = this.props.attributes.availableToggles.map((toggle, i) => {\n return (\n
\n
\n
\n
\n
\n \n \n\n\n
\n
\n
\n )\n });\n\n return (\n
\n\n
\n
\n commandOnlyToggles\n
\n
\n {this.updateCheckbox(checked,\"commandOnlyToggles\")}} checked={this.props.attributes.commandOnlyToggles} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the states.\n
\n
\n\n
\n
\n Add a toggle\n
\n
\n \n
\n
\n\n {toggles}\n\n
\n );\n }\n}\n\nexport default Toggles\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Modes extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.updateMode = this.updateMode.bind(this);\n this.addMode = this.addMode.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n updateMode(event){\n const id = event.target.id.split('_')\n const mode_id = id[1]\n var temp_availableModes = this.props.attributes.availableModes\n\n if(id[0] === 'lang'){\n temp_availableModes[mode_id].name_values[0].lang = event.target.value;\n } else if (id[0] === 'names'){\n temp_availableModes[mode_id].name_values[0].name_synonym = event.target.value.split(',');\n temp_availableModes[mode_id].name = event.target.value.split(',')[0]\n } else if (id[0] === 'settings'){\n var values = event.target.value.split(',')\n var settings = []\n for ( var i = 0; i < values.length; i ++){\n settings.push({\n setting_name: values[i],\n setting_values: [{\n setting_synonym: [values[i]],\n lang: this.props.attributes.availableModes[mode_id].name_values[0].lang\n }]\n })\n }\n temp_availableModes[mode_id].settings = settings\n }\n this.props.update('attributes/availableModes', temp_availableModes);\n }\n\n addMode(){\n var temp_availableModes = this.props.attributes.availableModes\n temp_availableModes.push({\n \"name\": \"\",\n \"name_values\": [\n {\n \"name_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ],\n \"settings\": [\n {\n \"setting_name\": \"\",\n \"setting_values\": [{\n \"setting_synonym\": [\"\"],\n \"lang\": \"en\"\n }]\n }\n ]\n });\n this.props.update('attributes/availableModes', temp_availableModes);\n }\n\n render() {\n\n const names_box = {\n width: '150px'\n }\n\n const settings_box = {\n width: '230px'\n }\n\n\n const modes = this.props.attributes.availableModes.map((mode, i) => {\n const settings = mode.settings.map((setting,i) => {return setting.setting_name});\n\n return (\n
\n
\n
\n
\n
\n \n \n \n
\n
\n\n\n
\n\n )\n });\n\n return (\n
\n\n
\n
\n commandOnlyModes\n
\n
\n {this.updateCheckbox(checked,\"commandOnlyModes\")}} checked={this.props.attributes.commandOnlyModes} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the modes.\n
\n
\n\n
\n
\n Add a mode\n
\n
\n \n
\n
\n\n {modes}\n\n
\n );\n }\n}\n\nexport default Modes\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass HumiditySetting extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n
\n\n
\n
\n Minimum humidity\n
\n
\n \n
\n
\n Minimum humidity level as percentage.\n
\n
\n\n
\n
\n Maximum humidity\n
\n
\n \n
\n
\n Maximum humidity level as percentage.\n
\n
\n\n
\n
\n commandOnlyHumiditySetting\n
\n
\n {this.updateCheckbox(checked,\"commandOnlyHumiditySetting\")}} checked={this.props.attributes.commandOnlyHumiditySetting} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the humidity.\n
\n
\n\n
\n
\n queryOnlyHumiditySetting\n
\n
\n {this.updateCheckbox(checked,\"queryOnlyHumiditySetting\")}} checked={this.props.attributes.queryOnlyHumiditySetting} />\n
\n
\n Enable it if Google shouldn't change the device humidity.\n
\n
\n\n
\n );\n }\n}\n\nexport default HumiditySetting\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass OpenClose extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n
\n
\n
\n discreteOnlyOpenClose\n
\n
\n {this.updateCheckbox(checked,\"discreteOnlyOpenClose\")}} checked={this.props.attributes.discreteOnlyOpenClose} />\n
\n
\n Enable it if the device must either be fully open or fully closed.\n
\n
\n\n
\n
\n commandOnlyOpenClose\n
\n
\n {this.updateCheckbox(checked,\"commandOnlyOpenClose\")}} checked={this.props.attributes.commandOnlyOpenClose} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the state.\n
\n
\n\n
\n
\n queryOnlyOpenClose\n
\n
\n {this.updateCheckbox(checked,\"queryOnlyOpenClose\")}} checked={this.props.attributes.queryOnlyOpenClose} />\n
\n
\n Enable it if Google shouldn't change the device state.\n
\n
\n\n
\n );\n }\n}\n\nexport default OpenClose\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Rotation extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n
\n\n
\n
\n Minimum rotation\n
\n
\n \n
\n
\n Minimum rotation degrees that a device can rotate.\n
\n
\n\n
\n
\n Maximum rotation\n
\n
\n \n
\n
\n Maximum rotation degrees that a device can rotate.\n
\n
\n\n
\n
\n commandOnlyRotation\n
\n
\n {this.updateCheckbox(checked,\"commandOnlyRotation\")}} checked={this.props.attributes.commandOnlyRotation} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the device.\n
\n
\n\n
\n
\n supportsContinuousRotation\n
\n
\n {this.updateCheckbox(checked,\"supportsContinuousRotation\")}} checked={this.props.attributes.supportsContinuousRotation} />\n
\n
\n Enable it if the device supports continuous rotation.\n
\n
\n\n
\n
\n supportsDegrees\n
\n
\n {this.updateCheckbox(checked,\"supportsDegrees\")}} checked={this.props.attributes.supportsDegrees} />\n
\n
\n Enable it if the device allows rotation by degree.\n
\n
\n\n
\n
\n supportsPercent\n
\n
\n {this.updateCheckbox(checked,\"supportsPercent\")}} checked={this.props.attributes.supportsPercent} />\n
\n
\n Enable it if device allows rotation by percent.\n
\n
\n\n
\n );\n }\n}\n\nexport default Rotation\n","import React from 'react';\n\nclass Fill extends React.Component {\n constructor(props) {\n super(props);\n this.updateLevels = this.updateLevels.bind(this);\n this.addLevel = this.addLevel.bind(this);\n }\n\n updateLevels(event){\n const id = event.target.id.split('_')\n const level_id = id[1]\n //Process the attribute and value depending of the attribute\n const level_attribute = id[0] === 'lang' ? id[0] : 'level_synonym';\n const value = id[0] === 'lang' ? event.target.value : event.target.value.split(',')\n //Update the temporal data and update it\n var temp_availableFillLevels = this.props.attributes.availableFillLevels\n temp_availableFillLevels.levels[level_id].level_values[0][level_attribute] = value\n if (id[0] === 'names') temp_availableFillLevels.levels[level_id].level_name = value[0]\n this.props.update('attributes/availableFillLevels', temp_availableFillLevels);\n }\n\n addLevel(){\n var temp_availableFillLevels = this.props.attributes.availableFillLevels\n temp_availableFillLevels.levels.push({\n \"level_name\": \"\",\n \"level_values\": [\n {\n \"level_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ]\n });\n this.props.update('attributes/availableFillLevels', temp_availableFillLevels);\n }\n\n render() {\n\n const names_box = {\n width: '150px'\n }\n\n const levels = this.props.attributes.availableFillLevels.levels.map((level, i) => {\n return (\n
\n
\n
\n
\n
\n \n \n
\n
\n
\n )\n });\n\n return (\n
\n\n
\n
\n Add a level\n
\n
\n \n
\n
\n\n {levels}\n\n
\n );\n }\n}\n\nexport default Fill\n","import React from 'react';\n\nclass ArmDisarm extends React.Component {\n constructor(props) {\n super(props);\n this.updateSecurityLevel = this.updateSecurityLevel.bind(this);\n this.addSecurityLevel = this.addSecurityLevel.bind(this);\n }\n\n updateSecurityLevel(event){\n const id = event.target.id.split('_')\n const level_id = id[1]\n //Process the attribute and value depending of the attribute\n const level_attribute = id[0] === 'lang' ? id[0] : 'level_synonym';\n const value = id[0] === 'lang' ? event.target.value : event.target.value.split(',')\n //Update the temporal data and update it\n var temp_availableArmLevels = this.props.attributes.availableArmLevels\n temp_availableArmLevels.levels[level_id].level_values[0][level_attribute] = value\n if (id[0] === 'names') temp_availableArmLevels.levels[level_id].level_name = value[0]\n this.props.update('attributes/availableArmLevels', temp_availableArmLevels);\n }\n\n addSecurityLevel(){\n var temp_availableArmLevels = this.props.attributes.availableArmLevels\n temp_availableArmLevels.levels.push({\n \"level_name\": \"\",\n \"level_values\": [\n {\n \"level_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ]\n });\n this.props.update('attributes/availableArmLevels', temp_availableArmLevels);\n }\n\n render() {\n\n const names_box = {\n marginLeft: '20px',\n width: '150px'\n }\n\n const levels = this.props.attributes.availableArmLevels.levels.map((level, i) => {\n return (\n
\n
\n
\n
\n
\n \n \n
\n
\n
\n )\n });\n\n return (\n
\n\n
\n
\n Add a security level\n
\n
\n \n
\n
\n\n {levels}\n\n
\n );\n }\n}\n\nexport default ArmDisarm\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass StartStop extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.updateArray = this.updateArray.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n updateArray(event){\n this.props.update('attributes/' + event.target.id,event.target.value.split(','));\n }\n\n render() {\n return (\n
\n
\n
\n pausable\n
\n
\n {this.updateCheckbox(checked,\"pausable\")}} checked={this.props.attributes.pausable} />\n
\n
\n Enable it if the device can be paused.\n
\n
\n\n
\n
\n Zones\n
\n
\n \n
\n
\n\n
\n
\n\n
\n
\n Supported zones names separeted by commas.\n
\n
\n\n\n
\n );\n }\n}\n\nexport default StartStop\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Timer extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.update = this.update.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n render() {\n return (\n
\n
\n
\n commandOnlyTimer\n
\n
\n {this.updateCheckbox(checked,\"commandOnlyTimer\")}} checked={this.props.attributes.commandOnlyTimer} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the state.\n
\n
\n\n
\n
\n Max time\n
\n
\n \n
\n
\n\n
\n
\n\n
\n
\n Indicates the longest timer setting in seconds available on the device.\n
\n
\n
\n );\n }\n}\n\nexport default Timer\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass TemperatureControl extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n\n\n return (\n
\n\n
\n
\n commandOnlyTemperatureControl\n
\n
\n {this.updateCheckbox(checked,\"commandOnlyTemperatureControl\")}} checked={this.props.attributes.commandOnlyTemperatureControl} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the temperature.\n
\n
\n\n
\n
\n queryOnlyTemperatureControl\n
\n
\n {this.updateCheckbox(checked,\"queryOnlyTemperatureControl\")}} checked={this.props.attributes.queryOnlyTemperatureControl} />\n
\n
\n Enable it if Google shouldn't change the device temperature settings.\n
\n
\n\n
\n
\n Minimum temperature\n
\n
\n \n
\n
\n Minimum temperature (in Celsius) supported by the device.\n
\n
\n\n
\n
\n Maximum temperature\n
\n
\n \n
\n
\n Maximum temperature (in Celsius) supported by the device.\n
\n
\n\n
\n
\n Step\n
\n
\n \n
\n
\n Specifies the relative temperature step.\n
\n
\n\n
\n
\n Units\n
\n
\n \n
\n
\n\n\n\n
\n );\n }\n}\n\nexport default TemperatureControl\n","import React from 'react';\n\nclass Cook extends React.Component {\n constructor(props) {\n super(props);\n this.updateMode = this.updateMode.bind(this);\n this.addMode = this.addMode.bind(this);\n this.updatePreset = this.updatePreset.bind(this);\n this.addPreset = this.addPreset.bind(this);\n }\n\n updateMode(event){\n const id = event.target.id.split('_')\n const mode_id = id[1]\n var temp_supportedCookingModes = this.props.attributes.supportedCookingModes\n\n if (event.target.value === 'delete'){\n temp_supportedCookingModes.splice(mode_id, 1)\n } else if (event.target.value !== 'select') {\n temp_supportedCookingModes[mode_id] = event.target.value;\n }\n\n this.props.update('attributes/supportedCookingModes', temp_supportedCookingModes);\n }\n\n addMode(){\n var temp_supportedCookingModes = this.props.attributes.supportedCookingModes\n temp_supportedCookingModes.push(\"\");\n this.props.update('attributes/supportedCookingModes', temp_supportedCookingModes);\n }\n\n updatePreset(event){\n const id = event.target.id.split('_')\n const preset_id = id[1]\n var temp_foodPresets = this.props.attributes.foodPresets\n\n if(id[0] === 'lang'){\n temp_foodPresets[preset_id].food_synonyms[0].lang = event.target.value;\n } else if (id[0] === 'names'){\n temp_foodPresets[preset_id].food_synonyms[0].synonym = event.target.value.split(',');\n temp_foodPresets[preset_id].food_preset_name = event.target.value.split(',')[0]\n } else if (id[0] === 'units'){\n temp_foodPresets[preset_id].supported_units[0] = event.target.value;\n }\n this.props.update('attributes/foodPresets', temp_foodPresets);\n }\n\n addPreset(){\n var temp_foodPresets = this.props.attributes.foodPresets\n temp_foodPresets.push({\n \"food_preset_name\": \"\",\n \"supported_units\": [\"\"],\n \"food_synonyms\": [{\n \"synonym\": [\"\"],\n \"language\": \"en\"\n }]\n });\n this.props.update('attributes/foodPresets', temp_foodPresets);\n }\n\n render() {\n\n const names_box = {\n width: '150px'\n }\n\n const modes = this.props.attributes.supportedCookingModes.map((mode, i) => {\n\n return (\n
\n
\n
\n
\n
\n \n
\n
\n
\n\n )\n });\n\n const presets = this.props.attributes.foodPresets.map((preset, i) => {\n\n return (\n
\n
\n
\n
\n
\n \n \n \n
\n
\n
\n )\n });\n\n return (\n
\n\n
\n
\n Add a cooking mode\n
\n
\n \n
\n
\n\n {modes}\n\n
\n
\n Add a preset\n
\n
\n \n
\n
\n\n {presets}\n\n
\n );\n }\n}\n\nexport default Cook\n","import React from 'react';\n\nclass SensorState extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n }\n\n update(event){\n const value = event.target.value;\n var sensor = {\n name: value\n }\n\n switch (value) {\n default:\n sensor['descriptiveCapabilities'] = {\n availableStates: ['fair','good','healthy','moderate','poor','severe','unhealthy','unhealthy for sensitive groups','very poor','very unhealthy','unknown'],\n }\n sensor['numericCapabilities']= { rawValueUnit: \"AQI\" }\n break;\n case 'AirQuality':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['fair','good','healthy','moderate','poor','severe','unhealthy','unhealthy for sensitive groups','very poor','very unhealthy','unknown'],\n }\n sensor['numericCapabilities']= { rawValueUnit: \"AQI\" }\n break;\n case 'CarbonDioxideLevel':\n sensor['descriptiveCapabilities'] = {\n numericCapabilities: { rawValueUnit: \"PARTS_PER_MILLION\" }\n }\n break;\n case 'CarbonMonoxideLevel':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['carbon monoxide detected','high','no carbon monoxide detected','unknown']\n }\n sensor['numericCapabilities']= { rawValueUnit: \"PARTS_PER_MILLION\" }\n break;\n case 'FilterCleanliness':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['clean','dirty','needs replacement','unknown']\n }\n break;\n case 'FilterLifeTime':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['good','new','replace soon','replace now','unknown']\n }\n sensor['numericCapabilities']= { rawValueUnit: \"PERCENTAGE\" }\n break;\n case 'HEPAFilterLifeTime':\n sensor['numericCapabilities']= { rawValueUnit: \"PERCENTAGE\" }\n break;\n case 'Max2FilterLifeTime':\n sensor['numericCapabilities']= { rawValueUnit: \"PERCENTAGE\" }\n break;\n case 'PM2.5':\n sensor['numericCapabilities']= { rawValueUnit: \"MICROGRAMS_PER_CUBIC_METER\" }\n break;\n case 'PM10':\n sensor['numericCapabilities']= { rawValueUnit: \"MICROGRAMS_PER_CUBIC_METER\" }\n break;\n case 'PreFilterLifeTime':\n sensor['numericCapabilities']= { rawValueUnit: \"PERCENTAGE\" }\n break;\n case 'SmokeLevel':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['smoke detected','high','no smoke detected','unknown']\n }\n sensor['numericCapabilities']= { rawValueUnit: \"PARTS_PER_MILLION\" }\n break;\n case 'WaterLeak':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['leak','no leak','unknown']\n }\n break;\n case 'RainDetection':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['rain detected','no rain detected','unknown']\n }\n break;\n case 'VolatileOrganicCompounds':\n sensor['numericCapabilities']= { rawValueUnit: \"PARTS_PER_MILLION\" }\n break;\n }\n\n var sensorStatesSupported = []\n sensorStatesSupported.push(sensor);\n this.props.update('attributes/' + event.target.id,sensorStatesSupported);\n }\n\n render() {\n return (\n
\n
\n
\n Sensor type\n
\n
\n \n
\n
\n \n
\n
\n\n
\n );\n }\n}\n\nexport default SensorState\n","import React from 'react';\nimport Switch from \"react-switch\";\nimport Text from '../editor/Text'\nimport Scene from '../editor/traits/Scene'\nimport OnOff from '../editor/traits/OnOff'\nimport Brightness from '../editor/traits/Brightness'\nimport FanSpeed from '../editor/traits/FanSpeed'\nimport ColorSetting from '../editor/traits/ColorSetting'\nimport TemperatureSetting from '../editor/traits/TemperatureSetting'\nimport Toggles from '../editor/traits/Toggles'\nimport Modes from '../editor/traits/Modes'\nimport HumiditySetting from '../editor/traits/HumiditySetting'\nimport OpenClose from '../editor/traits/OpenClose'\nimport Rotation from '../editor/traits/Rotation'\nimport Fill from '../editor/traits/Fill'\nimport ArmDisarm from '../editor/traits/ArmDisarm'\nimport StartStop from '../editor/traits/StartStop'\nimport Timer from '../editor/traits/Timer'\nimport TemperatureControl from '../editor/traits/TemperatureControl'\nimport Cook from '../editor/traits/Cook'\nimport SensorState from '../editor/traits/SensorState'\nimport getCookieValue from '../../functions'\nimport { root, deviceReference } from '../../constants'\n\nimport './Editor.css';\n\nclass Editor extends React.Component {\n constructor(props) {\n super(props);\n const id = window.location.pathname.split('/')[3];\n var create = false;\n if (id === \"\") create = true;\n this.state = {\n id: id,\n create: create,\n device: {\n attributes: {},\n deviceInfo: {},\n id: \"\",\n name: {\n defaultNames: [],\n nicknames: [],\n name: \"\"\n },\n traits: [],\n type: \"\"\n },\n status: {\n online: true\n },\n posible_traits: [],\n save_status: \"\"\n }\n this.updateNames = this.updateNames.bind(this);\n this.update = this.update.bind(this);\n this.updateId = this.updateId.bind(this);\n this.updateType = this.updateType.bind(this);\n this.updateTraits = this.updateTraits.bind(this);\n this.save = this.save.bind(this);\n this.delete = this.delete.bind(this);\n this.renderAttrinutes = this.renderAttrinutes.bind(this);\n }\n\n componentDidMount() {\n if (!this.state.create){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({\n device: data,\n posible_traits: deviceReference.devices[data.type].traits\n });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/devices/get/\" + this.state.id + \"/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n }\n\n updateNames(dumy_key, value){\n var names = value.split(',');\n var temp_device = this.state.device\n temp_device.name = {\n defaultNames: names,\n nicknames: names,\n name: names[0]\n }\n this.setState({\n device: temp_device\n })\n }\n\n update(key, value){\n var temp_device = this.state.device\n var keys = key.split('/');\n if (keys.length === 1)\n temp_device[key] = value\n else if (keys.length === 2)\n temp_device[keys[0]][keys[1]] = value\n else if (keys.length === 3)\n temp_device[keys[0]][keys[1]][keys[2]] = value\n this.setState({\n device: temp_device\n })\n }\n\n updateId(event){\n this.update('id',event.target.value)\n }\n\n updateType(event){\n this.update('type',event.target.value)\n this.setState({\n posible_traits: deviceReference.devices[event.target.value].traits\n });\n }\n\n updateTraits(checked, trait){\n var temp_device = this.state.device\n var temp_status = this.state.status\n if (checked) {\n if (this.state.device.traits.includes(trait) === false){\n //Push the trait to the device\n temp_device.traits.push(trait)\n //Set the default values\n var attributes = deviceReference.traits[trait].attributes;\n Object.keys(attributes).forEach((attribute, i) => {\n temp_device.attributes[attribute] = attributes[attribute].default\n });\n //Set the default status params\n var params = deviceReference.traits[trait].params;\n params.forEach((param, i) => {\n temp_status[param] = deviceReference.params[param].default\n });\n }\n } else {\n if (this.state.device.traits.includes(trait) === true){\n temp_device.traits = temp_device.traits.filter(function(value, index, arr){ return value !== trait;});\n }\n }\n this.setState({\n device: temp_device,\n status: temp_status\n })\n }\n\n save(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n JSON.parse(http.responseText);\n this.setState({\n save_status: \"Saved correctly.\"\n });\n if (this.state.create) {\n window.location.href = '/devices'\n }\n } else {\n console.error(http.statusText);\n this.setState({\n save_status: \"Error, the changes haven't been saved.\"\n });\n }\n setTimeout(function(){\n this.setState({\n save_status: \"\"\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n var payload = {\n \"device\": this.state.device\n }\n if (this.state.create){\n http.open(\"POST\", root + \"api/devices/create/\");\n payload.status = this.state.status\n } else {\n http.open(\"POST\", root + \"api/devices/update/\");\n }\n http.setRequestHeader(\"Content-Type\", \"application/json;charset=UTF-8\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send(JSON.stringify(payload));\n }\n\n delete(){\n if(window.confirm('Do you want to delete the device?')){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n window.location.href = \"/devices/\"\n } else {\n console.error(http.statusText);\n this.setState({\n save_status: \"Error, the device hasn't been deleted.\"\n });\n }\n setTimeout(function(){\n this.setState({\n save_status: \"\"\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/devices/delete/\" + this.state.device.id + \"/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n } else {\n this.setState({\n save_status: \"Ok. The device is save.\"\n });\n }\n }\n\n renderAttrinutes(trait){\n if (this.state.device.traits.includes(trait)){\n if (trait === 'action.devices.traits.Scene')\n return \n else if (trait === 'action.devices.traits.OnOff')\n return \n else if (trait === 'action.devices.traits.Brightness')\n return \n else if (trait === 'action.devices.traits.ColorSetting')\n return \n else if (trait === 'action.devices.traits.FanSpeed')\n return \n else if (trait === 'action.devices.traits.TemperatureSetting')\n return \n else if (trait === 'action.devices.traits.Toggles')\n return \n else if (trait === 'action.devices.traits.Modes')\n return \n else if (trait === 'action.devices.traits.HumiditySetting')\n return \n else if (trait === 'action.devices.traits.OpenClose')\n return \n else if (trait === 'action.devices.traits.Rotation')\n return \n else if (trait === 'action.devices.traits.Fill')\n return \n else if (trait === 'action.devices.traits.ArmDisarm')\n return \n else if (trait === 'action.devices.traits.StartStop')\n return \n else if (trait === 'action.devices.traits.Timer')\n return \n else if (trait === 'action.devices.traits.TemperatureControl')\n return \n else if (trait === 'action.devices.traits.Cook')\n return \n else if (trait === 'action.devices.traits.SensorState')\n return \n }\n }\n\n render() {\n\n const deleteButton = {\n backgroundColor: 'red'\n }\n\n const deleteButtonDisabled = {\n backgroundColor: 'red',\n opacity: '0.2'\n }\n\n const types = Object.keys(deviceReference.devices).map((type) => {\n return \n })\n\n const nicknames = this.state.device.name.nicknames.map((name) => {\n return name\n });\n\n const traits = this.state.posible_traits.map((trait) =>\n
\n
\n
\n
\n {deviceReference.traits[trait].name}\n
\n
\n {this.updateTraits(checked,trait)}} checked={this.state.device.traits.includes(trait)} />\n
\n
\n Read Google's documentation\n
\n
\n {this.renderAttrinutes(trait)}\n
\n );\n\n return (\n
\n\n
\n

Global settings

\n
\n General settings of the device.\n
\n
\n
\n
\n
\n Device ID*\n
\n
\n \n
\n
\n
\n
\n Device Type*\n
\n
\n \n
\n
\n \n \n \n \n \n
\n Nick names must be separeted by , commas.
\n * data is required.\n
\n
\n

Traits

\n
\n The traits define what the device can do.\n
\n {traits}\n
\n
\n \n \n {this.state.save_status}\n
\n
\n
\n\n
\n );\n }\n}\n\nexport default Editor\n","import React from 'react';\nimport ReactJson from 'react-json-view'\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nclass Editor extends React.Component {\n constructor(props) {\n super(props);\n const id = window.location.pathname.split('/')[3];\n this.state = {\n id: id,\n device: {\n attributes: {},\n deviceInfo: {},\n id: \"\",\n name: {\n defaultnames: [],\n nicknames: [],\n name: \"\"\n },\n traits: [],\n type: \"\"\n },\n status: {\n online: true\n }\n }\n }\n\n componentDidMount() {\n var dev = new XMLHttpRequest();\n dev.onload = function (e) {\n if (dev.readyState === 4) {\n if (dev.status === 200) {\n var data = JSON.parse(dev.responseText);\n this.setState({\n device: data\n });\n } else {\n console.error(dev.statusText);\n }\n }\n }.bind(this);\n dev.open(\"GET\", root + \"api/devices/get/\" + this.state.id + \"/\");\n dev.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n dev.send();\n\n var sta = new XMLHttpRequest();\n sta.onload = function (e) {\n if (sta.readyState === 4) {\n if (sta.status === 200) {\n var data = JSON.parse(sta.responseText);\n this.setState({\n status: data\n });\n } else {\n console.error(sta.statusText);\n }\n }\n }.bind(this);\n sta.open(\"GET\", root + \"api/status/get/\" + this.state.id + \"/\");\n sta.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n sta.send();\n }\n\n\n\n render() {\n\n const json_viewer = {\n textAlign: 'left',\n }\n\n return (\n
\n\n
\n

Device definition

\n
\n General settings of the device.\n
\n
\n
\n \n
\n
\n\n
\n

Device status

\n
\n Status of the device.\n
\n
\n
\n \n
\n
\n\n
\n );\n }\n}\n\nexport default Editor\n","import React from 'react';\nimport ReactJson from 'react-json-view'\nimport getCookieValue from '../../functions'\nimport { root, deviceReference } from '../../constants'\n\nimport './Connecting.css';\n\nclass Connecting extends React.Component {\n constructor(props) {\n super(props);\n const id = window.location.pathname.split('/')[3]\n this.state = {\n id: id,\n traits: [],\n params: [],\n commands: []\n }\n }\n\n componentDidMount() {\n var dev = new XMLHttpRequest();\n dev.onload = function (e) {\n if (dev.readyState === 4) {\n if (dev.status === 200) {\n const data = JSON.parse(dev.responseText);\n const traits = data.traits;\n var commands = [];\n var params = []\n traits.forEach((trait) => {\n params = params.concat(deviceReference.traits[trait].params);\n commands = commands.concat(deviceReference.traits[trait].commands);\n });\n this.setState({\n traits: traits,\n params: params,\n commands: commands\n });\n } else {\n console.error(dev.statusText)\n }\n }\n }.bind(this);\n dev.open(\"GET\", root + \"api/devices/get/\" + this.state.id + \"/\");\n dev.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n dev.send();\n }\n\n render() {\n\n const params = this.state.params.map((param, i) => {\n var type = deviceReference.params[param].type\n if (type === 'list')\n type = 'string'\n\n var topic = 'None - Controlled only by the device'\n if (deviceReference.params[param].commanded)\n topic = 'device/' + this.state.id + '/' + param\n\n return (\n
\n
{param}
\n
{topic}
\n
{type}
\n
\n )\n })\n\n const commands = this.state.commands.map((command, i) => {\n return (\n
\n
{command.command}
\n
{'device/' + this.state.id + '/command'}
\n
{command.description}
\n
\n )\n })\n\n var example = {\"id\":\"light001\",\"param\":\"brightness\",\"value\":\"80\",\"intent\":\"execute\"}\n var advise = {\n textAlign: 'left'\n }\n\n return (\n
\n\n
\n

Params

\n
\n

Params are data interchanged between Google and the device and stored in Homeware database.

\n

If the param has got a notification topic, Google Home can control it. A notification will be sent in this MQTT topic when Google change a param.

\n

If the param hasn't got a notification topic, the device should update the param value when necessary.

\n
\n
\n
\n
Param
\n
Notifications topic
\n
Type
\n
\n {params}\n
\n
\n

The device can change the value of any param sending an execute request to device/control topic as follow

\n \n
\n
\n\n
\n

Commands

\n
\n

Commands are directs orders from Google to the device. Commands are not stored in Homeware's database.

\n
\n
\n
\n
Command
\n
Notifications topic
\n
Description
\n
\n {commands}\n
\n\n
\n );\n }\n}\n\nexport default Connecting\n","import React from 'react';\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nimport './Tasks.css';\n\nclass Tasks extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n devices: [],\n tasks: []\n }\n this.loadData = this.loadData.bind(this);\n this.openManager = this.openManager.bind(this);\n this.newTask = this.newTask.bind(this);\n }\n\n componentDidMount() {\n this.loadData();\n }\n\n loadData(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({\n devices: data.devices,\n tasks: data.tasks\n });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/global/get/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n\n openManager(event){\n window.location.href = '/tasks/manager/' + event.target.id.split('_')[1]\n }\n\n newTask(){\n window.location.href = '/tasks/manager/'\n }\n\n render() {\n\n const tasks = this.state.tasks.map((task, i) => {\n return(\n
\n

{ task.title }

\n
\n

{ task.description }

\n
\n )\n });\n\n return (\n
\n
\n

Tasks

\n
\n\n
\n {tasks}\n
\n\n
\n \n
\n
\n );\n }\n}\n\nexport default Tasks\n","import React from 'react';\nimport Triggers from './Triggers'\n\nimport '../pages/Manager.css';\n\nclass Logic extends React.Component {\n constructor(props) {\n super(props);\n this.delete = this.delete.bind(this);\n this.addOr = this.addOr.bind(this);\n this.addAnd = this.addAnd.bind(this);\n this.openTriggerAssistant = this.openTriggerAssistant.bind(this);\n }\n\n delete() {\n this.props.delete(this.props.id);\n }\n\n addOr() {\n this.props.addTriggerLogic('or',this.props.id)\n }\n\n addAnd() {\n this.props.addTriggerLogic('and',this.props.id)\n }\n\n openTriggerAssistant() {\n this.props.openTriggerAssistant(this.props.id)\n }\n\n render() {\n\n const num_operations = this.props.triggers[this.props.id].operation.length-1;\n const operations = this.props.triggers[this.props.id].operation.map((op, i) => {\n return (\n
\n \n {i < num_operations ?

{this.props.triggers[this.props.id].type}

: '' }\n
\n );\n });\n\n return (\n
\n {operations}\n
\n \n \n \n \n
\n
\n );\n }\n}\n\nexport default Logic\n","import React from 'react';\nimport { deviceReference } from '../../constants'\n\nimport '../pages/Manager.css';\n\nclass Trigger extends React.Component {\n constructor(props) {\n super(props);\n this.delete = this.delete.bind(this);\n this.renderTriggerText = this.renderTriggerText.bind(this);\n }\n\n delete() {\n this.props.delete(this.props.id);\n }\n\n renderTriggerText() {\n const week = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']\n const device_triggers = ['d2b','d2i','d2l','d2s']\n\n const type = this.props.triggers[this.props.id].type;\n const operation = this.props.triggers[this.props.id].operation.split(':');\n if (device_triggers.includes(type)) {\n return this.props.devices[operation[0]] + ' (' + (deviceReference.params[operation[1]] ? deviceReference.params[operation[1]].name : operation[1]) + ') ' + operation[2] + ' ' + operation[3];\n } else if (type === 'd2d') {\n return this.props.devices[operation[0]] + ' (' + (deviceReference.params[operation[1]] ? deviceReference.params[operation[1]].name : operation[1]) + ') ' + operation[2] + ' ' + this.props.devices[operation[3]] + ' (' + (deviceReference.params[operation[4]].name ? deviceReference.params[operation[4]].name : operation[4]) + ') ';\n } else if (type === 'd2c') {\n return this.props.devices[operation[0]] + ' (' + (deviceReference.params[operation[1]] ? deviceReference.params[operation[1]].name : operation[1]) + ') ' + operation[2] + ' ' + operation[3];\n } else if (type === 'time') {\n\n var days = '';\n for( var i = 0; i < operation[2].length; i++){\n days += week[operation[2][i]];\n if (i !== operation[2].length - 1)\n days += ', ';\n }\n return operation[0] + ':' + operation[1] + ' on ' + days\n\n } else {\n return this.props.triggers[this.props.id].operation\n }\n }\n\n render() {\n\n return (\n
\n {this.renderTriggerText()}\n \"Delete\n
\n );\n }\n}\n\nexport default Trigger\n","import React from 'react';\nimport Logic from './Logic'\nimport Trigger from './Trigger'\n\nclass Triggers extends React.Component {\n constructor(props) {\n super(props);\n this.addOr = this.addOr.bind(this);\n this.addAnd = this.addAnd.bind(this);\n this.openTriggerAssistant = this.openTriggerAssistant.bind(this);\n }\n\n addOr() {\n this.props.addTriggerLogic('or','triggers')\n }\n\n addAnd() {\n this.props.addTriggerLogic('and','triggers')\n }\n\n openTriggerAssistant() {\n this.props.openTriggerAssistant('triggers')\n }\n\n render() {\n\n if (this.props.triggers.trigger) {\n var operation = this.props.triggers[this.props.id]\n const device_triggers = ['d2b','d2d','d2i','d2l','time','d2c']\n\n if (operation.type === 'or'){\n return \n } else if (operation.type === 'and'){\n return \n } else if (device_triggers.includes(operation.type)){\n return \n }\n } else {\n return (\n
\n \n \n \n
\n );\n }\n\n }\n}\n\nexport default Triggers\n","import React from 'react';\n\nimport '../pages/Manager.css';\n\nclass Assistant extends React.Component {\n constructor(props) {\n super(props);\n this.addTriggerOperation = this.addTriggerOperation.bind(this);\n }\n\n addTriggerOperation(){\n const hour = document.getElementById('hour').value;\n const minute = document.getElementById('minute').value;\n var week = '';\n\n if (document.getElementById('monday').checked)\n week += '1'\n if (document.getElementById('tuesday').checked)\n week += '2'\n if (document.getElementById('wednesday').checked)\n week += '3'\n if (document.getElementById('thursday').checked)\n week += '4'\n if (document.getElementById('friday').checked)\n week += '5'\n if (document.getElementById('saturday').checked)\n week += '6'\n if (document.getElementById('sunday').checked)\n week += '0'\n\n const value = hour + ':' + minute + ':' + week;\n this.props.addTriggerOperation('time',value);\n this.props.closeTriggerAssistant();\n }\n\n render() {\n\n return (\n
\n

Triggered by time

\n
\n
\n Hour*\n
\n
\n \n
\n
\n 24h format\n
\n
\n
\n
\n Minute*\n
\n
\n \n
\n
\n \n
\n
\n\n
\n
\n Week*\n
\n
\n Sunday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Monday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Tuesday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Wednesday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Thursday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Friday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Saturday\n
\n
\n \n
\n
\n\n\n\n\n\n
\n \n \n
\n
\n );\n }\n}\n\nexport default Assistant\n","import React from 'react';\nimport { deviceReference } from '../../constants'\n\nimport '../pages/Manager.css';\n\nclass Device extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n device: \"\"\n }\n this.updateDevice = this.updateDevice.bind(this);\n this.updateParam = this.updateParam.bind(this);\n this.addTriggerOperation = this.addTriggerOperation.bind(this);\n this.typeConversion = this.typeConversion.bind(this);\n }\n\n updateDevice(event) {\n this.setState({\n device: event.target.value\n });\n }\n\n updateParam(event) {\n this.setState({\n param: event.target.value\n });\n }\n\n addTriggerOperation(){\n const device = document.getElementById('device').value;\n const param = document.getElementById('param').value;\n const comparator = document.getElementById('comparator').value;\n const value = document.getElementById('value').value;\n\n\n const operation = device + ':' + param + ':' + comparator + ':' + value;\n this.props.addTriggerOperation(this.typeConversion(deviceReference.params[this.state.param].type),operation);\n this.props.closeTriggerAssistant();\n }\n\n typeConversion(origen) {\n const type = {\n int: 'd2i',\n list: 'd2l',\n bool: 'd2b',\n string: 'd2s',\n color: 'd2c'\n }\n return type[origen]\n }\n\n render() {\n\n const devices = Object.keys(this.props.devices).map((device) => {\n return \n })\n\n const params = this.state.device === \"\" ? '' : Object.keys(this.props.status[this.state.device]).map((param) => {\n return \n })\n\n var value = '';\n if (deviceReference.params[this.state.param]){\n const type = this.typeConversion(deviceReference.params[this.state.param].type);\n if(type === 'd2i'){\n value = (\n
\n
\n Value*\n
\n
\n \n
\n
\n )\n } else if(type === 'd2s'){\n value = (\n
\n
\n Value*\n
\n
\n \n
\n
\n )\n } else if(type === 'd2b' || type === 'd2l'){\n\n const options = deviceReference.params[this.state.param].select.map((option) => {\n return \n })\n\n value = (\n
\n
\n Value*\n
\n
\n \n
\n
\n )\n }\n\n }\n\n return (\n
\n

Triggered by a device

\n\n
\n
\n Device*\n
\n
\n \n
\n
\n
\n
\n Param*\n
\n
\n \n
\n
\n
\n
\n Comparator*\n
\n
\n \n
\n
\n\n {value}\n\n
\n \n \n
\n
\n );\n }\n}\n\nexport default Device\n","import React from 'react';\nimport { deviceReference } from '../../constants'\n\nimport '../pages/Manager.css';\n\nclass DeviceToDevice extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n device_a: \"\",\n device_b: \"\"\n }\n this.updateDependencies = this.updateDependencies.bind(this);\n this.addTriggerOperation = this.addTriggerOperation.bind(this);\n }\n\n updateDependencies(event) {\n var state = this.state;\n state[event.target.id] = event.target.value;\n this.setState(state);\n }\n\n\n addTriggerOperation(){\n const device_a = document.getElementById('device_a').value;\n const param_a = document.getElementById('param_a').value;\n const comparator = document.getElementById('comparator').value;\n const device_b = document.getElementById('device_b').value;\n const param_b = document.getElementById('param_b').value;\n\n const operation = device_a + ':' + param_a + ':' + comparator + ':' + device_b + ':' + param_b;\n this.props.addTriggerOperation('d2d',operation);\n this.props.closeTriggerAssistant();\n }\n\n render() {\n\n const devices = Object.keys(this.props.devices).map((device) => {\n return \n })\n\n const params_a = this.state.device_a === \"\" ? '' : Object.keys(this.props.status[this.state.device_a]).map((param) => {\n return \n })\n\n const params_b = this.state.device_b === \"\" ? '' : Object.keys(this.props.status[this.state.device_b]).map((param) => {\n return \n })\n\n return (\n
\n

Compare two devices

\n\n
\n
\n Device A*\n
\n
\n \n
\n
\n
\n
\n Param A*\n
\n
\n \n
\n
\n\n
\n
\n Comparator*\n
\n
\n \n
\n
\n\n
\n
\n Device B*\n
\n
\n \n
\n
\n
\n
\n Param B*\n
\n
\n \n
\n
\n\n
\n \n \n
\n
\n );\n }\n}\n\nexport default DeviceToDevice\n","import React from 'react';\nimport Time from './Time'\nimport Device from './Device'\nimport DeviceToDevice from './DeviceToDevice'\n\nimport '../pages/Manager.css';\n\nclass Assistant extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n type: ''\n }\n this.timeTigger = this.timeTigger.bind(this);\n this.deiceTrigger = this.deiceTrigger.bind(this);\n this.deviceToDeviceTrigger = this.deviceToDeviceTrigger.bind(this);\n }\n\n timeTigger() {\n this.setState({\n type: 'time'\n });\n }\n\n deiceTrigger() {\n this.setState({\n type: 'device'\n });\n }\n\n deviceToDeviceTrigger() {\n this.setState({\n type: 'device2device'\n });\n }\n\n render() {\n\n if (this.state.type === '')\n return (\n
\n

Add a new trigger

\n
\n \n \n \n \n
\n
\n );\n else if (this.state.type === 'time')\n return