Migrating lights panel WIP

This commit is contained in:
Fabio Manganiello 2020-12-14 02:13:55 +01:00
parent 2de1e3ebe6
commit 5e7c6c26c9
60 changed files with 797 additions and 181 deletions

View file

@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>platypush</title><link href="/static/css/chunk-0a24466a.2793b349.css" rel="prefetch"><link href="/static/css/chunk-16a3f845.79277e60.css" rel="prefetch"><link href="/static/css/chunk-24ff873d.c68a1871.css" rel="prefetch"><link href="/static/css/chunk-4bbbb9a3.c0cffcb7.css" rel="prefetch"><link href="/static/css/chunk-5710a9bc.b05a2ff9.css" rel="prefetch"><link href="/static/css/chunk-62a3d08e.698b2d60.css" rel="prefetch"><link href="/static/css/chunk-ac6aae98.a322204e.css" rel="prefetch"><link href="/static/css/chunk-e8078048.67cca65c.css" rel="prefetch"><link href="/static/js/chunk-0a24466a.ebe2c04f.js" rel="prefetch"><link href="/static/js/chunk-16a3f845.3bdbbdb5.js" rel="prefetch"><link href="/static/js/chunk-24ff873d.0f916e0f.js" rel="prefetch"><link href="/static/js/chunk-2d2091df.377ea7b0.js" rel="prefetch"><link href="/static/js/chunk-4bbbb9a3.c1ba820e.js" rel="prefetch"><link href="/static/js/chunk-5710a9bc.5aba1b9a.js" rel="prefetch"><link href="/static/js/chunk-62a3d08e.cd0ca5eb.js" rel="prefetch"><link href="/static/js/chunk-ac6aae98.dda16597.js" rel="prefetch"><link href="/static/js/chunk-e8078048.bc52467d.js" rel="prefetch"><link href="/static/css/app.ac911816.css" rel="preload" as="style"><link href="/static/js/app.9f4771bd.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.e8b1896c.js" rel="preload" as="script"><link href="/static/css/app.ac911816.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but platypush doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.e8b1896c.js"></script><script src="/static/js/app.9f4771bd.js"></script></body></html>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>platypush</title><link href="/static/css/chunk-014e8b04.542f4068.css" rel="prefetch"><link href="/static/css/chunk-16a3f845.1df61c27.css" rel="prefetch"><link href="/static/css/chunk-24ff873d.5ef32028.css" rel="prefetch"><link href="/static/css/chunk-4bbbb9a3.431b3300.css" rel="prefetch"><link href="/static/css/chunk-5710a9bc.763b29ed.css" rel="prefetch"><link href="/static/css/chunk-62a3d08e.495b15c5.css" rel="prefetch"><link href="/static/css/chunk-ac6aae98.f24d8093.css" rel="prefetch"><link href="/static/css/chunk-e8078048.6c400707.css" rel="prefetch"><link href="/static/js/chunk-014e8b04.7f400c2d.js" rel="prefetch"><link href="/static/js/chunk-16a3f845.59b58d41.js" rel="prefetch"><link href="/static/js/chunk-24ff873d.f955ad3b.js" rel="prefetch"><link href="/static/js/chunk-2d2091df.ec2fb649.js" rel="prefetch"><link href="/static/js/chunk-4bbbb9a3.6f0e4975.js" rel="prefetch"><link href="/static/js/chunk-5710a9bc.47bb3f2d.js" rel="prefetch"><link href="/static/js/chunk-62a3d08e.8fc4fd3a.js" rel="prefetch"><link href="/static/js/chunk-ac6aae98.04b7413c.js" rel="prefetch"><link href="/static/js/chunk-e8078048.e668de5f.js" rel="prefetch"><link href="/static/css/app.5408c936.css" rel="preload" as="style"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="preload" as="style"><link href="/static/js/app.fd969252.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.6eaf6fa5.js" rel="preload" as="script"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="stylesheet"><link href="/static/css/app.5408c936.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but platypush doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.6eaf6fa5.js"></script><script src="/static/js/app.fd969252.js"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,2 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-24ff873d"],{"9e28":function(e,t,s){},b9a8:function(e,t,s){"use strict";s("cfdb")},c845:function(e,t,s){"use strict";s.r(t);var r=s("7a23"),a=Object(r["G"])("data-v-7358a82d");Object(r["u"])("data-v-7358a82d");var o={class:"image-carousel"},i={ref:"background",class:"background"},n={key:1,class:"row info-container"},h={class:"col-6 weather-container"},c={key:0},u={class:"col-6 date-time-container"};Object(r["s"])();var m=a((function(e,t,s,a,m,d){var f=Object(r["z"])("Loading"),l=Object(r["z"])("Weather"),w=Object(r["z"])("DateTime");return Object(r["r"])(),Object(r["e"])("div",o,[m.images.length?Object(r["f"])("",!0):(Object(r["r"])(),Object(r["e"])(f,{key:0})),Object(r["h"])("div",i,null,512),Object(r["h"])("img",{ref:"img",src:d.imgURL,alt:"Your carousel images",style:{display:m.images.length?"block":"none"}},null,12,["src"]),d._showDate||d._showTime?(Object(r["r"])(),Object(r["e"])("div",n,[Object(r["h"])("div",h,[d._showWeather?(Object(r["r"])(),Object(r["e"])(l,{key:1,"show-icon":d._showWeatherIcon,"show-summary":d._showWeatherSummary,"show-temperature":d._showTemperature,"icon-color":s.weatherIconColor,"icon-size":s.weatherIconSize,animate:d._animateWeatherIcon},null,8,["show-icon","show-summary","show-temperature","icon-color","icon-size","animate"])):(Object(r["r"])(),Object(r["e"])("span",c," "))]),Object(r["h"])("div",u,[d._showTime||d._showDate?(Object(r["r"])(),Object(r["e"])(w,{key:0,"show-date":d._showDate,"show-time":d._showTime,"show-seconds":d._showSeconds},null,8,["show-date","show-time","show-seconds"])):Object(r["f"])("",!0)])])):Object(r["f"])("",!0)])})),d=(s("a9e3"),s("96cf"),s("1da1")),f=s("3e54"),l=s("3a5e"),w=s("365a"),g=s("5b43"),b={name:"ImageCarousel",components:{Weather:g["default"],DateTime:w["default"],Loading:l["a"]},mixins:[f["a"]],props:{imgDir:{type:String,required:!0},refreshSeconds:{type:Number,default:15},showDate:{default:!1},showTime:{default:!1},showSeconds:{default:!1},showWeather:{default:!1},showTemperature:{default:!0},showWeatherIcon:{default:!0},showWeatherSummary:{default:!0},weatherIconColor:{type:String,default:"white"},weatherIconSize:{type:Number,default:70},animateWeatherIcon:{default:!0}},data:function(){return{images:[],currentImage:void 0,loading:!1}},computed:{imgURL:function(){var e=8008;return"backend.http"in this.$root.config&&"port"in this.$root.config["backend.http"]&&(e=this.$root.config["backend.http"].port),"//"+window.location.hostname+":"+e+this.currentImage},_showDate:function(){return this.parseBoolean(this.showDate)},_showTime:function(){return this.parseBoolean(this.showTime)},_showSeconds:function(){return this.parseBoolean(this.showSeconds)},_showTemperature:function(){return this.parseBoolean(this.showTemperature)},_showWeather:function(){return this.parseBoolean(this.showWeather)},_showWeatherIcon:function(){return this.parseBoolean(this.showWeatherIcon)},_showWeatherSummary:function(){return this.parseBoolean(this.showWeatherSummary)},_animateWeatherIcon:function(){return this.parseBoolean(this.animateWeatherIcon)}},methods:{refresh:function(){var e=this;return Object(d["a"])(regeneratorRuntime.mark((function t(){return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:if(e.images.length){t.next=10;break}return e.loading=!0,t.prev=2,t.next=5,e.request("utils.search_web_directory",{directory:e.imgDir,extensions:[".jpg",".jpeg",".png"]});case 5:e.images=t.sent,e.shuffleImages();case 7:return t.prev=7,e.loading=!1,t.finish(7);case 10:e.images.length&&(e.currentImage=e.images.pop());case 11:case"end":return t.stop()}}),t,null,[[2,,7,10]])})))()},onNewImage:function(){if(this.$refs.img&&(this.$refs.background.style["background-image"]="url("+this.imgURL+")",this.$refs.img.style.width="auto",this.$refs.img.width>this.$refs.img.height)){var e=this.$refs.img.width/this.$refs.img.height;4/3<=e<=16/9&&(this.$refs.img.style.width="100%"),e<=4/3&&(this.$refs.img.style.height="100%")}},shuffleImages:function(){for(var e=this.images.length-1;e>0;e--){var t=Math.floor(Math.random()*(e+1)),s=this.images[e];this.images[e]=this.images[t],this.images[t]=s}}},mounted:function(){this.$refs.img.addEventListener("load",this.onNewImage),this.$refs.img.addEventListener("error",this.refresh),this.refresh(),setInterval(this.refresh,Math.round(1e3*this.refreshSeconds))}};s("b9a8"),s("d233");b.render=m,b.__scopeId="data-v-7358a82d";t["default"]=b},cfdb:function(e,t,s){},d233:function(e,t,s){"use strict";s("9e28")}}]);
//# sourceMappingURL=chunk-24ff873d.0f916e0f.js.map
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-24ff873d"],{"9e28":function(e,t,s){},b9a8:function(e,t,s){"use strict";s("cfdb")},c845:function(e,t,s){"use strict";s.r(t);var r=s("7a23"),a=Object(r["J"])("data-v-7358a82d");Object(r["u"])("data-v-7358a82d");var o={class:"image-carousel"},i={ref:"background",class:"background"},n={key:1,class:"row info-container"},h={class:"col-6 weather-container"},c={key:0},u={class:"col-6 date-time-container"};Object(r["s"])();var m=a((function(e,t,s,a,m,d){var f=Object(r["z"])("Loading"),l=Object(r["z"])("Weather"),w=Object(r["z"])("DateTime");return Object(r["r"])(),Object(r["e"])("div",o,[m.images.length?Object(r["f"])("",!0):(Object(r["r"])(),Object(r["e"])(f,{key:0})),Object(r["h"])("div",i,null,512),Object(r["h"])("img",{ref:"img",src:d.imgURL,alt:"Your carousel images",style:{display:m.images.length?"block":"none"}},null,12,["src"]),d._showDate||d._showTime?(Object(r["r"])(),Object(r["e"])("div",n,[Object(r["h"])("div",h,[d._showWeather?(Object(r["r"])(),Object(r["e"])(l,{key:1,"show-icon":d._showWeatherIcon,"show-summary":d._showWeatherSummary,"show-temperature":d._showTemperature,"icon-color":s.weatherIconColor,"icon-size":s.weatherIconSize,animate:d._animateWeatherIcon},null,8,["show-icon","show-summary","show-temperature","icon-color","icon-size","animate"])):(Object(r["r"])(),Object(r["e"])("span",c," "))]),Object(r["h"])("div",u,[d._showTime||d._showDate?(Object(r["r"])(),Object(r["e"])(w,{key:0,"show-date":d._showDate,"show-time":d._showTime,"show-seconds":d._showSeconds},null,8,["show-date","show-time","show-seconds"])):Object(r["f"])("",!0)])])):Object(r["f"])("",!0)])})),d=(s("a9e3"),s("96cf"),s("1da1")),f=s("3e54"),l=s("3a5e"),w=s("365a"),g=s("5b43"),b={name:"ImageCarousel",components:{Weather:g["default"],DateTime:w["default"],Loading:l["a"]},mixins:[f["a"]],props:{imgDir:{type:String,required:!0},refreshSeconds:{type:Number,default:15},showDate:{default:!1},showTime:{default:!1},showSeconds:{default:!1},showWeather:{default:!1},showTemperature:{default:!0},showWeatherIcon:{default:!0},showWeatherSummary:{default:!0},weatherIconColor:{type:String,default:"white"},weatherIconSize:{type:Number,default:70},animateWeatherIcon:{default:!0}},data:function(){return{images:[],currentImage:void 0,loading:!1}},computed:{imgURL:function(){var e=8008;return"backend.http"in this.$root.config&&"port"in this.$root.config["backend.http"]&&(e=this.$root.config["backend.http"].port),"//"+window.location.hostname+":"+e+this.currentImage},_showDate:function(){return this.parseBoolean(this.showDate)},_showTime:function(){return this.parseBoolean(this.showTime)},_showSeconds:function(){return this.parseBoolean(this.showSeconds)},_showTemperature:function(){return this.parseBoolean(this.showTemperature)},_showWeather:function(){return this.parseBoolean(this.showWeather)},_showWeatherIcon:function(){return this.parseBoolean(this.showWeatherIcon)},_showWeatherSummary:function(){return this.parseBoolean(this.showWeatherSummary)},_animateWeatherIcon:function(){return this.parseBoolean(this.animateWeatherIcon)}},methods:{refresh:function(){var e=this;return Object(d["a"])(regeneratorRuntime.mark((function t(){return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:if(e.images.length){t.next=10;break}return e.loading=!0,t.prev=2,t.next=5,e.request("utils.search_web_directory",{directory:e.imgDir,extensions:[".jpg",".jpeg",".png"]});case 5:e.images=t.sent,e.shuffleImages();case 7:return t.prev=7,e.loading=!1,t.finish(7);case 10:e.images.length&&(e.currentImage=e.images.pop());case 11:case"end":return t.stop()}}),t,null,[[2,,7,10]])})))()},onNewImage:function(){if(this.$refs.img&&(this.$refs.background.style["background-image"]="url("+this.imgURL+")",this.$refs.img.style.width="auto",this.$refs.img.width>this.$refs.img.height)){var e=this.$refs.img.width/this.$refs.img.height;4/3<=e<=16/9&&(this.$refs.img.style.width="100%"),e<=4/3&&(this.$refs.img.style.height="100%")}},shuffleImages:function(){for(var e=this.images.length-1;e>0;e--){var t=Math.floor(Math.random()*(e+1)),s=this.images[e];this.images[e]=this.images[t],this.images[t]=s}}},mounted:function(){this.$refs.img.addEventListener("load",this.onNewImage),this.$refs.img.addEventListener("error",this.refresh),this.refresh(),setInterval(this.refresh,Math.round(1e3*this.refreshSeconds))}};s("b9a8"),s("d233");b.render=m,b.__scopeId="data-v-7358a82d";t["default"]=b},cfdb:function(e,t,s){},d233:function(e,t,s){"use strict";s("9e28")}}]);
//# sourceMappingURL=chunk-24ff873d.f955ad3b.js.map

View file

@ -1,2 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d2091df"],{a84f:function(e,t,n){"use strict";n.r(t);var r=n("7a23");function i(e,t,n,i,u,s){var a=Object(r["z"])("Loading"),o=Object(r["z"])("LightPlugin");return Object(r["r"])(),Object(r["e"])(r["a"],null,[u.loading?(Object(r["r"])(),Object(r["e"])(a,{key:0})):Object(r["f"])("",!0),Object(r["h"])(o,{"plugin-name":"light.hue",config:n.config,lights:u.lights,groups:u.groups,scenes:u.scenes,animations:u.animations,"initial-group":s.initialGroup,"loading-groups":u.loadingGroups,onGroupToggle:s.toggleGroup},null,8,["config","lights","groups","scenes","animations","initial-group","loading-groups","onGroupToggle"])],64)}n("4de4"),n("13d5"),n("b0c0"),n("4fad"),n("b64b"),n("d3b7"),n("3ca3"),n("ddb0");var u=n("b85c"),s=(n("96cf"),n("1da1")),a=n("5530"),o=n("3835"),c=n("cf99"),g=n("3e54"),p=n("3a5e"),l={name:"LightHue",components:{Loading:p["a"],LightPlugin:c["default"]},mixins:[g["a"]],props:{config:{type:Object,default:function(){}}},data:function(){return{lights:{},groups:{},scenes:{},animations:{},loading:!1,loadingLights:{},loadingGroups:{}}},computed:{groupsByName:function(){return this.groups?Object.entries(this.groups).reduce((function(e,t){var n=Object(o["a"])(t,2),r=n[0],i=n[1];return e[i.name||r]=Object(a["a"])(Object(a["a"])({},i),{},{id:r}),e}),{}):{}},initialGroup:function(){if(!this.config.groups||!Object.keys(this.config.groups).length)return null;var e=this.config.groups[0];return e in this.groups?this.groups[e].id:e in this.groupsByName?this.groupsByName[e].id:null}},methods:{getLights:function(){var e=this;return Object(s["a"])(regeneratorRuntime.mark((function t(){return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:return t.next=2,e.request("light.hue.get_lights");case 2:return t.abrupt("return",t.sent);case 3:case"end":return t.stop()}}),t)})))()},getGroups:function(){var e=this;return Object(s["a"])(regeneratorRuntime.mark((function t(){return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:return t.t0=Object,t.next=3,e.request("light.hue.get_groups");case 3:return t.t1=t.sent,t.abrupt("return",t.t0.entries.call(t.t0,t.t1).filter((function(e){return!e[1].recycle&&"room"===e[1].type.toLowerCase()})).reduce((function(e,t){var n=Object(o["a"])(t,2),r=n[0],i=n[1];return e[r]=i,e}),{}));case 5:case"end":return t.stop()}}),t)})))()},getScenes:function(){var e=this;return Object(s["a"])(regeneratorRuntime.mark((function t(){return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:return t.next=2,e.request("light.hue.get_scenes");case 2:return t.abrupt("return",t.sent);case 3:case"end":return t.stop()}}),t)})))()},toggleGroup:function(e){var t=this;return Object(s["a"])(regeneratorRuntime.mark((function n(){var r;return regeneratorRuntime.wrap((function(n){while(1)switch(n.prev=n.next){case 0:return r=[],null!=e&&r.push(e.name),t.setGroupsLoading(e),n.prev=3,n.next=6,t.request("light.hue.toggle",{groups:r});case 6:return n.next=8,t.refresh();case 8:return n.prev=8,t.unsetGroupsLoading(e),n.finish(8);case 11:case"end":return n.stop()}}),n,null,[[3,,8,11]])})))()},refresh:function(){var e=this;return Object(s["a"])(regeneratorRuntime.mark((function t(){var n,r;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:return e.loading=!0,t.prev=1,t.next=4,Promise.all([e.getLights(),e.getGroups(),e.getScenes()]);case 4:n=t.sent,r=Object(o["a"])(n,3),e.lights=r[0],e.groups=r[1],e.scenes=r[2];case 9:return t.prev=9,e.loading=!1,t.finish(9);case 12:case"end":return t.stop()}}),t,null,[[1,,9,12]])})))()},setGroupsLoading:function(){for(var e={},t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];if(n.length&&n[0]){var i,s=Object(u["a"])(n);try{for(s.s();!(i=s.n()).done;){var o=i.value;e[o.id]=!0}}catch(c){s.e(c)}finally{s.f()}}else e=Object.keys(this.groups);this.loadingGroups=Object(a["a"])(Object(a["a"])({},this.loadingGroups),e)},unsetGroupsLoading:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];for(var r=0,i=t;r<i.length;r++){var u=i[r];u.id in this.loadingGroups&&delete this.loadingGroups[u.id]}}},mounted:function(){this.refresh()}};l.render=i;t["default"]=l}}]);
//# sourceMappingURL=chunk-2d2091df.377ea7b0.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,2 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-4bbbb9a3"],{"365a":function(e,t,n){"use strict";n.r(t);var o=n("7a23"),s=Object(o["G"])("data-v-4835dfb0");Object(o["u"])("data-v-4835dfb0");var a={class:"date-time"};Object(o["s"])();var i=s((function(e,t,n,s,i,r){return Object(o["r"])(),Object(o["e"])("div",a,[r._showDate?(Object(o["r"])(),Object(o["e"])("div",{key:0,class:"date",textContent:Object(o["C"])(e.formatDate(e.now))},null,8,["textContent"])):Object(o["f"])("",!0),r._showTime?(Object(o["r"])(),Object(o["e"])("div",{key:1,class:"time",textContent:Object(o["C"])(e.formatTime(e.now,r._showSeconds))},null,8,["textContent"])):Object(o["f"])("",!0)])})),r=n("3e54"),c={name:"DateTime",mixins:[r["a"]],props:{showDate:{required:!1,default:!0},showTime:{required:!1,default:!0},showSeconds:{required:!1,default:!0}},computed:{_showTime:function(){return this.parseBoolean(this.showTime)},_showDate:function(){return this.parseBoolean(this.showDate)},_showSeconds:function(){return this.parseBoolean(this.showSeconds)}},data:function(){return{now:new Date}},methods:{refreshTime:function(){this.now=new Date}},mounted:function(){this.refreshTime(),setInterval(this.refreshTime,1e3)}};n("a8ae");c.render=i,c.__scopeId="data-v-4835dfb0";t["default"]=c},"5e1e":function(e,t,n){},a8ae:function(e,t,n){"use strict";n("5e1e")}}]);
//# sourceMappingURL=chunk-4bbbb9a3.c1ba820e.js.map
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-4bbbb9a3"],{"365a":function(e,t,n){"use strict";n.r(t);var o=n("7a23"),s=Object(o["J"])("data-v-4835dfb0");Object(o["u"])("data-v-4835dfb0");var a={class:"date-time"};Object(o["s"])();var i=s((function(e,t,n,s,i,r){return Object(o["r"])(),Object(o["e"])("div",a,[r._showDate?(Object(o["r"])(),Object(o["e"])("div",{key:0,class:"date",textContent:Object(o["C"])(e.formatDate(e.now))},null,8,["textContent"])):Object(o["f"])("",!0),r._showTime?(Object(o["r"])(),Object(o["e"])("div",{key:1,class:"time",textContent:Object(o["C"])(e.formatTime(e.now,r._showSeconds))},null,8,["textContent"])):Object(o["f"])("",!0)])})),r=n("3e54"),c={name:"DateTime",mixins:[r["a"]],props:{showDate:{required:!1,default:!0},showTime:{required:!1,default:!0},showSeconds:{required:!1,default:!0}},computed:{_showTime:function(){return this.parseBoolean(this.showTime)},_showDate:function(){return this.parseBoolean(this.showDate)},_showSeconds:function(){return this.parseBoolean(this.showSeconds)}},data:function(){return{now:new Date}},methods:{refreshTime:function(){this.now=new Date}},mounted:function(){this.refreshTime(),setInterval(this.refreshTime,1e3)}};n("a8ae");c.render=i,c.__scopeId="data-v-4835dfb0";t["default"]=c},"5e1e":function(e,t,n){},a8ae:function(e,t,n){"use strict";n("5e1e")}}]);
//# sourceMappingURL=chunk-4bbbb9a3.6f0e4975.js.map

View file

@ -1 +1 @@
{"version":3,"sources":["webpack:///./src/components/widgets/DateTime/Index.vue","webpack:///./src/components/widgets/DateTime/Index.vue?de64","webpack:///./src/components/widgets/DateTime/Index.vue?fa60"],"names":["class","_showDate","now","_showTime","_showSeconds","name","mixins","Utils","props","showDate","required","default","showTime","showSeconds","computed","this","parseBoolean","data","Date","methods","refreshTime","mounted","setInterval","render","__scopeId"],"mappings":"sNACOA,MAAM,a,wEAAX,eAGM,MAHN,EAGM,CAF6C,EAAAC,W,iBAAjD,eAA8D,O,MAAzDD,MAAM,O,YAAO,eAAwB,EAAN,WAAC,EAAAE,O,+CAC0B,EAAAC,W,iBAA/D,eAA4E,O,MAAvEH,MAAM,O,YAAO,eAAsC,EAApB,WAAC,EAAAE,IAAK,EAAAE,gB,gEAQ/B,GACbC,KAAM,WACNC,OAAQ,CAACC,EAAA,MACTC,MAAO,CAELC,SAAU,CACRC,UAAU,EACVC,SAAS,GAIXC,SAAU,CACRF,UAAU,EACVC,SAAS,GAIXE,YAAa,CACXH,UAAU,EACVC,SAAS,IAIbG,SAAU,CACRX,UADQ,WAEN,OAAOY,KAAKC,aAAaD,KAAKH,WAGhCX,UALQ,WAMN,OAAOc,KAAKC,aAAaD,KAAKN,WAGhCL,aATQ,WAUN,OAAOW,KAAKC,aAAaD,KAAKF,eAIlCI,KAAM,WACJ,MAAO,CACLf,IAAK,IAAIgB,OAIbC,QAAS,CACPC,YADO,WAELL,KAAKb,IAAM,IAAIgB,OAInBG,QAAS,WACPN,KAAKK,cACLE,YAAYP,KAAKK,YAAa,O,UCzDlC,EAAOG,OAAS,EAChB,EAAOC,UAAY,kBAEJ,gB,2DCRf","file":"static/js/chunk-4bbbb9a3.c1ba820e.js","sourcesContent":["<template>\n <div class=\"date-time\">\n <div class=\"date\" v-text=\"formatDate(now)\" v-if=\"_showDate\" />\n <div class=\"time\" v-text=\"formatTime(now, _showSeconds)\" v-if=\"_showTime\" />\n </div>\n</template>\n\n<script>\nimport Utils from \"@/Utils\";\n\n// Widget to show date and time\nexport default {\n name: 'DateTime',\n mixins: [Utils],\n props: {\n // If false then don't display the date.\n showDate: {\n required: false,\n default: true,\n },\n\n // If false then don't display the time.\n showTime: {\n required: false,\n default: true,\n },\n\n // If false then don't display the seconds.\n showSeconds: {\n required: false,\n default: true,\n },\n },\n\n computed: {\n _showTime() {\n return this.parseBoolean(this.showTime)\n },\n\n _showDate() {\n return this.parseBoolean(this.showDate)\n },\n\n _showSeconds() {\n return this.parseBoolean(this.showSeconds)\n },\n },\n\n data: function() {\n return {\n now: new Date(),\n };\n },\n\n methods: {\n refreshTime() {\n this.now = new Date()\n },\n },\n\n mounted: function() {\n this.refreshTime()\n setInterval(this.refreshTime, 1000)\n },\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.date-time {\n .date {\n font-size: 1.1em;\n }\n\n .time {\n font-size: 2em;\n }\n}\n</style>\n","import { render } from \"./Index.vue?vue&type=template&id=4835dfb0&scoped=true&bindings={\\\"showDate\\\":\\\"props\\\",\\\"showTime\\\":\\\"props\\\",\\\"showSeconds\\\":\\\"props\\\",\\\"_showTime\\\":\\\"options\\\",\\\"_showDate\\\":\\\"options\\\",\\\"_showSeconds\\\":\\\"options\\\",\\\"refreshTime\\\":\\\"options\\\"}\"\nimport script from \"./Index.vue?vue&type=script&lang=js\"\nexport * from \"./Index.vue?vue&type=script&lang=js\"\n\nimport \"./Index.vue?vue&type=style&index=0&id=4835dfb0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-4835dfb0\"\n\nexport default script","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Index.vue?vue&type=style&index=0&id=4835dfb0&lang=scss&scoped=true\""],"sourceRoot":""}
{"version":3,"sources":["webpack:///./src/components/widgets/DateTime/Index.vue","webpack:///./src/components/widgets/DateTime/Index.vue?de64","webpack:///./src/components/widgets/DateTime/Index.vue?fa60"],"names":["class","_showDate","now","_showTime","_showSeconds","name","mixins","Utils","props","showDate","required","default","showTime","showSeconds","computed","this","parseBoolean","data","Date","methods","refreshTime","mounted","setInterval","render","__scopeId"],"mappings":"sNACOA,MAAM,a,wEAAX,eAGM,MAHN,EAGM,CAF6C,EAAAC,W,iBAAjD,eAA8D,O,MAAzDD,MAAM,O,YAAO,eAAwB,EAAN,WAAC,EAAAE,O,+CAC0B,EAAAC,W,iBAA/D,eAA4E,O,MAAvEH,MAAM,O,YAAO,eAAsC,EAApB,WAAC,EAAAE,IAAK,EAAAE,gB,gEAQ/B,GACbC,KAAM,WACNC,OAAQ,CAACC,EAAA,MACTC,MAAO,CAELC,SAAU,CACRC,UAAU,EACVC,SAAS,GAIXC,SAAU,CACRF,UAAU,EACVC,SAAS,GAIXE,YAAa,CACXH,UAAU,EACVC,SAAS,IAIbG,SAAU,CACRX,UADQ,WAEN,OAAOY,KAAKC,aAAaD,KAAKH,WAGhCX,UALQ,WAMN,OAAOc,KAAKC,aAAaD,KAAKN,WAGhCL,aATQ,WAUN,OAAOW,KAAKC,aAAaD,KAAKF,eAIlCI,KAAM,WACJ,MAAO,CACLf,IAAK,IAAIgB,OAIbC,QAAS,CACPC,YADO,WAELL,KAAKb,IAAM,IAAIgB,OAInBG,QAAS,WACPN,KAAKK,cACLE,YAAYP,KAAKK,YAAa,O,UCzDlC,EAAOG,OAAS,EAChB,EAAOC,UAAY,kBAEJ,gB,2DCRf","file":"static/js/chunk-4bbbb9a3.6f0e4975.js","sourcesContent":["<template>\n <div class=\"date-time\">\n <div class=\"date\" v-text=\"formatDate(now)\" v-if=\"_showDate\" />\n <div class=\"time\" v-text=\"formatTime(now, _showSeconds)\" v-if=\"_showTime\" />\n </div>\n</template>\n\n<script>\nimport Utils from \"@/Utils\";\n\n// Widget to show date and time\nexport default {\n name: 'DateTime',\n mixins: [Utils],\n props: {\n // If false then don't display the date.\n showDate: {\n required: false,\n default: true,\n },\n\n // If false then don't display the time.\n showTime: {\n required: false,\n default: true,\n },\n\n // If false then don't display the seconds.\n showSeconds: {\n required: false,\n default: true,\n },\n },\n\n computed: {\n _showTime() {\n return this.parseBoolean(this.showTime)\n },\n\n _showDate() {\n return this.parseBoolean(this.showDate)\n },\n\n _showSeconds() {\n return this.parseBoolean(this.showSeconds)\n },\n },\n\n data: function() {\n return {\n now: new Date(),\n };\n },\n\n methods: {\n refreshTime() {\n this.now = new Date()\n },\n },\n\n mounted: function() {\n this.refreshTime()\n setInterval(this.refreshTime, 1000)\n },\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.date-time {\n .date {\n font-size: 1.1em;\n }\n\n .time {\n font-size: 2em;\n }\n}\n</style>\n","import { render } from \"./Index.vue?vue&type=template&id=4835dfb0&scoped=true&bindings={\\\"showDate\\\":\\\"props\\\",\\\"showTime\\\":\\\"props\\\",\\\"showSeconds\\\":\\\"props\\\",\\\"_showTime\\\":\\\"options\\\",\\\"_showDate\\\":\\\"options\\\",\\\"_showSeconds\\\":\\\"options\\\",\\\"refreshTime\\\":\\\"options\\\"}\"\nimport script from \"./Index.vue?vue&type=script&lang=js\"\nexport * from \"./Index.vue?vue&type=script&lang=js\"\n\nimport \"./Index.vue?vue&type=style&index=0&id=4835dfb0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-4835dfb0\"\n\nexport default script","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Index.vue?vue&type=style&index=0&id=4835dfb0&lang=scss&scoped=true\""],"sourceRoot":""}

View file

@ -1,2 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-5710a9bc"],{"2e0b":function(e,t,s){"use strict";s("e458")},3737:function(e,t,s){"use strict";s.r(t);s("b64b");var a=s("7a23"),n=Object(a["G"])("data-v-6bc0bd70");Object(a["u"])("data-v-6bc0bd70");var r={class:"date-time-weather"},i={class:"row date-time-container"},o={class:"row weather-container"},c={class:"row sensors-container"},u={key:0,class:"row"},d={class:"col-3"},h=Object(a["h"])("div",{class:"col-6"}," ",-1),l={class:"col-3"};Object(a["s"])();var b=n((function(e,t,s,n,b,m){var f=Object(a["z"])("DateTime"),w=Object(a["z"])("Weather"),j=Object(a["z"])("Sensor");return Object(a["r"])(),Object(a["e"])("div",r,[Object(a["h"])("div",i,[m._showDate||m._showTime?(Object(a["r"])(),Object(a["e"])(f,{key:0,"show-date":m._showDate,"show-time":m._showTime,"show-seconds":m._showSeconds,animate:s.animate},null,8,["show-date","show-time","show-seconds","animate"])):Object(a["f"])("",!0)]),Object(a["h"])("div",o,[s.showWeather?(Object(a["r"])(),Object(a["e"])(w,{key:0,"show-summary":m._showSummary,animate:m._animate,"icon-size":s.iconSize,"refresh-seconds":s.weatherRefreshSeconds},null,8,["show-summary","animate","icon-size","refresh-seconds"])):Object(a["f"])("",!0)]),Object(a["h"])("div",c,[m._showSensors&&Object.keys(e.sensors).length?(Object(a["r"])(),Object(a["e"])("div",u,[Object(a["h"])("div",d,[null!=e.sensors.temperature?(Object(a["r"])(),Object(a["e"])(j,{key:0,"icon-class":"fas fa-thermometer-half",value:e.sensors.temperature,unit:"°"},null,8,["value"])):Object(a["f"])("",!0)]),h,Object(a["h"])("div",l,[null!=e.sensors.humidity?(Object(a["r"])(),Object(a["e"])(j,{key:0,"icon-class":"fas fa-tint",value:e.sensors.humidity,unit:"%"},null,8,["value"])):Object(a["f"])("",!0)])])):Object(a["f"])("",!0)])])})),m=(s("a9e3"),s("3e54")),f=s("365a"),w=s("5b43"),j=(s("b0c0"),Object(a["G"])("data-v-1efb373e"));Object(a["u"])("data-v-1efb373e");var O={class:"sensor"},p={key:0,class:"label-container col-6"},v={class:"value-container col-6"};Object(a["s"])();var y=j((function(e,t,s,n,r,i){return Object(a["r"])(),Object(a["e"])("div",O,[s.iconClass||s.name?(Object(a["r"])(),Object(a["e"])("div",p,[s.iconClass?(Object(a["r"])(),Object(a["e"])("i",{key:0,class:s.iconClass},null,2)):s.name?(Object(a["r"])(),Object(a["e"])("span",{key:1,textContent:Object(a["C"])(s.name)},null,8,["textContent"])):Object(a["f"])("",!0)])):Object(a["f"])("",!0),Object(a["h"])("div",v,[Object(a["h"])("span",{class:"value",textContent:Object(a["C"])(i._value)},null,8,["textContent"])])])})),S=(s("99af"),s("b680"),{name:"Sensor",props:{iconClass:{type:String,required:!1},name:{type:String,required:!1},value:{required:!1},unit:{type:String,required:!1},decimals:{type:Number,required:!1,default:1},isBoolean:{type:Boolean,required:!1,default:!1}},computed:{_value:function(){if(null==this.value)return"N/A";if(this.isBoolean)return this.parseBoolean(this.value);var e=parseFloat(this.value);return null!=this.decimals&&(e=e.toFixed(this.decimals)),this.unit&&(e="".concat(e).concat(this.unit)),e}}});s("2e0b");S.render=y,S.__scopeId="data-v-1efb373e";var _=S,q={name:"DateTimeWeather",mixins:[m["a"]],components:{Sensor:_,DateTime:f["default"],Weather:w["default"]},props:{animate:{required:!1,default:!0},iconSize:{type:Number,required:!1,default:50},showDate:{required:!1,default:!0},showTime:{required:!1,default:!0},showWeather:{required:!1,default:!0},showSummary:{required:!1,default:!0},showSensors:{required:!1,default:!0},showSeconds:{required:!1,default:!0},sensorTemperatureAttr:{type:String,required:!1,default:"temperature"},sensorHumidityAttr:{type:String,required:!1,default:"humidity"},weatherRefreshSeconds:{type:Number,required:!1,default:900}},computed:{_showDate:function(){return this.parseBoolean(this.showDate)},_showTime:function(){return this.parseBoolean(this.showTime)},_showSeconds:function(){return this.parseBoolean(this.showSeconds)},_showWeather:function(){return this.parseBoolean(this.showWeather)},_showSummary:function(){return this.parseBoolean(this.showSummary)},_showSensors:function(){return this.parseBoolean(this.showSensors)},_animate:function(){return this.parseBoolean(this.animate)}},data:function(){return{sensors:{}}},methods:{onSensorData:function(e){this.sensorTemperatureAttr in e.data&&(this.sensors.temperature=e.data.temperature),this.sensorHumidityAttr in e.data&&(this.sensors.humidity=e.data.humidity)}},mounted:function(){this.subscribe(this.onSensorData,"platypush.message.event.sensor.SensorDataChangeEvent")}};s("cd6d");q.render=b,q.__scopeId="data-v-6bc0bd70";t["default"]=q},"5d41":function(e,t,s){},cd6d:function(e,t,s){"use strict";s("5d41")},e458:function(e,t,s){}}]);
//# sourceMappingURL=chunk-5710a9bc.5aba1b9a.js.map
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-5710a9bc"],{"2e0b":function(e,t,s){"use strict";s("e458")},3737:function(e,t,s){"use strict";s.r(t);s("b64b");var a=s("7a23"),n=Object(a["J"])("data-v-6bc0bd70");Object(a["u"])("data-v-6bc0bd70");var r={class:"date-time-weather"},i={class:"row date-time-container"},o={class:"row weather-container"},c={class:"row sensors-container"},u={key:0,class:"row"},d={class:"col-3"},h=Object(a["h"])("div",{class:"col-6"}," ",-1),l={class:"col-3"};Object(a["s"])();var b=n((function(e,t,s,n,b,m){var f=Object(a["z"])("DateTime"),w=Object(a["z"])("Weather"),j=Object(a["z"])("Sensor");return Object(a["r"])(),Object(a["e"])("div",r,[Object(a["h"])("div",i,[m._showDate||m._showTime?(Object(a["r"])(),Object(a["e"])(f,{key:0,"show-date":m._showDate,"show-time":m._showTime,"show-seconds":m._showSeconds,animate:s.animate},null,8,["show-date","show-time","show-seconds","animate"])):Object(a["f"])("",!0)]),Object(a["h"])("div",o,[s.showWeather?(Object(a["r"])(),Object(a["e"])(w,{key:0,"show-summary":m._showSummary,animate:m._animate,"icon-size":s.iconSize,"refresh-seconds":s.weatherRefreshSeconds},null,8,["show-summary","animate","icon-size","refresh-seconds"])):Object(a["f"])("",!0)]),Object(a["h"])("div",c,[m._showSensors&&Object.keys(e.sensors).length?(Object(a["r"])(),Object(a["e"])("div",u,[Object(a["h"])("div",d,[null!=e.sensors.temperature?(Object(a["r"])(),Object(a["e"])(j,{key:0,"icon-class":"fas fa-thermometer-half",value:e.sensors.temperature,unit:"°"},null,8,["value"])):Object(a["f"])("",!0)]),h,Object(a["h"])("div",l,[null!=e.sensors.humidity?(Object(a["r"])(),Object(a["e"])(j,{key:0,"icon-class":"fas fa-tint",value:e.sensors.humidity,unit:"%"},null,8,["value"])):Object(a["f"])("",!0)])])):Object(a["f"])("",!0)])])})),m=(s("a9e3"),s("3e54")),f=s("365a"),w=s("5b43"),j=(s("b0c0"),Object(a["J"])("data-v-1efb373e"));Object(a["u"])("data-v-1efb373e");var O={class:"sensor"},p={key:0,class:"label-container col-6"},v={class:"value-container col-6"};Object(a["s"])();var y=j((function(e,t,s,n,r,i){return Object(a["r"])(),Object(a["e"])("div",O,[s.iconClass||s.name?(Object(a["r"])(),Object(a["e"])("div",p,[s.iconClass?(Object(a["r"])(),Object(a["e"])("i",{key:0,class:s.iconClass},null,2)):s.name?(Object(a["r"])(),Object(a["e"])("span",{key:1,textContent:Object(a["C"])(s.name)},null,8,["textContent"])):Object(a["f"])("",!0)])):Object(a["f"])("",!0),Object(a["h"])("div",v,[Object(a["h"])("span",{class:"value",textContent:Object(a["C"])(i._value)},null,8,["textContent"])])])})),S=(s("99af"),s("b680"),{name:"Sensor",props:{iconClass:{type:String,required:!1},name:{type:String,required:!1},value:{required:!1},unit:{type:String,required:!1},decimals:{type:Number,required:!1,default:1},isBoolean:{type:Boolean,required:!1,default:!1}},computed:{_value:function(){if(null==this.value)return"N/A";if(this.isBoolean)return this.parseBoolean(this.value);var e=parseFloat(this.value);return null!=this.decimals&&(e=e.toFixed(this.decimals)),this.unit&&(e="".concat(e).concat(this.unit)),e}}});s("2e0b");S.render=y,S.__scopeId="data-v-1efb373e";var _=S,q={name:"DateTimeWeather",mixins:[m["a"]],components:{Sensor:_,DateTime:f["default"],Weather:w["default"]},props:{animate:{required:!1,default:!0},iconSize:{type:Number,required:!1,default:50},showDate:{required:!1,default:!0},showTime:{required:!1,default:!0},showWeather:{required:!1,default:!0},showSummary:{required:!1,default:!0},showSensors:{required:!1,default:!0},showSeconds:{required:!1,default:!0},sensorTemperatureAttr:{type:String,required:!1,default:"temperature"},sensorHumidityAttr:{type:String,required:!1,default:"humidity"},weatherRefreshSeconds:{type:Number,required:!1,default:900}},computed:{_showDate:function(){return this.parseBoolean(this.showDate)},_showTime:function(){return this.parseBoolean(this.showTime)},_showSeconds:function(){return this.parseBoolean(this.showSeconds)},_showWeather:function(){return this.parseBoolean(this.showWeather)},_showSummary:function(){return this.parseBoolean(this.showSummary)},_showSensors:function(){return this.parseBoolean(this.showSensors)},_animate:function(){return this.parseBoolean(this.animate)}},data:function(){return{sensors:{}}},methods:{onSensorData:function(e){this.sensorTemperatureAttr in e.data&&(this.sensors.temperature=e.data.temperature),this.sensorHumidityAttr in e.data&&(this.sensors.humidity=e.data.humidity)}},mounted:function(){this.subscribe(this.onSensorData,"platypush.message.event.sensor.SensorDataChangeEvent")}};s("cd6d");q.render=b,q.__scopeId="data-v-6bc0bd70";t["default"]=q},"5d41":function(e,t,s){},cd6d:function(e,t,s){"use strict";s("5d41")},e458:function(e,t,s){}}]);
//# sourceMappingURL=chunk-5710a9bc.47bb3f2d.js.map

View file

@ -1,2 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-62a3d08e"],{"2eb2":function(e,t,n){"use strict";n("8647")},"3c97":function(e,t,n){"use strict";n.r(t);n("fb6a");var a=n("7a23"),s=Object(a["G"])("data-v-bb595e58");Object(a["u"])("data-v-bb595e58");var r={class:"calendar"},c={key:1,class:"no-events"},i={key:2,class:"event upcoming-event"},o={class:"time"},d={key:3,class:"event-list"};Object(a["s"])();var u=s((function(e,t,n,s,u,b){var l=Object(a["z"])("Loading");return Object(a["r"])(),Object(a["e"])("div",r,[e.loading?(Object(a["r"])(),Object(a["e"])(l,{key:0})):e.events.length?e.events.length>0?(Object(a["r"])(),Object(a["e"])("div",i,[Object(a["h"])("div",{class:"date",textContent:Object(a["C"])(e.formatDate(e.events[0].start))},null,8,["textContent"]),Object(a["h"])("div",{class:"summary",textContent:Object(a["C"])(e.events[0].summary)},null,8,["textContent"]),Object(a["h"])("div",o,Object(a["C"])(e.formatTime(e.events[0].start,!1))+" - "+Object(a["C"])(e.formatTime(e.events[0].end,!1)),1)])):Object(a["f"])("",!0):(Object(a["r"])(),Object(a["e"])("div",c," No events found ")),e.events.length>1?(Object(a["r"])(),Object(a["e"])("div",d,[(Object(a["r"])(!0),Object(a["e"])(a["a"],null,Object(a["x"])(e.events.slice(1,n.maxEvents),(function(t){return Object(a["r"])(),Object(a["e"])("div",{class:"event",key:t.id},[Object(a["h"])("div",{class:"date col-2",textContent:Object(a["C"])(e.formatDate(t.start))},null,8,["textContent"]),Object(a["h"])("div",{class:"time col-2",textContent:Object(a["C"])(e.formatTime(t.start,!1))},null,8,["textContent"]),Object(a["h"])("div",{class:"summary col-8",textContent:Object(a["C"])(t.summary)},null,8,["textContent"])])})),128))])):Object(a["f"])("",!0)])})),b=(n("d81d"),n("a9e3"),n("b680"),n("96cf"),n("1da1")),l=n("3e54"),v=n("3a5e"),j={name:"Calendar",components:{Loading:v["a"]},mixins:[l["a"]],props:{maxEvents:{type:Number,required:!1,default:10},refreshSeconds:{type:Number,required:!1,default:600}},data:function(){return{events:[],loading:!1}},methods:{refresh:function(){var e=Object(b["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return this.loading=!0,e.prev=1,e.next=4,this.request("calendar.get_upcoming_events");case 4:this.events=e.sent.map((function(e){return e.start&&(e.start=new Date(e.start.dateTime||e.start.date)),e.end&&(e.end=new Date(e.end.dateTime||e.end.date)),e}));case 5:return e.prev=5,this.loading=!1,e.finish(5);case 8:case"end":return e.stop()}}),e,this,[[1,,5,8]])})));function t(){return e.apply(this,arguments)}return t}()},mounted:function(){this.refresh(),setInterval(this.refresh,parseInt((1e3*this.refreshSeconds).toFixed(0)))}};n("2eb2");j.render=u,j.__scopeId="data-v-bb595e58";t["default"]=j},8647:function(e,t,n){}}]);
//# sourceMappingURL=chunk-62a3d08e.cd0ca5eb.js.map
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-62a3d08e"],{"2eb2":function(e,t,n){"use strict";n("8647")},"3c97":function(e,t,n){"use strict";n.r(t);n("fb6a");var a=n("7a23"),s=Object(a["J"])("data-v-bb595e58");Object(a["u"])("data-v-bb595e58");var r={class:"calendar"},c={key:1,class:"no-events"},i={key:2,class:"event upcoming-event"},o={class:"time"},d={key:3,class:"event-list"};Object(a["s"])();var u=s((function(e,t,n,s,u,b){var l=Object(a["z"])("Loading");return Object(a["r"])(),Object(a["e"])("div",r,[e.loading?(Object(a["r"])(),Object(a["e"])(l,{key:0})):e.events.length?e.events.length>0?(Object(a["r"])(),Object(a["e"])("div",i,[Object(a["h"])("div",{class:"date",textContent:Object(a["C"])(e.formatDate(e.events[0].start))},null,8,["textContent"]),Object(a["h"])("div",{class:"summary",textContent:Object(a["C"])(e.events[0].summary)},null,8,["textContent"]),Object(a["h"])("div",o,Object(a["C"])(e.formatTime(e.events[0].start,!1))+" - "+Object(a["C"])(e.formatTime(e.events[0].end,!1)),1)])):Object(a["f"])("",!0):(Object(a["r"])(),Object(a["e"])("div",c," No events found ")),e.events.length>1?(Object(a["r"])(),Object(a["e"])("div",d,[(Object(a["r"])(!0),Object(a["e"])(a["a"],null,Object(a["x"])(e.events.slice(1,n.maxEvents),(function(t){return Object(a["r"])(),Object(a["e"])("div",{class:"event",key:t.id},[Object(a["h"])("div",{class:"date col-2",textContent:Object(a["C"])(e.formatDate(t.start))},null,8,["textContent"]),Object(a["h"])("div",{class:"time col-2",textContent:Object(a["C"])(e.formatTime(t.start,!1))},null,8,["textContent"]),Object(a["h"])("div",{class:"summary col-8",textContent:Object(a["C"])(t.summary)},null,8,["textContent"])])})),128))])):Object(a["f"])("",!0)])})),b=(n("d81d"),n("a9e3"),n("b680"),n("96cf"),n("1da1")),l=n("3e54"),v=n("3a5e"),j={name:"Calendar",components:{Loading:v["a"]},mixins:[l["a"]],props:{maxEvents:{type:Number,required:!1,default:10},refreshSeconds:{type:Number,required:!1,default:600}},data:function(){return{events:[],loading:!1}},methods:{refresh:function(){var e=Object(b["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return this.loading=!0,e.prev=1,e.next=4,this.request("calendar.get_upcoming_events");case 4:this.events=e.sent.map((function(e){return e.start&&(e.start=new Date(e.start.dateTime||e.start.date)),e.end&&(e.end=new Date(e.end.dateTime||e.end.date)),e}));case 5:return e.prev=5,this.loading=!1,e.finish(5);case 8:case"end":return e.stop()}}),e,this,[[1,,5,8]])})));function t(){return e.apply(this,arguments)}return t}()},mounted:function(){this.refresh(),setInterval(this.refresh,parseInt((1e3*this.refreshSeconds).toFixed(0)))}};n("2eb2");j.render=u,j.__scopeId="data-v-bb595e58";t["default"]=j},8647:function(e,t,n){}}]);
//# sourceMappingURL=chunk-62a3d08e.8fc4fd3a.js.map

View file

@ -1,2 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-e8078048"],{"3ddd":function(e,t,r){},a41f:function(e,t,r){"use strict";r("3ddd")},c306:function(e,t,r){"use strict";r.r(t);var n=r("7a23"),s=Object(n["G"])("data-v-919872a2");Object(n["u"])("data-v-919872a2");var i={class:"rss-news"},c={key:0,class:"article"};Object(n["s"])();var u=s((function(e,t,r,s,u,a){return Object(n["r"])(),Object(n["e"])("div",i,[e.currentArticle?(Object(n["r"])(),Object(n["e"])("div",c,[Object(n["h"])("div",{class:"source",textContent:Object(n["C"])(e.currentArticle.source)},null,8,["textContent"]),Object(n["h"])("div",{class:"title",textContent:Object(n["C"])(e.currentArticle.title)},null,8,["textContent"]),Object(n["h"])("div",{class:"published",textContent:Object(n["C"])(new Date(e.currentArticle.published).toDateString()+", "+new Date(e.currentArticle.published).toTimeString().substring(0,5))},null,8,["textContent"])])):Object(n["f"])("",!0)])})),a=(r("a9e3"),r("b680"),r("2909")),d=(r("96cf"),r("1da1")),l=r("3e54"),o={name:"RssNews",mixins:[l["a"]],props:{db:{type:String,required:!0},limit:{type:Number,required:!1,default:25},refreshSeconds:{type:Number,required:!1,default:15}},data:function(){return{articles:[],queue:[],currentArticle:void 0}},methods:{refresh:function(){var e=Object(d["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:if(this.queue.length){e.next=5;break}return e.next=3,this.request("db.select",{engine:this.db,query:"\n select s.title as source, e.title, e.summary,\n strftime('%Y-%m-%dT%H:%M:%fZ', e.published) as published\n from FeedEntry e join FeedSource s\n on e.source_id = s.id order by e.published desc limit ".concat(this.limit)});case 3:this.articles=e.sent,this.queue=Object(a["a"])(this.articles);case 5:if(this.queue.length){e.next=7;break}return e.abrupt("return");case 7:this.currentArticle=this.queue.pop();case 8:case"end":return e.stop()}}),e,this)})));function t(){return e.apply(this,arguments)}return t}()},mounted:function(){this.refresh(),setInterval(this.refresh,parseInt((1e3*this.refreshSeconds).toFixed(0)))}};r("a41f");o.render=u,o.__scopeId="data-v-919872a2";t["default"]=o}}]);
//# sourceMappingURL=chunk-e8078048.bc52467d.js.map
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-e8078048"],{"3ddd":function(e,t,r){},a41f:function(e,t,r){"use strict";r("3ddd")},c306:function(e,t,r){"use strict";r.r(t);var n=r("7a23"),s=Object(n["J"])("data-v-919872a2");Object(n["u"])("data-v-919872a2");var i={class:"rss-news"},c={key:0,class:"article"};Object(n["s"])();var u=s((function(e,t,r,s,u,a){return Object(n["r"])(),Object(n["e"])("div",i,[e.currentArticle?(Object(n["r"])(),Object(n["e"])("div",c,[Object(n["h"])("div",{class:"source",textContent:Object(n["C"])(e.currentArticle.source)},null,8,["textContent"]),Object(n["h"])("div",{class:"title",textContent:Object(n["C"])(e.currentArticle.title)},null,8,["textContent"]),Object(n["h"])("div",{class:"published",textContent:Object(n["C"])(new Date(e.currentArticle.published).toDateString()+", "+new Date(e.currentArticle.published).toTimeString().substring(0,5))},null,8,["textContent"])])):Object(n["f"])("",!0)])})),a=(r("a9e3"),r("b680"),r("2909")),d=(r("96cf"),r("1da1")),l=r("3e54"),o={name:"RssNews",mixins:[l["a"]],props:{db:{type:String,required:!0},limit:{type:Number,required:!1,default:25},refreshSeconds:{type:Number,required:!1,default:15}},data:function(){return{articles:[],queue:[],currentArticle:void 0}},methods:{refresh:function(){var e=Object(d["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:if(this.queue.length){e.next=5;break}return e.next=3,this.request("db.select",{engine:this.db,query:"\n select s.title as source, e.title, e.summary,\n strftime('%Y-%m-%dT%H:%M:%fZ', e.published) as published\n from FeedEntry e join FeedSource s\n on e.source_id = s.id order by e.published desc limit ".concat(this.limit)});case 3:this.articles=e.sent,this.queue=Object(a["a"])(this.articles);case 5:if(this.queue.length){e.next=7;break}return e.abrupt("return");case 7:this.currentArticle=this.queue.pop();case 8:case"end":return e.stop()}}),e,this)})));function t(){return e.apply(this,arguments)}return t}()},mounted:function(){this.refresh(),setInterval(this.refresh,parseInt((1e3*this.refreshSeconds).toFixed(0)))}};r("a41f");o.render=u,o.__scopeId="data-v-919872a2";t["default"]=o}}]);
//# sourceMappingURL=chunk-e8078048.e668de5f.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -11856,6 +11856,11 @@
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
"dev": true
},
"w3css": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/w3css/-/w3css-2.7.0.tgz",
"integrity": "sha1-gR8cj3eW20RB+k5On45PuPfxC18="
},
"watchpack": {
"version": "1.7.5",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",

View file

@ -17,7 +17,8 @@
"sass-loader": "^10.1.0",
"vue": "^3.0.0",
"vue-router": "^4.0.0-rc.3",
"vue-skycons": "^4.0.3"
"vue-skycons": "^4.0.3",
"w3css": "^2.7.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",

View file

@ -3,10 +3,11 @@ import Api from "@/utils/Api";
import DateTime from "@/utils/DateTime";
import Events from "@/utils/Events";
import Notification from "@/utils/Notification";
import Screen from "@/utils/Screen";
import Types from "@/utils/Types";
export default {
name: "Utils",
mixins: [Api, Notification, Events, DateTime, Types],
mixins: [Api, Notification, Events, DateTime, Screen, Types],
}
</script>

View file

@ -0,0 +1,306 @@
<template>
<div class="controls animation-controls" @click="$event.stopPropagation()">
<Loading v-if="loading" />
<div class="animation-container">
<div class="animation-header">
<div class="row">
<div class="col-3">
Run Animation
</div>
<div class="col-9">
<ToggleSwitch :value="animationRunning" @input="toggleAnimation" />
</div>
</div>
<div class="row">
<div class="col-3">Animation</div>
<div class="col-9">
<label>
<select class="selector" @click="selectedAnimation = $event.target.value">
<option value="color_transition">Color transition</option>
<option value="blink">Blink</option>
</select>
</label>
</div>
</div>
</div>
<div class="animation">
<div class="row" v-if="selectedAnimation === 'color_transition'">
<div class="col-3">
Hue range
</div>
<div class="col-9">
<RangeSlider :range="colorConverter.ranges.hue" :disabled="loading"
:value="animations.color_transition.hue_range"
@mouseup="animations.color_transition.hue_range = $event.target.value" />
</div>
</div>
<div class="row" v-if="selectedAnimation === 'color_transition'">
<div class="col-3">
Sat range
</div>
<div class="col-9">
<RangeSlider :range="colorConverter.ranges.sat" :disabled="loading"
:value="animations.color_transition.sat_range"
@mouseup="animations.color_transition.sat_range = $event.target.value" />
</div>
</div>
<div class="row" v-if="selectedAnimation === 'color_transition'">
<div class="col-3">
Bri range
</div>
<div class="col-9">
<RangeSlider :range="colorConverter.ranges.sat" :disabled="loading"
:value="animations.color_transition.bri_range"
@mouseup="animations.color_transition.bri_range = $event.target.value" />
</div>
</div>
<div class="row" v-if="selectedAnimation === 'color_transition'">
<div class="col-3">
Hue step
</div>
<div class="col-9">
<Slider :range="colorConverter.ranges.hue" :disabled="loading"
:value="animations.color_transition.hue_step"
@mouseup="animations.color_transition.hue_step = parseFloat($event.target.value)" />
</div>
</div>
<div class="row" v-if="selectedAnimation === 'color_transition'">
<div class="col-3">
Sat step
</div>
<div class="col-9">
<Slider :range="colorConverter.ranges.sat" :disabled="loading"
:value="animations.color_transition.sat_step"
@mouseup="animations.color_transition.sat_step = parseFloat($event.target.value)" />
</div>
</div>
<div class="row" v-if="selectedAnimation === 'color_transition'">
<div class="col-3">
Bri step
</div>
<div class="col-9">
<Slider :range="colorConverter.ranges.bri" :disabled="loading"
:value="animations.color_transition.bri_step"
@mouseup="animations.color_transition.bri_step = parseFloat($event.target.value)" />
</div>
</div>
<div class="row">
<div class="col-3">
Refresh seconds
</div>
<div class="col-9">
<label>
<input type="number" :value="animations[selectedAnimation].transition_seconds" step="0.1"
@input="animations[selectedAnimation].transition_seconds = parseFloat($event.target.value)" >
</label>
</div>
</div>
<div class="row">
<div class="col-3">
Duration (seconds)
</div>
<div class="col-9">
<label>
<input type="number" :value="animations[selectedAnimation].duration" step="5"
@input="animations[selectedAnimation].duration = $event.target.value?.length ? parseFloat($event.target.value) : null" >
</label>
</div>
</div>
</div>
</div>
<div class="lights">
<div class="row">
<label>
<input type="checkbox"
:checked="Object.keys(lights).length === Object.values(selectedLights).filter((v) => v).length" @click="toggleSelectAll">
Select all lights
</label>
</div>
<div class="row" v-for="(light, id) in lights" :key="id">
<label>
<input type="checkbox" v-model="selectedLights[id]" @input="selectedLights[id] = !selectedLights[id]">
{{ light.name }}
</label>
</div>
</div>
</div>
</template>
<script>
import Loading from "@/components/Loading";
import {ColorConverter} from "@/components/panels/Light/color";
import RangeSlider from "@/components/elements/RangeSlider";
import Slider from "@/components/elements/Slider";
import ToggleSwitch from "@/components/elements/ToggleSwitch";
import Utils from "@/Utils";
export default {
name: "Animate",
mixins: [Utils],
components: {ToggleSwitch, Slider, RangeSlider, Loading},
emits: ['start', 'stop'],
props: {
lights: {
type: Object,
},
group: {
type: Object,
},
loading: {
type: Boolean,
default: false,
},
colorConverter: {
type: Object,
default: () => new ColorConverter(),
},
runningAnimations: {
type: Object,
default: () => {},
}
},
data() {
return {
selectedAnimation: 'color_transition',
animation: {},
selectedLights: Object.keys(this.lights).reduce((obj, lightId) => {
obj[lightId] = true
return obj
}, {}),
animations: {
color_transition: {
hue_range: this.colorConverter.ranges.hue,
sat_range: [
parseInt((this.colorConverter.ranges.sat[1] - this.colorConverter.ranges.sat[0])/2),
this.colorConverter.ranges.sat[1]
],
bri_range: [
parseInt((this.colorConverter.ranges.bri[1] - this.colorConverter.ranges.bri[0]) * 0.75),
this.colorConverter.ranges.bri[1]
],
hue_step: parseInt((this.colorConverter.ranges.hue[1] - this.colorConverter.ranges.hue[0]) / 25),
sat_step: parseInt((this.colorConverter.ranges.sat[1] - this.colorConverter.ranges.sat[0]) / 50),
bri_step: parseInt((this.colorConverter.ranges.bri[1] - this.colorConverter.ranges.bri[0]) / 50),
transition_seconds: 1,
duration: null,
},
blink: {
transition_seconds: 1,
duration: null,
},
},
}
},
computed: {
animationRunning() {
return Object.keys(this.runningAnimations).length > 0
},
},
methods: {
toggleSelectAll() {
const select = Object.values(this.selectedLights).filter((v) => v).length < Object.keys(this.lights).length
Object.keys(this.lights).forEach((lightId) => {
this.selectedLights[lightId] = select
})
},
toggleAnimation() {
const eventType = this.animationRunning ? 'stop' : 'start'
const selectedLights = Object.entries(this.selectedLights).filter((light) => light[1]).map((light) => light[0])
if (!selectedLights.length) {
this.warn('No lights have been selected')
return
}
this.$emit(eventType, {
lights: selectedLights,
animation: {
...this.animations[this.selectedAnimation],
animation: this.selectedAnimation,
},
})
},
},
}
</script>
<style lang="scss" scoped>
$light-controls-bg: white;
.animation-container {
width: 100%;
.animation-header,
.animation {
padding-bottom: 0.5em;
margin-bottom: 0.5em;
box-shadow: $border-shadow-bottom;
}
}
.controls {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
margin-top: 2.25em;
background: $light-controls-bg;
padding: 0.5em 1em;
border-radius: 1em;
box-shadow: $plugin-panel-shadow;
.selector {
width: 100%;
}
.row {
width: 100%;
display: flex;
align-items: center;
padding: 0.5em 0;
& > div:last-child {
text-align: right;
}
}
.control {
padding-top: 0.25em;
}
.lights {
padding-top: 0.5em;
width: 100%;
.row {
display: flex;
align-items: center;
}
label {
width: 100%;
}
}
}
</style>

View file

@ -18,7 +18,7 @@
</div>
<div class="col-11 control">
<Slider :range="colorConverter.ranges.ct" :disabled="loading" :value="state.ct"
@change.stop="$emit(light ? 'set-light' : 'set-group', {temperature: parseInt($event.target.value)})" />
@mouseup.stop="$emit(light ? 'set-light' : 'set-group', {temperature: parseInt($event.target.value)})" />
</div>
</div>

View file

@ -23,14 +23,21 @@
<div class="lights-view" v-else>
<div class="row view-selector">
<button :class="{selected: selectedView === 'lights'}" title="Lights" @click="selectedView = 'lights'">
<i class="fas fa-lightbulb" /> &nbsp; Lights
<i class="icon fas fa-lightbulb" />
<span class="view-title">&nbsp; Lights</span>
</button>
<button :class="{selected: selectedView === 'scenes'}" title="Scenes" @click="selectedView = 'scenes'">
<i class="far fa-image" /> &nbsp; Scenes
<i class="icon far fa-image" />
<span class="view-title">&nbsp; Scenes</span>
</button>
<button :class="{selected: selectedView === 'animate'}" title="Animate"
@click="selectedView = 'animate'">
<i class="icon fas fa-video" />
<span class="view-title">&nbsp; Animate</span>
</button>
</div>
<div class="view" v-if="selectedView === 'lights'">
<div class="view fade-in" v-if="selectedView === 'lights'">
<keep-alive>
<div class="panel-row row" :class="{expanded: light.id === selectedLight}"
v-for="(light, id) in lightsSorted" :key="id"
@ -42,7 +49,7 @@
</keep-alive>
</div>
<div class="view" v-else-if="selectedView === 'scenes'">
<div class="view fade-in" v-else-if="selectedView === 'scenes'">
<keep-alive>
<div class="panel-row row" :class="{selected: scene.id === selectedScene}"
v-for="(scene, id) in scenesSorted" :key="id" @click="onSceneSelected(scene.id)">
@ -51,12 +58,19 @@
</keep-alive>
</div>
<div class="view group-controls" v-else-if="selectedView === 'group'">
<div class="view group-controls fade-in" v-else-if="selectedView === 'group'">
<keep-alive>
<Controls :group="group" :lights="lights" :color-converter="colorConverter"
@set-group="$emit('set-group', $event)" />
</keep-alive>
</div>
<div class="view group-controls fade-in" v-else-if="selectedView === 'animate'">
<keep-alive>
<Animate :group="group" :lights="lights" :color-converter="colorConverter" :running-animations="animations"
@start="$emit('start-animation', $event)" @stop="$emit('stop-animation', $event)" />
</keep-alive>
</div>
</div>
</MenuPanel>
</div>
@ -69,11 +83,12 @@ import Controls from "@/components/Light/Controls";
import MenuPanel from "@/components/MenuPanel";
import ToggleSwitch from "@/components/elements/ToggleSwitch";
import {ColorConverter} from "@/components/panels/Light/color";
import Animate from "@/components/Light/Animate";
export default {
name: "Group",
emits: ['close', 'group-toggle', 'light-toggle', 'set-light', 'select-scene'],
components: {ToggleSwitch, MenuPanel, Light, Scene, Controls},
emits: ['close', 'group-toggle', 'light-toggle', 'set-light', 'select-scene', 'start-animation', 'stop-animation'],
components: {Animate, ToggleSwitch, MenuPanel, Light, Scene, Controls},
props: {
lights: {
type: Object,
@ -87,6 +102,11 @@ export default {
type: Object,
},
animations: {
type: Object,
default: () => {},
},
colorConverter: {
type: Object,
default: () => new ColorConverter(),
@ -200,15 +220,12 @@ export default {
border-radius: 0;
button {
width: 50%;
width: 33.3%;
padding: 1.5em;
text-align: left;
opacity: 0.8;
box-shadow: $plugin-panel-entry-shadow;
&:first-child {
border-right: 0;
}
border-right: 0;
&.selected {
background: $selected-bg;
@ -218,6 +235,18 @@ export default {
background: $hover-bg;
}
}
@media screen and (max-width: $tablet) {
.view-title {
display: none;
}
.icon {
width: 100%;
text-align: center;
font-size: 1.2em;
}
}
}
}
</style>
@ -225,7 +254,10 @@ export default {
<style lang="scss">
.light-group-container {
.group-controls {
margin: 1em;
margin: 0;
padding: 1em;
background-color: $default-bg-6;
border-radius: 0 0 1em 1em;
.controls {
margin: 0;

View file

@ -2,11 +2,11 @@
<nav :class="{collapsed: collapsed}">
<div class="toggler" @click="collapsed = !collapsed">
<i class="fas fa-bars" />
<span class="hostname" v-if="!collapsed && hostname" v-text="hostname" />
<span class="hostname" v-if="hostname" v-text="hostname" />
</div>
<li v-for="name in Object.keys(panels)" :key="name" class="entry" :class="{selected: name === selectedPanel}"
@click="$emit('select', name)">
:title="name" @click="onItemClick(name)">
<a :href="`/#${name}`">
<span class="icon">
<i :class="icons[name].class" v-if="icons[name]?.class" />
@ -20,10 +20,12 @@
<script>
import { icons } from '@/assets/icons.json'
import Utils from "@/Utils";
export default {
name: "Nav",
emits: ['select'],
mixins: [Utils],
props: {
panels: {
type: Object,
@ -43,6 +45,12 @@ export default {
displayName(name) {
return name.split('.').map((token) => token[0].toUpperCase() + token.slice(1)).join(' ')
},
onItemClick(name) {
this.$emit('select', name)
if (this.isMobile())
this.collapsed = true
},
},
data() {
@ -52,25 +60,48 @@ export default {
host: null,
}
},
mounted() {
if (this.isMobile() && !this.$root.$route.hash.length)
this.collapsed = false
},
}
</script>
<!--suppress SassScssResolvedByNameOnly -->
<style lang="scss" scoped>
nav {
width: 20%;
min-width: 12.5em;
max-width: 25em;
height: 100%;
overflow: auto;
background: $nav-bg;
color: $nav-fg;
box-shadow: $nav-box-shadow-main;
margin-right: 4px;
@media screen and (max-width: $tablet) {
width: 100%;
height: 100vh;
background: $nav-bg;
color: $nav-fg;
box-shadow: $nav-box-shadow-main;
&:not(.collapsed) {
position: absolute;
top: 0;
left: 0;
z-index: 2;
}
}
@media screen and (min-width: $tablet) {
width: 20%;
min-width: 12.5em;
max-width: 25em;
height: 100%;
overflow: auto;
background: $nav-bg;
color: $nav-fg;
box-shadow: $nav-box-shadow-main;
margin-right: 4px;
}
li {
box-shadow: $nav-box-shadow-entry;
cursor: pointer;
list-style: none;
a {
display: block;
@ -104,20 +135,40 @@ nav {
font-size: 1.5em;
cursor: pointer;
padding: 0.4em;
align-items: center;
}
.hostname {
font-size: 0.7em;
.hostname {
font-size: 0.7em;
@media screen and (min-width: $tablet) {
margin-left: 1em;
}
@media screen and (max-width: $tablet) {
text-align: right;
margin-right: 0.25em;
flex-grow: 1;
}
}
&.collapsed {
width: 2.5em;
min-width: unset;
max-width: unset;
background: initial;
color: $nav-collapsed-fg;
box-shadow: $nav-box-shadow-collapsed;
@media screen and (min-width: $tablet) {
width: 2.5em;
min-width: unset;
max-width: unset;
background: initial;
color: $nav-collapsed-fg;
box-shadow: $nav-box-shadow-collapsed;
.hostname {
display: none;
}
}
@media screen and (max-width: $tablet) {
height: auto;
}
a {
color: $nav-collapsed-fg;
@ -129,7 +180,9 @@ nav {
.toggler {
text-align: center;
margin-bottom: 3em;
@media screen and (min-width: $tablet) {
margin-bottom: 3em;
}
}
li {
@ -154,6 +207,10 @@ nav {
.icon {
margin-right: 0;
}
@media screen and (max-width: $tablet) {
display: none;
}
}
}
}

View file

@ -0,0 +1,145 @@
<template>
<div class="range-slider">
<label>
<input class="slider" type="range" :value="v" :min="range[0]" :max="range[1]"
:disabled="disabled" @input="input" @change="changed" @mouseup="mouseup" @mousedown="mousedown"
@touchstart="mouseup" @touchend="mousedown" :ref="`input_${i}`" v-for="(v, i) in value" :key="i">
</label>
</div>
</template>
<script>
export default {
name: "RangeSlider",
emits: ['input', 'change', 'mouseup', 'mousedown'],
props: {
disabled: {
type: Boolean,
default: false,
},
range: {
type: Array,
default: () => [0, 100],
},
value: {
type: Array,
default: () => [0, 100],
},
},
methods: {
getEvent(event) {
return {
...event,
target: {
...event.target,
value: Object.values(this.$refs).map((input) => parseFloat(input.value)).sort(),
}
}
},
input(event) {
this.$emit('input', this.getEvent(event))
},
changed(event) {
this.$emit('change', this.getEvent(event))
},
mouseup(event) {
this.$emit('mouseup', this.getEvent(event))
},
mousedown(event) {
this.$emit('mousedown', this.getEvent(event))
},
},
mounted() {
if (this.value) {
const self = this
this.value.forEach((v, i) => {
self.$refs[`input_${i}`].value = v
})
}
},
}
</script>
<style lang="scss" scoped>
.range-slider {
position: relative;
display: flex;
label {
height: 2em;
}
.slider {
@include appearance(none);
@include transition(opacity .2s);
background: none;
width: 100%;
height: 2em;
position: absolute;
left: 0;
top: 0;
margin: 0;
padding: 0;
border-radius: 1em;
outline: none;
pointer-events: none;
overflow: hidden;
z-index: 20;
@mixin slider-thumb {
@include appearance(none);
position: relative;
width: 1.5em;
height: 1.5em;
pointer-events: all;
border-radius: 50%;
border: 0;
background: $slider-thumb-bg;
cursor: pointer;
z-index: 10;
outline: 0;
}
&::-webkit-slider-thumb { @include slider-thumb }
&::-moz-range-thumb { @include slider-thumb}
&::-moz-range-track {
@include appearance(none);
position: relative;
border: 0;
}
&::-moz-range-progress { height: 1em; }
&:first-child {
z-index: 21;
&::-moz-range-progress { background: $slider-bg; }
}
&:last-child {
background: $slider-bg;
&::-moz-range-progress { background: $slider-progress-bg; }
}
&[disabled] {
opacity: 0.3;
@mixin no-thumb {
display: none;
width: 0;
}
&::-moz-range-progress { background: none; }
&::-webkit-slider-runnable-track { background: none; }
&::-moz-range-thumb { @include no-thumb; }
&::-webkit-slider-thumb { @include no-thumb; }
}
}
}
</style>

View file

@ -1,8 +1,9 @@
<template>
<label>
<input class="slider" type="range" :min="range[0]" :max="range[1]" :value="value"
@change="$emit('input', $event)" @mouseup="$emit('mouseup', $event)"
@mousedown="$emit('mousedown', $event)">
<input class="slider" type="range" :min="range[0]" :max="range[1]" :value="value" :disabled="disabled"
@change="$emit('input', $event)" @mouseup="$emit('mouseup', $event)" @input="$emit('input', $event)"
@mousedown="$emit('mousedown', $event)" @touch="$emit('input', $event)"
@touchstart="$emit('mousedown', $event)" @touchend="$emit('mouseup', $event)">
</label>
</template>
@ -38,7 +39,7 @@ export default {
background: $slider-bg;
outline: none;
&::-webkit-slider-thumb {
@mixin slider-thumb {
@include appearance(none);
width: 1.5em;
height: 1.5em;
@ -48,43 +49,29 @@ export default {
cursor: pointer;
}
&::-moz-range-thumb {
@include appearance(none);
width: 1.5em;
height: 1.5em;
border-radius: 50%;
border: 0;
background: $slider-thumb-bg;
cursor: pointer;
}
&[disabled]::-webkit-slider-thumb {
display: none;
width: 0;
}
&[disabled]::-moz-range-thumb {
display: none;
width: 0;
}
&.disabled { opacity: 0.3; }
&::-moz-range-track {
@include appearance(none);
}
&::-webkit-slider-thumb { @include slider-thumb; }
&::-moz-range-thumb { @include slider-thumb; }
&::-moz-range-track { @include appearance(none); }
&::-webkit-progress-value,
&::-moz-range-progress {
background: $slider-progress-bg;
height: 1em;
}
&[disabled]::-webkit-progress-value {
background: none;
}
&[disabled] {
opacity: 0.3;
&[disabled]::-moz-range-progress {
background: none;
&::-webkit-progress-value,
&::-moz-range-progress {
background: none;
}
&::-webkit-slider-thumb,
&::-moz-range-thumb {
display: none;
width: 0;
}
}
}
</style>

View file

@ -6,10 +6,12 @@
</div>
<div class="panel" v-else>
<Group :group="groups[selectedGroup]" :lights="displayedLights" :scenes="scenesByGroup[selectedGroup]"
:color-converter="colorConverter" @close="closeGroup" @light-toggle="$emit('light-toggle', $event)"
@group-toggle="$emit('group-toggle', $event)" @set-light="$emit('set-light', $event)"
:color-converter="colorConverter" :animations="animationsByGroup[selectedGroup]" @close="closeGroup"
@light-toggle="$emit('light-toggle', $event)" @group-toggle="$emit('group-toggle', $event)"
@set-light="$emit('set-light', $event)"
@set-group="$emit('set-group', {groupId: selectedGroup, value: $event})"
@select-scene="$emit('select-scene', {groupId: selectedGroup, sceneId: $event})" />
@select-scene="$emit('select-scene', {groupId: selectedGroup, sceneId: $event})"
@start-animation="$emit('start-animation', $event)" @stop-animation="$emit('stop-animation', $event)" />
</div>
</div>
</template>
@ -28,7 +30,7 @@ export default {
name: "Light",
components: {Group, Groups},
mixins: [Utils, Panel],
emits: ['group-toggle', 'light-toggle', 'set-light', 'set-group', 'select-scene'],
emits: ['group-toggle', 'light-toggle', 'set-light', 'set-group', 'select-scene', 'start-animation', 'stop-animation'],
props: {
lights: {
@ -90,17 +92,6 @@ export default {
}, {})
},
lightsByGroup() {
if (!this.groups)
return {}
const self = this
return Object.entries(this.groups).reduce((obj, [groupId, group]) => {
obj[groupId] = group.lights.map((lightId) => self.lights[lightId])
return obj
}, {})
},
groupsByLight() {
if (!this.groups)
return {}
@ -134,6 +125,33 @@ export default {
return obj
}, {})
},
animationsByGroup() {
const self = this
const animations = Object.entries(this.animations?.groups || {}).reduce((obj, [groupId, animation]) => {
obj[groupId] = {}
if (animation)
obj[groupId][null] = animation
return obj
}, {})
return {
...animations,
...Object.entries(this.animations?.lights || {}).reduce((obj, [lightId, animation]) => {
const group = Object.values(self.groupsByLight[lightId])?.[0]
if (group) {
if (animation && group.id != null) {
if (!obj[group.id])
obj[group.id] = {}
obj[group.id][lightId] = animation
}
}
return obj
}, {})
}
}
},
methods: {

View file

@ -3,7 +3,8 @@
<LightPlugin plugin-name="light.hue" :config="config" :lights="lights" :groups="groups" :scenes="scenes"
:animations="animations" :initial-group="initialGroup" :loading-groups="loadingGroups"
:color-converter="colorConverter" @group-toggle="toggleGroup"
@light-toggle="toggleLight" @set-light="setLight" @set-group="setGroup" @select-scene="setScene" />
@light-toggle="toggleLight" @set-light="setLight" @set-group="setGroup" @select-scene="setScene"
@start-animation="startAnimation" @stop-animation="stopAnimation" />
</template>
<script>
@ -65,7 +66,6 @@ export default {
},
async getScenes() {
// return await this.request('light.hue.get_scenes')
return Object.entries(await this.request('light.hue.get_scenes'))
.filter((scene) => !scene[1].recycle && scene[1].type.toLowerCase() === 'lightscene')
.reduce((obj, [id, scene]) => {
@ -74,6 +74,10 @@ export default {
}, {})
},
async getAnimations() {
return await this.request('light.hue.get_animations')
},
async toggleGroup(group) {
let groups = Object.values(this.groups)
let args = {
@ -167,7 +171,7 @@ export default {
}
if (method)
return self.lightAction(method, args, group)
return self.groupAction(method, args, group)
}).filter((req) => req != null)
await Promise.all(requests)
@ -188,16 +192,31 @@ export default {
this.loading = true
try {
[this.lights, this.groups, this.scenes] = await Promise.all([
[this.lights, this.groups, this.scenes, this.animations] = await Promise.all([
this.getLights(),
this.getGroups(),
this.getScenes(),
this.getAnimations(),
])
} finally {
if (!background)
this.loading = false
}
},
async startAnimation(event) {
await this.request('light.hue.animate', {
lights: event.lights,
...event.animation,
})
await this.refresh(true)
},
async stopAnimation() {
await this.request('light.hue.stop_animation')
await this.refresh(true)
},
},
mounted() {

View file

@ -1,5 +1,11 @@
//// General
$background-color: white;
$default-bg-2: #f8f8f8 !default;
$default-bg-3: #f4f5f6 !default;
$default-bg-4: #f1f3f2 !default;
$default-bg-5: #edf0ee !default;
$default-bg-6: #e4eae8 !default;
$default-bg-7: #e4e4e4 !default;
//// Notifications
$notification-bg: rgba(185, 255, 193, 0.9) !default;
@ -32,6 +38,9 @@ $default-border: 1px solid $border-color-1 !default;
$default-border-2: 1px solid $border-color-2 !default;
$default-border-3: 1px solid $border-color-3 !default;
//// Shadows
$border-shadow-bottom: 0 3px 2px -1px #c0c0c0;
//// Modals
$modal-header-bg: #e0e0e0 !default;
$modal-header-border: 1px solid #ccc !default;

View file

@ -8,6 +8,13 @@ export default {
bus.emit('notification-create', notification)
},
warn(msg) {
this.notify({
text: msg,
warning: true,
})
},
error(msg) {
this.notify({
text: msg,

View file

@ -0,0 +1,10 @@
<script>
export default {
name: "Screen",
methods: {
isMobile() {
return window.matchMedia("only screen and (max-width: 760px)").matches
},
},
}
</script>

View file

@ -73,6 +73,7 @@ body {
display: flex;
align-items: center;
justify-content: center;
background: $default-bg-6;
}
.description {
@ -87,6 +88,7 @@ form {
border: $default-border-3;
border-radius: 3em;
box-shadow: 2px 2px 3px 3px $border-color-2;
background: $background-color;
.row {
margin: 0.5em 0;

View file

@ -99,10 +99,15 @@ main {
height: 100%;
display: flex;
@media screen and (max-width: $tablet) {
flex-direction: column;
}
.canvas {
display: flex;
flex-grow: 100;
background: $menu-panel-bg;
overflow: auto;
.panel {
width: 100%;

View file

@ -6,6 +6,7 @@ module.exports = {
sass: {
additionalData: `
@import '~bulma';
@import '~w3css/w3.css';
@import "@/style/mixins.scss";
@import "@/style/themes/light.scss";
@import "@/style/layout.scss";

View file

@ -738,33 +738,36 @@ class LightHuePlugin(LightPlugin):
:param duration: Animation duration in seconds (default: None, i.e. continue until stop)
:type duration: float
:param hue_range: If you selected a color color_transition.html, this will specify the hue range of your color color_transition.html.
:param hue_range: If you selected a ``color_transition``, this will specify the hue range of your color ``color_transition``.
Default: [0, 65535]
:type hue_range: list[int]
:param sat_range: If you selected a color color_transition.html, this will specify the saturation range of your color
color_transition.html. Default: [0, 255]
:param sat_range: If you selected a color ``color_transition``, this will specify the saturation range of your color
``color_transition``. Default: [0, 255]
:type sat_range: list[int]
:param bri_range: If you selected a color color_transition.html, this will specify the brightness range of your color
color_transition.html. Default: [254, 255] :type bri_range: list[int]
:param bri_range: If you selected a color ``color_transition``, this will specify the brightness range of your color
``color_transition``. Default: [254, 255] :type bri_range: list[int]
:param lights: Lights to control (names, IDs or light objects). Default: plugin default lights
:param groups: Groups to control (names, IDs or group objects). Default: plugin default groups
:param hue_step: If you selected a color color_transition.html, this will specify by how much the color hue will change
:param hue_step: If you selected a color ``color_transition``, this will specify by how much the color hue will change
between iterations. Default: 1000 :type hue_step: int
:param sat_step: If you selected a color color_transition.html, this will specify by how much the saturation will change
:param sat_step: If you selected a color ``color_transition``, this will specify by how much the saturation will change
between iterations. Default: 2 :type sat_step: int
:param bri_step: If you selected a color color_transition.html, this will specify by how much the brightness will change
:param bri_step: If you selected a color ``color_transition``, this will specify by how much the brightness will change
between iterations. Default: 1 :type bri_step: int
:param transition_seconds: Time between two transitions or blinks in seconds. Default: 1.0
:type transition_seconds: float
"""
self.stop_animation()
self._animation_stop.clear()
if bri_range is None:
bri_range = [self.MAX_BRI - 1, self.MAX_BRI]
if sat_range is None:
@ -807,6 +810,7 @@ class LightHuePlugin(LightPlugin):
'hue': random.randint(hue_range[0], hue_range[1]),
'sat': random.randint(sat_range[0], sat_range[1]),
'bri': random.randint(bri_range[0], bri_range[1]),
'transitiontime': transition_seconds,
} for light in lights}
elif animation == self.Animation.BLINK:
return {light: {
@ -819,9 +823,6 @@ class LightHuePlugin(LightPlugin):
if animation == self.Animation.COLOR_TRANSITION:
for (light, attrs) in lights.items():
for (attr, value) in attrs.items():
attr_range = [0, 0]
attr_step = 0
if attr == 'hue':
attr_range = hue_range
attr_step = hue_step
@ -831,6 +832,8 @@ class LightHuePlugin(LightPlugin):
elif attr == 'sat':
attr_range = sat_range
attr_step = sat_step
else:
continue
lights[light][attr] = ((value - attr_range[0] + attr_step) %
(attr_range[1] - attr_range[0] + 1)) + \
@ -849,25 +852,18 @@ class LightHuePlugin(LightPlugin):
def _animate_thread(lights):
set_thread_name('HueAnimate')
self.logger.info('Starting {} animation'.format(
animation, (lights or groups)))
self.logger.info('Starting {} animation'.format(animation, (lights or groups)))
lights = _initialize_light_attrs(lights)
animation_start_time = time.time()
stop_animation = False
while True:
if stop_animation or \
(duration and time.time() - animation_start_time > duration):
break
while not stop_animation and not (duration and time.time() - animation_start_time > duration):
try:
if animation == self.Animation.COLOR_TRANSITION:
for (light, attrs) in lights.items():
self.logger.debug('Setting {} to {}'.format(light, attrs))
self.bridge.set_light(light, attrs)
stop_animation = _should_stop()
if stop_animation: break
elif animation == self.Animation.BLINK:
conf = lights[list(lights.keys())[0]]
self.logger.debug('Setting lights to {}'.format(conf))
@ -877,8 +873,10 @@ class LightHuePlugin(LightPlugin):
else:
self.bridge.set_light(lights.keys(), conf)
stop_animation = _should_stop()
if stop_animation: break
if transition_seconds:
time.sleep(transition_seconds)
stop_animation = _should_stop()
except Exception as e:
self.logger.warning(e)
time.sleep(2)
@ -888,8 +886,6 @@ class LightHuePlugin(LightPlugin):
self.logger.info('Stopping animation')
self.animation_thread = None
self.stop_animation()
self._animation_stop.clear()
self.animation_thread = Thread(target=_animate_thread,
name='HueAnimate',
args=(lights,))