music.mpd refactor WIP

This commit is contained in:
Fabio Manganiello 2020-12-31 01:36:02 +01:00
parent 3eb7f01d38
commit e127f2597c
60 changed files with 1098 additions and 167 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-24ff873d.64d9bc0b.css" rel="prefetch"><link href="/static/css/chunk-35b45d59.0c4a18da.css" rel="prefetch"><link href="/static/css/chunk-3d60f62e.2026dd4f.css" rel="prefetch"><link href="/static/css/chunk-45939517.e4a1ddf3.css" rel="prefetch"><link href="/static/css/chunk-4bbbb9a3.3108d379.css" rel="prefetch"><link href="/static/css/chunk-53360c78.c486a396.css" rel="prefetch"><link href="/static/css/chunk-545459d0.009b6a70.css" rel="prefetch"><link href="/static/css/chunk-62a3d08e.6cb54f10.css" rel="prefetch"><link href="/static/css/chunk-ba6439f0.48dc2d11.css" rel="prefetch"><link href="/static/css/chunk-d8561e02.b52f89a0.css" rel="prefetch"><link href="/static/css/chunk-e8078048.c6785c78.css" rel="prefetch"><link href="/static/js/chunk-24ff873d.f955ad3b.js" rel="prefetch"><link href="/static/js/chunk-2d2091df.b017f6d4.js" rel="prefetch"><link href="/static/js/chunk-2d21da1a.867fde19.js" rel="prefetch"><link href="/static/js/chunk-35b45d59.d541d43f.js" rel="prefetch"><link href="/static/js/chunk-3d60f62e.8cc48f2d.js" rel="prefetch"><link href="/static/js/chunk-45939517.38162e50.js" rel="prefetch"><link href="/static/js/chunk-4bbbb9a3.6f0e4975.js" rel="prefetch"><link href="/static/js/chunk-53360c78.54e2e626.js" rel="prefetch"><link href="/static/js/chunk-545459d0.aa1e42a3.js" rel="prefetch"><link href="/static/js/chunk-62a3d08e.8fc4fd3a.js" rel="prefetch"><link href="/static/js/chunk-ba6439f0.a6ca0191.js" rel="prefetch"><link href="/static/js/chunk-d8561e02.78e44394.js" rel="prefetch"><link href="/static/js/chunk-e8078048.e668de5f.js" rel="prefetch"><link href="/static/css/app.e87398b0.css" rel="preload" as="style"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="preload" as="style"><link href="/static/js/app.9c37c838.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.63de75fe.js" rel="preload" as="script"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="stylesheet"><link href="/static/css/app.e87398b0.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.63de75fe.js"></script><script src="/static/js/app.9c37c838.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-24ff873d.64d9bc0b.css" rel="prefetch"><link href="/static/css/chunk-3b44ec4e.0c4a18da.css" rel="prefetch"><link href="/static/css/chunk-45939517.e4a1ddf3.css" rel="prefetch"><link href="/static/css/chunk-4bbbb9a3.3108d379.css" rel="prefetch"><link href="/static/css/chunk-4c0b0f48.009b6a70.css" rel="prefetch"><link href="/static/css/chunk-4eeb8349.2026dd4f.css" rel="prefetch"><link href="/static/css/chunk-52804492.a64fd302.css" rel="prefetch"><link href="/static/css/chunk-53360c78.c486a396.css" rel="prefetch"><link href="/static/css/chunk-62a3d08e.6cb54f10.css" rel="prefetch"><link href="/static/css/chunk-d8561e02.b52f89a0.css" rel="prefetch"><link href="/static/css/chunk-e8078048.c6785c78.css" rel="prefetch"><link href="/static/js/chunk-24ff873d.691c883d.js" rel="prefetch"><link href="/static/js/chunk-2d2091df.1e51ae4c.js" rel="prefetch"><link href="/static/js/chunk-2d21da1a.6bb60047.js" rel="prefetch"><link href="/static/js/chunk-3b44ec4e.904c7e10.js" rel="prefetch"><link href="/static/js/chunk-45939517.c0034c6b.js" rel="prefetch"><link href="/static/js/chunk-4bbbb9a3.251fff37.js" rel="prefetch"><link href="/static/js/chunk-4c0b0f48.366980a2.js" rel="prefetch"><link href="/static/js/chunk-4eeb8349.5c94d58c.js" rel="prefetch"><link href="/static/js/chunk-52804492.1cbed362.js" rel="prefetch"><link href="/static/js/chunk-53360c78.51ee7c96.js" rel="prefetch"><link href="/static/js/chunk-62a3d08e.17d3c86d.js" rel="prefetch"><link href="/static/js/chunk-d8561e02.1e366cb3.js" rel="prefetch"><link href="/static/js/chunk-e8078048.ce29b8d4.js" rel="prefetch"><link href="/static/css/app.4868c461.css" rel="preload" as="style"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="preload" as="style"><link href="/static/js/app.ce952734.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.30e3a6cb.js" rel="preload" as="script"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="stylesheet"><link href="/static/css/app.4868c461.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.30e3a6cb.js"></script><script src="/static/js/app.ce952734.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

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["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")}}]); (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["K"])("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 //# sourceMappingURL=chunk-24ff873d.691c883d.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

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-45939517"],{"1cb0":function(e,t,s){"use strict";s("5eaa")},"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-d6e48dfa");Object(a["u"])("data-v-d6e48dfa");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"},h={class:"col-3"},d=Object(a["h"])("div",{class:"col-6"}," ",-1),l={class:"col-3"};Object(a["s"])();var m=n((function(e,t,s,n,m,b){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,[b._showDate||b._showTime?(Object(a["r"])(),Object(a["e"])(f,{key:0,"show-date":b._showDate,"show-time":b._showTime,"show-seconds":b._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":b._showSummary,animate:b._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,[b._showSensors&&Object.keys(e.sensors).length?(Object(a["r"])(),Object(a["e"])("div",u,[Object(a["h"])("div",h,[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)]),d,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)])])})),b=(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:[b["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,null,"platypush.message.event.sensor.SensorDataChangeEvent")}};s("1cb0");q.render=m,q.__scopeId="data-v-d6e48dfa";t["default"]=q},"5eaa":function(e,t,s){},e458:function(e,t,s){}}]); (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-45939517"],{"1cb0":function(e,t,s){"use strict";s("5eaa")},"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["K"])("data-v-d6e48dfa");Object(a["u"])("data-v-d6e48dfa");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"},h={class:"col-3"},d=Object(a["h"])("div",{class:"col-6"}," ",-1),l={class:"col-3"};Object(a["s"])();var m=n((function(e,t,s,n,m,b){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,[b._showDate||b._showTime?(Object(a["r"])(),Object(a["e"])(f,{key:0,"show-date":b._showDate,"show-time":b._showTime,"show-seconds":b._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":b._showSummary,animate:b._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,[b._showSensors&&Object.keys(e.sensors).length?(Object(a["r"])(),Object(a["e"])("div",u,[Object(a["h"])("div",h,[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)]),d,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)])])})),b=(s("a9e3"),s("3e54")),f=s("365a"),w=s("5b43"),j=(s("b0c0"),Object(a["K"])("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:[b["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,null,"platypush.message.event.sensor.SensorDataChangeEvent")}};s("1cb0");q.render=m,q.__scopeId="data-v-d6e48dfa";t["default"]=q},"5eaa":function(e,t,s){},e458:function(e,t,s){}}]);
//# sourceMappingURL=chunk-45939517.38162e50.js.map //# sourceMappingURL=chunk-45939517.c0034c6b.js.map

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["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")}}]); (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-4bbbb9a3"],{"365a":function(e,t,n){"use strict";n.r(t);var o=n("7a23"),s=Object(o["K"])("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 //# sourceMappingURL=chunk-4bbbb9a3.251fff37.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.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":""} {"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.251fff37.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

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-4c0b0f48"],{"4de4":function(e,n,t){"use strict";var u=t("23e7"),o=t("b727").filter,r=t("1dde"),i=t("ae40"),a=r("filter"),c=i("filter");u({target:"Array",proto:!0,forced:!a||!c},{filter:function(e){return o(this,e,arguments.length>1?arguments[1]:void 0)}})},8285:function(e,n,t){"use strict";var u=t("7a23"),o=Object(u["K"])("data-v-12a0983b"),r=o((function(e,n,t,o,r,i){return Object(u["r"])(),Object(u["e"])("label",null,[Object(u["h"])("input",{class:"slider",type:"range",min:t.range[0],max:t.range[1],value:t.value,disabled:t.disabled,onChange:n[1]||(n[1]=function(n){return e.$emit("input",n)}),onMouseup:n[2]||(n[2]=function(n){return e.$emit("mouseup",n)}),onInput:n[3]||(n[3]=function(n){return e.$emit("input",n)}),onMousedown:n[4]||(n[4]=function(n){return e.$emit("mousedown",n)}),onTouch:n[5]||(n[5]=function(n){return e.$emit("input",n)}),onTouchstart:n[6]||(n[6]=function(n){return e.$emit("mousedown",n)}),onTouchend:n[7]||(n[7]=function(n){return e.$emit("mouseup",n)})},null,40,["min","max","value","disabled"])])})),i=(t("a9e3"),{name:"Slider",emits:["input","mouseup","mousedown"],props:{value:{type:Number},disabled:{type:Boolean,default:!1},range:{type:Array,default:function(){return[0,100]}}}});t("ee52");i.render=r,i.__scopeId="data-v-12a0983b";n["a"]=i},e1773:function(e,n,t){},ee52:function(e,n,t){"use strict";t("e1773")}}]);
//# sourceMappingURL=chunk-4c0b0f48.366980a2.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

File diff suppressed because one or more lines are too long

View file

@ -1,2 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-545459d0"],{8285:function(e,n,u){"use strict";var t=u("7a23"),o=Object(t["J"])("data-v-12a0983b"),i=o((function(e,n,u,o,i,a){return Object(t["r"])(),Object(t["e"])("label",null,[Object(t["h"])("input",{class:"slider",type:"range",min:u.range[0],max:u.range[1],value:u.value,disabled:u.disabled,onChange:n[1]||(n[1]=function(n){return e.$emit("input",n)}),onMouseup:n[2]||(n[2]=function(n){return e.$emit("mouseup",n)}),onInput:n[3]||(n[3]=function(n){return e.$emit("input",n)}),onMousedown:n[4]||(n[4]=function(n){return e.$emit("mousedown",n)}),onTouch:n[5]||(n[5]=function(n){return e.$emit("input",n)}),onTouchstart:n[6]||(n[6]=function(n){return e.$emit("mousedown",n)}),onTouchend:n[7]||(n[7]=function(n){return e.$emit("mouseup",n)})},null,40,["min","max","value","disabled"])])})),a=(u("a9e3"),{name:"Slider",emits:["input","mouseup","mousedown"],props:{value:{type:Number},disabled:{type:Boolean,default:!1},range:{type:Array,default:function(){return[0,100]}}}});u("ee52");a.render=i,a.__scopeId="data-v-12a0983b";n["a"]=a},e1773:function(e,n,u){},ee52:function(e,n,u){"use strict";u("e1773")}}]);
//# sourceMappingURL=chunk-545459d0.aa1e42a3.js.map

View file

@ -1 +0,0 @@
{"version":3,"sources":["webpack:///./src/components/elements/Slider.vue","webpack:///./src/components/elements/Slider.vue?7dba","webpack:///./src/components/elements/Slider.vue?5806"],"names":["class","type","min","range","max","value","disabled","$emit","$event","name","emits","props","Number","Boolean","default","Array","render","__scopeId"],"mappings":"uNACE,eAKQ,cAJN,eAGqF,SAH9EA,MAAM,SAASC,KAAK,QAASC,IAAK,EAAAC,MAAK,GAAMC,IAAK,EAAAD,MAAK,GAAME,MAAO,EAAAA,MAAQC,SAAU,EAAAA,SACrF,SAAM,+BAAE,EAAAC,MAAK,QAAUC,KAAU,UAAO,+BAAE,EAAAD,MAAK,UAAYC,KAAU,QAAK,+BAAE,EAAAD,MAAK,QAAUC,KAC3F,YAAS,+BAAE,EAAAD,MAAK,YAAcC,KAAU,QAAK,+BAAE,EAAAD,MAAK,QAAUC,KAC9D,aAAU,+BAAE,EAAAD,MAAK,YAAcC,KAAU,WAAQ,+BAAE,EAAAD,MAAK,UAAYC,M,+CAKjE,G,UAAA,CACbC,KAAM,SACNC,MAAO,CAAC,QAAS,UAAW,aAC5BC,MAAO,CACLN,MAAO,CACLJ,KAAMW,QAGRN,SAAU,CACRL,KAAMY,QACNC,SAAS,GAGXX,MAAO,CACLF,KAAMc,MACND,QAAS,iBAAM,CAAC,EAAG,U,UCpBzB,EAAOE,OAAS,EAChB,EAAOC,UAAY,kBAEJ,U,0DCRf","file":"static/js/chunk-545459d0.aa1e42a3.js","sourcesContent":["<template>\n <label>\n <input class=\"slider\" type=\"range\" :min=\"range[0]\" :max=\"range[1]\" :value=\"value\" :disabled=\"disabled\"\n @change=\"$emit('input', $event)\" @mouseup=\"$emit('mouseup', $event)\" @input=\"$emit('input', $event)\"\n @mousedown=\"$emit('mousedown', $event)\" @touch=\"$emit('input', $event)\"\n @touchstart=\"$emit('mousedown', $event)\" @touchend=\"$emit('mouseup', $event)\">\n </label>\n</template>\n\n<script>\nexport default {\n name: \"Slider\",\n emits: ['input', 'mouseup', 'mousedown'],\n props: {\n value: {\n type: Number,\n },\n\n disabled: {\n type: Boolean,\n default: false,\n },\n\n range: {\n type: Array,\n default: () => [0, 100],\n },\n },\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.slider {\n @include appearance(none);\n @include transition(opacity .2s);\n width: 100%;\n height: 1em;\n border-radius: 0.33em;\n background: $slider-bg;\n outline: none;\n\n @mixin slider-thumb {\n @include appearance(none);\n width: 1.5em;\n height: 1.5em;\n border-radius: 50%;\n border: 0;\n background: $slider-thumb-bg;\n cursor: pointer;\n }\n\n &::-webkit-slider-thumb { @include slider-thumb; }\n &::-moz-range-thumb { @include slider-thumb; }\n &::-moz-range-track { @include appearance(none); }\n\n &::-webkit-progress-value,\n &::-moz-range-progress {\n background: $slider-progress-bg;\n height: 1em;\n }\n\n &[disabled] {\n &::-webkit-progress-value,\n &::-moz-range-progress {\n background: none;\n }\n\n &::-webkit-slider-thumb,\n &::-moz-range-thumb {\n display: none;\n width: 0;\n }\n }\n}\n</style>","import { render } from \"./Slider.vue?vue&type=template&id=12a0983b&scoped=true&bindings={\\\"value\\\":\\\"props\\\",\\\"disabled\\\":\\\"props\\\",\\\"range\\\":\\\"props\\\"}\"\nimport script from \"./Slider.vue?vue&type=script&lang=js\"\nexport * from \"./Slider.vue?vue&type=script&lang=js\"\n\nimport \"./Slider.vue?vue&type=style&index=0&id=12a0983b&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-12a0983b\"\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!./Slider.vue?vue&type=style&index=0&id=12a0983b&lang=scss&scoped=true\""],"sourceRoot":""}

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["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){}}]); (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["K"])("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 //# sourceMappingURL=chunk-62a3d08e.17d3c86d.js.map

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-d8561e02"],{"49c1":function(e,t,n){},"9e1b":function(e,t,n){"use strict";n("49c1")},dabe:function(e,t,n){"use strict";n.r(t);var i=n("7a23"),c=Object(i["J"])("data-v-3565b88b");Object(i["u"])("data-v-3565b88b");var o={class:"plugin"};Object(i["s"])();var a=c((function(e,t,n,c,a,r){var s=Object(i["z"])("Loading");return Object(i["r"])(),Object(i["e"])("div",o,[a.loading?(Object(i["r"])(),Object(i["e"])(s,{key:0})):a.component?(Object(i["r"])(),Object(i["e"])(Object(i["A"])(a.component),{key:1,config:a.config},null,8,["config"])):Object(i["f"])("",!0)])})),r=(n("a15b"),n("d81d"),n("fb6a"),n("d3b7"),n("ac1f"),n("1276"),n("96cf"),n("1da1")),s=n("3e54"),u=n("3a5e"),p={name:"Plugin",components:{Loading:u["a"]},mixins:[s["a"]],props:{pluginName:{type:String,required:!0}},data:function(){return{loading:!1,component:null,config:{}}},computed:{componentName:function(){return this.pluginName.split(".").map((function(e){return e[0].toUpperCase()+e.slice(1)})).join("")}},methods:{refresh:function(){var e=Object(r["a"])(regeneratorRuntime.mark((function e(){var t,c=this;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return this.loading=!0,e.prev=1,this.component=Object(i["i"])((function(){return n("0f0c")("./".concat(c.componentName,"/Index"))})),this.$options.components[this.componentName]=this.component,e.next=6,this.request("config.get_plugins");case 6:if(e.t2=t=e.sent,e.t1=null===e.t2,e.t1){e.next=10;break}e.t1=void 0===t;case 10:if(!e.t1){e.next=14;break}e.t3=void 0,e.next=15;break;case 14:e.t3=t[this.pluginName];case 15:if(e.t0=e.t3,e.t0){e.next=18;break}e.t0={};case 18:this.config=e.t0;case 19:return e.prev=19,this.loading=!1,e.finish(19);case 22:case"end":return e.stop()}}),e,this,[[1,,19,22]])})));function t(){return e.apply(this,arguments)}return t}()},mounted:function(){this.refresh()}};n("9e1b");p.render=a,p.__scopeId="data-v-3565b88b";t["default"]=p}}]); (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-d8561e02"],{"49c1":function(e,t,n){},"9e1b":function(e,t,n){"use strict";n("49c1")},dabe:function(e,t,n){"use strict";n.r(t);var i=n("7a23"),c=Object(i["K"])("data-v-3565b88b");Object(i["u"])("data-v-3565b88b");var o={class:"plugin"};Object(i["s"])();var a=c((function(e,t,n,c,a,r){var s=Object(i["z"])("Loading");return Object(i["r"])(),Object(i["e"])("div",o,[a.loading?(Object(i["r"])(),Object(i["e"])(s,{key:0})):a.component?(Object(i["r"])(),Object(i["e"])(Object(i["A"])(a.component),{key:1,config:a.config},null,8,["config"])):Object(i["f"])("",!0)])})),r=(n("a15b"),n("d81d"),n("fb6a"),n("d3b7"),n("ac1f"),n("1276"),n("96cf"),n("1da1")),s=n("3e54"),u=n("3a5e"),p={name:"Plugin",components:{Loading:u["a"]},mixins:[s["a"]],props:{pluginName:{type:String,required:!0}},data:function(){return{loading:!1,component:null,config:{}}},computed:{componentName:function(){return this.pluginName.split(".").map((function(e){return e[0].toUpperCase()+e.slice(1)})).join("")}},methods:{refresh:function(){var e=Object(r["a"])(regeneratorRuntime.mark((function e(){var t,c=this;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return this.loading=!0,e.prev=1,this.component=Object(i["i"])((function(){return n("0f0c")("./".concat(c.componentName,"/Index"))})),this.$options.components[this.componentName]=this.component,e.next=6,this.request("config.get_plugins");case 6:if(e.t2=t=e.sent,e.t1=null===e.t2,e.t1){e.next=10;break}e.t1=void 0===t;case 10:if(!e.t1){e.next=14;break}e.t3=void 0,e.next=15;break;case 14:e.t3=t[this.pluginName];case 15:if(e.t0=e.t3,e.t0){e.next=18;break}e.t0={};case 18:this.config=e.t0;case 19:return e.prev=19,this.loading=!1,e.finish(19);case 22:case"end":return e.stop()}}),e,this,[[1,,19,22]])})));function t(){return e.apply(this,arguments)}return t}()},mounted:function(){this.refresh()}};n("9e1b");p.render=a,p.__scopeId="data-v-3565b88b";t["default"]=p}}]);
//# sourceMappingURL=chunk-d8561e02.78e44394.js.map //# sourceMappingURL=chunk-d8561e02.1e366cb3.js.map

View file

@ -1 +1 @@
{"version":3,"sources":["webpack:///./src/components/widgets/Plugin/Index.vue?bbf0","webpack:///./src/components/widgets/Plugin/Index.vue","webpack:///./src/components/widgets/Plugin/Index.vue?fc8a"],"names":["class","loading","component","config","name","components","Loading","mixins","Utils","props","pluginName","type","String","required","data","computed","componentName","this","split","map","t","toUpperCase","slice","join","methods","refresh","$options","request","mounted","render","__scopeId"],"mappings":"2IAAA,W,sICCOA,MAAM,U,wGAAX,eAGM,MAHN,EAGM,CAFW,EAAAC,S,iBAAf,eAA0B,YAC6B,EAAAC,W,iBAAvD,eAAoE,eAApD,EAAAA,WAAS,C,MAAGC,OAAQ,EAAAA,Q,2JASzB,GACbC,KAAM,SACNC,WAAY,CAACC,UAAA,MACbC,OAAQ,CAACC,EAAA,MACTC,MAAO,CAELC,WAAY,CACVC,KAAMC,OACNC,UAAU,IAIdC,KAZa,WAaX,MAAO,CACLb,SAAS,EACTC,UAAW,KACXC,OAAQ,KAIZY,SAAU,CACRC,cADQ,WAEN,OAAOC,KAAKP,WAAWQ,MAAM,KAAKC,KAAI,SAACC,GAAD,OAAOA,EAAE,GAAGC,cAAgBD,EAAEE,MAAM,MAAIC,KAAK,MAIvFC,QAAS,CACPC,QAAS,WAAF,8CAAE,kHACPR,KAAKhB,SAAU,EADR,SAILgB,KAAKf,UAAY,gBAAqB,kBAAM,UAAO,YAAuB,EAAKc,cAAnC,cAC5CC,KAAKS,SAASrB,WAAWY,KAAKD,eAAiBC,KAAKf,UAL/C,SAMgBe,KAAKU,QAAQ,sBAN7B,0JAMS,EAA6CV,KAAKP,YAN3D,gDAM0E,GAN1E,QAMLO,KAAKd,OANA,8BAQLc,KAAKhB,SAAU,EARV,2EAAF,qDAAE,IAaX2B,QAAS,WACPX,KAAKQ,Y,UChDT,EAAOI,OAAS,EAChB,EAAOC,UAAY,kBAEJ","file":"static/js/chunk-d8561e02.78e44394.js","sourcesContent":["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=3565b88b&lang=scss&scoped=true\"","<template>\n <div class=\"plugin\">\n <Loading v-if=\"loading\" />\n <component :is=\"component\" :config=\"config\" v-else-if=\"component\" />\n </div>\n</template>\n\n<script>\nimport Utils from \"@/Utils\";\nimport Loading from \"@/components/Loading\";\nimport {defineAsyncComponent} from \"vue\";\n\nexport default {\n name: \"Plugin\",\n components: {Loading},\n mixins: [Utils],\n props: {\n // Name of the plugin view to be loaded\n pluginName: {\n type: String,\n required: true,\n },\n },\n\n data() {\n return {\n loading: false,\n component: null,\n config: {},\n }\n },\n\n computed: {\n componentName() {\n return this.pluginName.split('.').map((t) => t[0].toUpperCase() + t.slice(1)).join('')\n },\n },\n\n methods: {\n refresh: async function() {\n this.loading = true\n\n try {\n this.component = defineAsyncComponent(() => import(`@/components/panels/${this.componentName}/Index`))\n this.$options.components[this.componentName] = this.component\n this.config = (await this.request('config.get_plugins'))?.[this.pluginName] || {}\n } finally {\n this.loading = false\n }\n },\n },\n\n mounted: function() {\n this.refresh()\n },\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.plugin {\n margin: -1em 0 0 -1em !important;\n padding: 0;\n width: calc(100% + 2em);\n height: calc(100% + 2em);\n}\n</style>\n","import { render } from \"./Index.vue?vue&type=template&id=3565b88b&scoped=true&bindings={\\\"pluginName\\\":\\\"props\\\",\\\"loading\\\":\\\"data\\\",\\\"component\\\":\\\"data\\\",\\\"config\\\":\\\"data\\\",\\\"componentName\\\":\\\"options\\\",\\\"refresh\\\":\\\"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=3565b88b&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-3565b88b\"\n\nexport default script"],"sourceRoot":""} {"version":3,"sources":["webpack:///./src/components/widgets/Plugin/Index.vue?bbf0","webpack:///./src/components/widgets/Plugin/Index.vue","webpack:///./src/components/widgets/Plugin/Index.vue?fc8a"],"names":["class","loading","component","config","name","components","Loading","mixins","Utils","props","pluginName","type","String","required","data","computed","componentName","this","split","map","t","toUpperCase","slice","join","methods","refresh","$options","request","mounted","render","__scopeId"],"mappings":"2IAAA,W,sICCOA,MAAM,U,wGAAX,eAGM,MAHN,EAGM,CAFW,EAAAC,S,iBAAf,eAA0B,YAC6B,EAAAC,W,iBAAvD,eAAoE,eAApD,EAAAA,WAAS,C,MAAGC,OAAQ,EAAAA,Q,2JASzB,GACbC,KAAM,SACNC,WAAY,CAACC,UAAA,MACbC,OAAQ,CAACC,EAAA,MACTC,MAAO,CAELC,WAAY,CACVC,KAAMC,OACNC,UAAU,IAIdC,KAZa,WAaX,MAAO,CACLb,SAAS,EACTC,UAAW,KACXC,OAAQ,KAIZY,SAAU,CACRC,cADQ,WAEN,OAAOC,KAAKP,WAAWQ,MAAM,KAAKC,KAAI,SAACC,GAAD,OAAOA,EAAE,GAAGC,cAAgBD,EAAEE,MAAM,MAAIC,KAAK,MAIvFC,QAAS,CACPC,QAAS,WAAF,8CAAE,kHACPR,KAAKhB,SAAU,EADR,SAILgB,KAAKf,UAAY,gBAAqB,kBAAM,UAAO,YAAuB,EAAKc,cAAnC,cAC5CC,KAAKS,SAASrB,WAAWY,KAAKD,eAAiBC,KAAKf,UAL/C,SAMgBe,KAAKU,QAAQ,sBAN7B,0JAMS,EAA6CV,KAAKP,YAN3D,gDAM0E,GAN1E,QAMLO,KAAKd,OANA,8BAQLc,KAAKhB,SAAU,EARV,2EAAF,qDAAE,IAaX2B,QAAS,WACPX,KAAKQ,Y,UChDT,EAAOI,OAAS,EAChB,EAAOC,UAAY,kBAEJ","file":"static/js/chunk-d8561e02.1e366cb3.js","sourcesContent":["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=3565b88b&lang=scss&scoped=true\"","<template>\n <div class=\"plugin\">\n <Loading v-if=\"loading\" />\n <component :is=\"component\" :config=\"config\" v-else-if=\"component\" />\n </div>\n</template>\n\n<script>\nimport Utils from \"@/Utils\";\nimport Loading from \"@/components/Loading\";\nimport {defineAsyncComponent} from \"vue\";\n\nexport default {\n name: \"Plugin\",\n components: {Loading},\n mixins: [Utils],\n props: {\n // Name of the plugin view to be loaded\n pluginName: {\n type: String,\n required: true,\n },\n },\n\n data() {\n return {\n loading: false,\n component: null,\n config: {},\n }\n },\n\n computed: {\n componentName() {\n return this.pluginName.split('.').map((t) => t[0].toUpperCase() + t.slice(1)).join('')\n },\n },\n\n methods: {\n refresh: async function() {\n this.loading = true\n\n try {\n this.component = defineAsyncComponent(() => import(`@/components/panels/${this.componentName}/Index`))\n this.$options.components[this.componentName] = this.component\n this.config = (await this.request('config.get_plugins'))?.[this.pluginName] || {}\n } finally {\n this.loading = false\n }\n },\n },\n\n mounted: function() {\n this.refresh()\n },\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.plugin {\n margin: -1em 0 0 -1em !important;\n padding: 0;\n width: calc(100% + 2em);\n height: calc(100% + 2em);\n}\n</style>\n","import { render } from \"./Index.vue?vue&type=template&id=3565b88b&scoped=true&bindings={\\\"pluginName\\\":\\\"props\\\",\\\"loading\\\":\\\"data\\\",\\\"component\\\":\\\"data\\\",\\\"config\\\":\\\"data\\\",\\\"componentName\\\":\\\"options\\\",\\\"refresh\\\":\\\"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=3565b88b&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-3565b88b\"\n\nexport default script"],"sourceRoot":""}

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["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}}]); (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["K"])("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 //# sourceMappingURL=chunk-e8078048.ce29b8d4.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

@ -53,7 +53,7 @@ export default {
async initConfig() { async initConfig() {
this.config = await this.request('config.get') this.config = await this.request('config.get')
this.userAuthenticated = true this.userAuthenticated = true
} },
}, },
created() { created() {

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="modal-container fade-in" :id="id" :class="{hidden: !isVisible}" :style="{'--z-index': zIndex}" @click="close"> <div class="modal-container fade-in" :id="id" :class="{hidden: !isVisible}" :style="{'--z-index': zIndex}" @click="close">
<div class="modal" :style="{'--width': width, '--height': height}"> <div class="modal">
<div class="content" @click="$event.stopPropagation()"> <div class="content" :style="{'--width': width, '--height': height}" @click="$event.stopPropagation()">
<div class="header" v-text="title" v-if="title"></div> <div class="header" v-text="title" v-if="title"></div>
<div class="body"> <div class="body">
<slot @modal-close="close" /> <slot @modal-close="close" />
@ -14,6 +14,7 @@
<script> <script>
export default { export default {
name: "Modal", name: "Modal",
emits: ['close', 'open'],
props: { props: {
// Modal ID // Modal ID
id: { id: {
@ -86,6 +87,19 @@ export default {
}, },
}, },
mounted() {
const self = this
const visibleHndl = (visible) => {
if (!visible)
self.$emit('close')
else
self.$emit('open')
}
this.$watch(() => this.visible, visibleHndl)
this.$watch(() => this.isVisible, visibleHndl)
},
updated() { updated() {
this.prevVisible = this.isVisible this.prevVisible = this.isVisible
if (this.isVisible) { if (this.isVisible) {
@ -138,13 +152,13 @@ export default {
background: rgba(10,10,10,0.9); background: rgba(10,10,10,0.9);
.modal { .modal {
display: flex;
.content {
--width: auto; --width: auto;
--height: auto; --height: auto;
width: var(--width); width: var(--width);
height: var(--height); height: var(--height);
display: flex;
.content {
border-radius: 0.5em; border-radius: 0.5em;
background: $modal-body-bg; background: $modal-body-bg;
} }

View file

@ -50,7 +50,6 @@ export default {
onItemClick(name) { onItemClick(name) {
this.$emit('select', name) this.$emit('select', name)
if (this.isMobile())
this.collapsed = true this.collapsed = true
}, },
}, },

View file

@ -75,14 +75,11 @@ export default {
element.style.left = 0 element.style.left = 0
element.style.top = parseFloat(getComputedStyle(this.$refs.button).height) + 'px' element.style.top = parseFloat(getComputedStyle(this.$refs.button).height) + 'px'
const maxOffset = 45 if (element.getBoundingClientRect().left > window.innerWidth/2)
const maxLeft = window.innerWidth - maxOffset element.style.left = (-element.clientWidth + parseFloat(getComputedStyle(this.$refs.button).width)) + 'px'
const left = this.$refs.container.offsetLeft + element.offsetLeft
const width = element.clientWidth
if (left + width >= maxLeft) { if (element.getBoundingClientRect().top > window.innerHeight/2)
element.style.left = -(parseFloat(getComputedStyle(this.$refs.button).width) + maxOffset) + 'px' element.style.top = (-element.clientHeight + parseFloat(getComputedStyle(this.$refs.button).height)) + 'px'
}
}, 10) }, 10)
}, },

View file

@ -0,0 +1,20 @@
<template>
<div class="form-footer">
<slot />
</div>
</template>
<script>
export default {
name: "FormFooter"
}
</script>
<style lang="scss" scoped>
.form-footer {
height: 5em;
padding: 1em;
text-align: right;
border-top: $default-border-2;
}
</style>

View file

@ -12,24 +12,114 @@
<div class="view-container"> <div class="view-container">
<Playlist :tracks="tracks" :status="status" :loading="loading" v-if="selectedView === 'playing'" <Playlist :tracks="tracks" :status="status" :loading="loading" v-if="selectedView === 'playing'"
@play="$emit('play', $event)" @clear="$emit('clear')" /> @play="$emit('play', $event)" @clear="$emit('clear')" @swap="$emit('swap-tracks', $event)"
@add="$emit('add-to-tracklist', $event)" @remove="$emit('remove-from-tracklist', $event)"
@move="$emit('tracklist-move', $event)" @save="$emit('tracklist-save', $event)"
@track-info="$emit('track-info', $event)" @add-to-playlist="openAddToPlaylist" />
<Playlists :playlists="playlists" :loading="loading" v-else-if="selectedView === 'playlists'"
:edited-playlist="editedPlaylist" :tracks="editedPlaylistTracks"
@play="$emit('play-playlist', $event)" @load="$emit('load-playlist', $event)"
@remove="$emit('remove-playlist', $event)" @playlist-edit="$emit('playlist-edit', $event)"
@load-track="$emit('add-to-tracklist-from-edited-playlist', $event)"
@remove-track="$emit('remove-from-playlist', $event)" @track-info="$emit('track-info', $event)"
@playlist-add="$emit('playlist-add', $event)" @add-to-playlist="openAddToPlaylist"
@track-move="$emit('playlist-track-move', $event)"/>
</div> </div>
</main> </main>
</MediaView> </MediaView>
<div class="track-info-container">
<Modal title="Track info" ref="trackInfo">
<div class="track-info-content" v-if="trackInfo">
<div class="row file" v-if="trackInfo.file">
<div class="col-3 attr">File</div>
<div class="col-9 value" v-text="trackInfo.file" />
</div>
<div class="row artist" v-if="trackInfo.artist">
<div class="col-3 attr">Artist</div>
<div class="col-9 value">
<a :href="$route.fullPath" v-text="trackInfo.artist"
@click.stop="$emit('search', {artist: trackInfo.artist})" />
</div>
</div>
<div class="row track-title" v-if="trackInfo.title">
<div class="col-3 attr">Title</div>
<div class="col-9 value" v-text="trackInfo.title" />
</div>
<div class="row album" v-if="trackInfo.album">
<div class="col-3 attr">Album</div>
<div class="col-9 value">
<a :href="$route.fullPath" v-text="trackInfo.album"
@click.stop="$emit('search', {album: trackInfo.album})" />
</div>
</div>
<div class="row date" v-if="trackInfo.date">
<div class="col-3 attr">Date</div>
<div class="col-9 value" v-text="trackInfo.date" />
</div>
<div class="row duration" v-if="trackInfo.time">
<div class="col-3 attr">Duration</div>
<div class="col-9 value" v-text="convertTime(trackInfo.time)" />
</div>
</div>
</Modal>
</div>
<div class="playlists-modal-container">
<Modal title="Playlists" ref="playlistsModal" @close="addToPlaylistTrack = null"
@open="selectedPlaylists = [...Array(playlists.length).keys()].map(() => false)">
<div class="filter">
<label>
<input type="search" placeholder="Filter" v-model="playlistFilter">
</label>
</div>
<div class="playlists">
<label class="row playlist"
:class="{hidden: playlistFilter?.length > 0 && playlist.name.toLowerCase().indexOf(playlistFilter.toLowerCase()) < 0}"
v-for="(playlist, i) in playlists" :key="i">
<input type="checkbox" :checked="selectedPlaylists[i]"
@change="selectedPlaylists[i] = $event.target.checked" />
<span class="name" v-text="playlist.name" />
</label>
</div>
<FormFooter>
<button @click="addToPlaylist">
<i class="fa fa-plus" /> &nbsp; Add
</button>
</FormFooter>
</Modal>
</div>
</template> </template>
<script> <script>
import FormFooter from "@/components/elements/FormFooter";
import Loading from "@/components/Loading";
import Modal from "@/components/Modal";
import MediaUtils from "@/components/Media/Utils";
import MediaView from "@/components/Media/View"; import MediaView from "@/components/Media/View";
import Nav from "@/components/panels/Music/Nav"; import Nav from "@/components/panels/Music/Nav";
import Playlist from "@/components/panels/Music/Playlist"; import Playlist from "@/components/panels/Music/Playlist";
import Playlists from "@/components/panels/Music/Playlists";
import Utils from "@/Utils"; import Utils from "@/Utils";
export default { export default {
name: "Music", name: "Music",
emits: ['play', 'pause', 'stop', 'clear', 'previous', 'next', 'set-volume', 'seek', 'consume', 'repeat', 'random', emits: ['play', 'pause', 'stop', 'clear', 'previous', 'next', 'set-volume', 'seek', 'consume', 'repeat', 'random',
'status-update', 'playlist-update', 'new-playing-track'], 'status-update', 'playlist-update', 'new-playing-track', 'add-to-tracklist', 'remove-from-tracklist',
mixins: [Utils], 'swap-tracks', 'play-playlist', 'load-playlist', 'remove-playlist', 'tracklist-move', 'tracklist-save',
components: {Nav, MediaView, Playlist}, 'add-to-tracklist-from-edited-playlist', 'remove-from-playlist', 'track-info', 'playlist-add', 'add-to-playlist',
'playlist-track-move'],
mixins: [Utils, MediaUtils],
components: {Loading, Modal, Nav, MediaView, Playlist, Playlists, FormFooter},
props: { props: {
pluginName: { pluginName: {
type: String, type: String,
@ -51,15 +141,36 @@ export default {
default: () => [], default: () => [],
}, },
editedPlaylistTracks: {
type: Array,
default: () => [],
},
playlists: {
type: Array,
default: () => [],
},
status: { status: {
type: Object, type: Object,
default: () => {}, default: () => {},
}, },
editedPlaylist: {
type: Number,
},
trackInfo: {
type: String,
},
}, },
data() { data() {
return { return {
selectedView: 'playing', selectedView: 'playing',
selectedPlaylists: [],
addToPlaylistTrack: null,
playlistFilter: '',
} }
}, },
@ -92,13 +203,30 @@ export default {
return return
this.notify({ this.notify({
title: event.track?.artist, html: `<b>${event.track?.artist}</b><br>${event.track?.title}`,
text: event.track?.title, image: {
iconClass: 'fa fa-play', iconClass: 'fa fa-play',
},
}) })
this.$emit('new-playing-track', event) this.$emit('new-playing-track', event)
}, },
async openAddToPlaylist(track) {
this.addToPlaylistTrack = track
this.$refs.playlistsModal.isVisible = true
},
async addToPlaylist() {
this.$emit('add-to-playlist', {
track: this.addToPlaylistTrack,
playlists: [...Array(this.selectedPlaylists.length).keys()].filter((i) => this.selectedPlaylists[i])
})
this.$refs.playlistsModal.isVisible = false
this.addToPlaylistTrack = null
this.playlistFilter = ''
},
}, },
mounted() { mounted() {
@ -118,8 +246,13 @@ export default {
this.subscribe(this.onPlaylistEvent, 'on-playlist-update', this.subscribe(this.onPlaylistEvent, 'on-playlist-update',
'platypush.message.event.music.PlaylistChangeEvent') 'platypush.message.event.music.PlaylistChangeEvent')
this.subscribe(this.onPlaylistEvent, 'on-new-playing-track', this.subscribe(this.onNewPlayingTrack, 'on-new-playing-track',
'platypush.message.event.music.NewPlayingTrackEvent') 'platypush.message.event.music.NewPlayingTrackEvent')
this.$watch(() => this.trackInfo, (info) => {
if (info != null)
this.$refs.trackInfo.isVisible = true
})
}, },
unmounted() { unmounted() {
@ -142,8 +275,76 @@ main {
overflow: auto; overflow: auto;
} }
::v-deep button { ::v-deep(button) {
background: rgba(0, 0, 0, 0); background: none;
padding: .5em .75em;
border: 0;
&:hover {
border: 0;
color: $default-hover-fg;
}
}
::v-deep(a) {
color: $default-fg;
opacity: 0.65;
&:hover {
opacity: 0.75;
border-bottom: 1px dotted;
}
}
}
.playlists-modal-container {
::v-deep(.body) {
display: flex;
flex-direction: column;
padding: 0 !important;
}
::v-deep(.filter) {
padding: .33em;
background-color: $default-bg-6;
border-bottom: $default-border-2;
input {
width: 90%;
}
}
::v-deep(.playlists) {
overflow: auto;
padding: 1.5em;
label {
display: flex;
align-items: center;
&:not(:last-child) {
margin-bottom: .5em;
}
.name {
margin-left: .5em;
}
}
}
}
.track-info-container {
::v-deep(.body) {
height: 15em;
overflow: auto;
@include until($tablet) {
width: 25em;
}
@include from($tablet) {
width: 35em;
}
} }
} }
</style> </style>

View file

@ -3,68 +3,84 @@
<div class="playlist fade-in" v-else> <div class="playlist fade-in" v-else>
<div class="header-container"> <div class="header-container">
<MusicHeader> <MusicHeader ref="header">
<div class="col-8 filter"> <div class="col-8 filter">
<label> <label>
<input type="search" placeholder="Filter"> <input type="search" placeholder="Filter" v-model="filter">
</label> </label>
</div> </div>
<div class="col-4 buttons"> <div class="col-4 buttons">
<button title="Add item" @click="$refs.addToPlaylistModal.visible = true"> <button title="Add track" @click="addTrack">
<i class="fa fa-plus"></i> <i class="fa fa-plus"></i>
</button> </button>
<Dropdown title="Actions" icon-class="fa fa-ellipsis-h"> <Dropdown title="Actions" icon-class="fa fa-ellipsis-h">
<DropdownItem text="Save as playlist" icon-class="fa fa-save" :disabled="!tracks?.length" <DropdownItem text="Save as playlist" icon-class="fa fa-save" :disabled="!tracks?.length"
@click="$refs.savePlaylistModal.visible = true" /> @click="playlistSave" />
<DropdownItem text="Swap tracks" icon-class="fa fa-retweet" :disabled="tracks?.length !== 2 || !selectionMode" /> <DropdownItem text="Swap tracks" icon-class="fa fa-retweet" v-if="selectedTracks?.length === 2"
@click="$emit('swap', selectedTracks)" />
<DropdownItem :text="selectionMode ? 'End selection' : 'Start selection'" icon-class="far fa-check-square" <DropdownItem :text="selectionMode ? 'End selection' : 'Start selection'" icon-class="far fa-check-square"
:disabled="!tracks?.length" @click="selectionMode = !selectionMode" /> :disabled="!tracks?.length" @click="selectionMode = !selectionMode" />
<DropdownItem :text="selectedTracks?.length === tracks?.length ? 'Unselect all' : 'Select all'" <DropdownItem :text="selectedTracks?.length === tracks?.length ? 'Unselect all' : 'Select all'"
icon-class="fa fa-check-double" :disabled="!tracks?.length" icon-class="fa fa-check-double" :disabled="!tracks?.length"
@click="selectedTracks = [...Array(tracks.length).keys()]" /> @click="selectedTracks = selectedTracks.length === tracks.length ? [] : [...Array(tracks.length).keys()]" />
<DropdownItem :text="'Remove track' + (selectedTracks.length > 1 ? 's' : '')"
icon-class="fa fa-trash" v-if="selectedTracks.length > 0"
@click="$emit('remove', [...(new Set(selectedTracks))])" />
<DropdownItem text="Clear playlist" icon-class="fa fa-ban" :disabled="!tracks?.length" @click="$emit('clear')" /> <DropdownItem text="Clear playlist" icon-class="fa fa-ban" :disabled="!tracks?.length" @click="$emit('clear')" />
</Dropdown> </Dropdown>
</div> </div>
</MusicHeader> </MusicHeader>
</div> </div>
<div class="body"> <div class="body" ref="body">
<div class="no-content" v-if="!tracks?.length"> <div class="no-content" v-if="!tracks?.length">
No tracks are loaded No tracks are loaded
</div> </div>
<div class="row track" v-for="(track, i) in tracks" :key="i" @dblclick="$emit('play', {pos: i})"> <div class="row track" @dragstart="onTrackDragStart(i)" @dragend="onTrackDragEnd(i)"
@dragover="onTrackDragOver(i)" draggable="true"
:class="{selected: selectedTracksSet.has(i), active: status?.playingPos === i, hidden: !displayedTracks.has(i)}"
v-for="(track, i) in tracks" :key="i" @click="onTrackClick($event, i)" @dblclick="$emit('play', {pos: i})">
<div class="col-10"> <div class="col-10">
<div class="title" v-text="track.title || '[No Title]'" /> <div class="title">
<div class="artist" v-text="track.artist || '[No Artist]'" /> {{ track.title || '[No Title]' }}
<div class="album" v-text="track.album" v-if="track.album" /> <div class="playing-icon" :class="{paused: status?.state === 'pause'}"
v-if="status?.playingPos === i && (status?.state === 'play' || status?.state === 'pause')">
<span v-for="i in [...Array(3).keys()]" :key="i" />
</div>
</div>
<div class="artist" v-if="track.artist">
<a :href="$route.fullPath" v-text="track.artist"
@click.stop="$emit('search', {artist: track.artist})" />
</div>
<div class="album" v-if="track.album">
<a :href="$route.fullPath" v-text="track.album"
@click.stop="$emit('search', {artist: track.album})" />
</div>
</div> </div>
<div class="col-2 right-side"> <div class="col-2 right-side">
<span class="duration" v-text="convertTime(track.time)" /> <span class="duration" v-text="track.time ? convertTime(track.time) : '-:--'" />
<span class="actions"> <span class="actions">
<Dropdown title="Actions" icon-class="fa fa-ellipsis-h"> <Dropdown title="Actions" icon-class="fa fa-ellipsis-h">
<DropdownItem text="Play" icon-class="fa fa-play" @click="$emit('play', {pos: i})" /> <DropdownItem text="Play" icon-class="fa fa-play" @click="$emit('play', {pos: i})" />
<DropdownItem text="Add to playlist" icon-class="fa fa-list-ul" /> <DropdownItem text="Add to playlist" icon-class="fa fa-list-ul" @click="$emit('add-to-playlist', track)" />
<DropdownItem text="Remove" icon-class="fa fa-trash" @click="$emit('remove', [...(new Set([...selectedTracks, i]))])" />
<DropdownItem text="Track info" icon-class="fa fa-info" @click="$emit('track-info', tracks[i])" />
</Dropdown> </Dropdown>
</span> </span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<Modal :visible="false" ref="addToPlaylistModal">
</Modal>
<Modal :visible="false" ref="savePlaylistModal">
</Modal>
</template> </template>
<script> <script>
import Modal from "@/components/Modal";
import MusicHeader from "@/components/panels/Music/Header"; import MusicHeader from "@/components/panels/Music/Header";
import MediaUtils from "@/components/Media/Utils"; import MediaUtils from "@/components/Media/Utils";
import Dropdown from "@/components/elements/Dropdown"; import Dropdown from "@/components/elements/Dropdown";
@ -73,8 +89,8 @@ import DropdownItem from "@/components/elements/DropdownItem";
export default { export default {
name: "Playlist", name: "Playlist",
mixins: [MediaUtils], mixins: [MediaUtils],
components: {DropdownItem, Dropdown, Modal, MusicHeader}, components: {DropdownItem, Dropdown, MusicHeader},
emits: ['play', 'clear', 'add-to-playlist'], emits: ['play', 'clear', 'add', 'remove', 'swap', 'search', 'move', 'save', 'track-info'],
props: { props: {
tracks: { tracks: {
type: Array, type: Array,
@ -96,13 +112,126 @@ export default {
return { return {
selectionMode: false, selectionMode: false,
selectedTracks: [], selectedTracks: [],
filter: '',
infoTrack: null,
sourcePos: null,
targetPos: null,
} }
}, },
computed: {
selectedTracksSet() {
return new Set(this.selectedTracks)
},
displayedTracks() {
const positions = [...Array(this.tracks.length).keys()]
if (!this.filter?.length)
return new Set(positions)
const self = this
const filter = (self.filter || '').toLowerCase()
return new Set(
positions.filter((pos) => {
const track = this.tracks[pos]
return (track?.artist || '').toLowerCase().indexOf(filter) >= 0
|| (track?.title || '').toLowerCase().indexOf(filter) >= 0
|| (track?.album || '').toLowerCase().indexOf(filter) >= 0
})
)
},
},
methods: {
onTrackClick(event, pos) {
if (event.shiftKey) {
const selectedTracks = this.selectedTracks.sort()
if (!selectedTracks.length) {
this.selectedTracks = [pos]
} else if (pos < selectedTracks[0]) {
this.selectedTracks = [
...this.selectedTracks,
...[...Array(selectedTracks[0] - pos).keys()].map((i) => i + pos)
]
} else if (pos > selectedTracks[selectedTracks.length - 1]) {
this.selectedTracks = [
...this.selectedTracks,
...[...Array(pos - selectedTracks[selectedTracks.length - 1] + 1).keys()].
map((i) => i + selectedTracks[selectedTracks.length - 1])
]
}
} else {
const idx = this.selectedTracks.indexOf(pos)
if (this.selectionMode || event.ctrlKey) {
if (idx >= 0)
this.selectedTracks.splice(idx, 1)
else
this.selectedTracks.push(pos)
} else {
if (idx >= 0)
this.selectedTracks = []
else
this.selectedTracks = [pos]
}
}
},
addTrack() {
const track = prompt('Item path or URL')
if (!track?.length)
return
this.$emit('add', track)
},
onTrackDragStart(track) {
this.sourcePos = track
},
onTrackDragEnd() {
this.$refs.body.querySelectorAll('.track').forEach((track) => track.classList.remove('dragover'));
if (this.sourcePos == null || this.targetPos == null || this.sourcePos === this.targetPos)
return
this.$emit('move', {from: this.sourcePos, to: this.targetPos})
this.sourcePos = null
this.targetPos = null
},
onTrackDragOver(track) {
this.targetPos = track
const tracks = this.$refs.body.querySelectorAll('.track')
tracks.forEach((track) => track.classList.remove('dragover'));
[...tracks][track].classList.add('dragover')
},
playlistSave() {
const name = prompt('Playlist name')
if (!name?.length)
return
this.$emit('save', name)
},
},
mounted() {
const self = this
this.$watch(() => self.status?.playingPos, (pos) => {
if (pos == null)
return
const trackElement = [...self.$refs.body.querySelectorAll('.track')][pos]
const offset = trackElement.offsetTop - parseFloat(getComputedStyle(self.$refs.header.$el).height)
self.$refs.body.scrollTo(0, offset)
})
},
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import 'vars.scss'; @import 'vars.scss';
@import 'track.scss';
.playlist { .playlist {
width: 100%; width: 100%;
@ -135,72 +264,86 @@ export default {
.no-content { .no-content {
height: 100%; height: 100%;
} }
}
.track { .playing-icon {
display: flex; display: inline-block;
justify-content: center; position: relative;
padding: .75em .25em .25em .25em; margin-left: .75em;
box-shadow: 0 2.5px 2px -1px $default-shadow-color; width: 1.5em;
cursor: pointer; height: 1em;
&:hover { @keyframes playing_bar {
background: $hover-bg; 0% {
height: 0
} }
12.5% {
.title { height: 75%
font-size: 1em;
font-weight: normal;
margin: 0;
} }
25% {
.artist, .album { height: 100%
display: inline-flex;
opacity: 0.7;
font-size: .9em;
} }
37.5% {
.artist { height: 10%
margin-right: .25em;
} }
50% {
.album { height: 40%
@include until($tablet) {
display: none;
} }
62.5% {
&::before { height: 50%
content: "\2022"; }
margin-right: .25em; 75% {
height: 30%
}
87.5% {
height: 55%
}
100% {
height: 0
} }
} }
.right-side { span {
display: flex; @include animation(0.2s);
justify-content: right; display: block;
position: absolute;
bottom: 0;
width: .25em;
height: 100%;
background: $default-hover-fg-2;
animation-name: playing_bar;
animation-iteration-count: infinite;
&:nth-child(1){
left: 0;
animation-duration: 2s;
} }
.duration, &:nth-child(2){
.actions { left: 6px;
display: inline-flex; animation-duration: 4s;
align-items: center;
} }
.duration { &:nth-child(3){
font-size: .85em; left: 12px;
opacity: .7; animation-duration: 1s;
}
} }
.actions { &.paused {
::v-deep button { span {
opacity: .7; animation-play-state: paused;
}
} }
} }
} }
::v-deep button { ::v-deep(.track-info-content) {
background: none; .attr {
padding: .5em .75em; opacity: 0.75;
border: 0; }
.value {
text-align: right;
}
} }
</style> </style>

View file

@ -0,0 +1,336 @@
<template>
<Loading v-if="loading" />
<div class="editor-container fade-in" v-else-if="editedPlaylist">
<div class="header-container">
<MusicHeader ref="header">
<button class="back-btn" title="Back" @click="$emit('playlist-edit', null)">
<i class="fas fa-arrow-left" />
</button>
<label class="search-box">
<input type="search" placeholder="Filter" v-model="trackFilter">
</label>
<button class="add-btn" title="Add track" @click="addTrack">
<i class="fas fa-plus" />
</button>
</MusicHeader>
</div>
<div class="editor" ref="editor">
<div class="no-content" v-if="!tracks?.length">
No tracks found
</div>
<div class="row track" draggable="true" v-for="(track, i) in tracks" :key="i"
:class="{selected: selectedTracksSet.has(i), active: status?.playingPos === i, hidden: !displayedTracks.has(i)}"
@dragstart="onTrackDragStart(i)" @dragend="onTrackDragEnd(i)" @dragover="onTrackDragOver(i)"
@click="onTrackClick($event, i)" @dblclick="$emit('load-track', {pos: i, play: true})">
<div class="col-10">
<div class="title">
{{ track.title || '[No Title]' }}
</div>
<div class="artist" v-if="track.artist">
<a :href="$route.fullPath" v-text="track.artist" @click.stop="$emit('search', {artist: track.artist})" />
</div>
<div class="album" v-if="track.album">
<a :href="$route.fullPath" v-text="track.album" @click.stop="$emit('search', {artist: track.album})" />
</div>
</div>
<div class="col-2 right-side">
<span class="duration" v-text="track.time ? convertTime(track.time) : '-:--'" />
<span class="actions">
<Dropdown title="Actions" icon-class="fa fa-ellipsis-h">
<DropdownItem text="Play" icon-class="fa fa-play" @click="$emit('load-track', {pos: i, play: true})" />
<DropdownItem text="Add to tracklist" icon-class="fa fa-plus" @click="$emit('load-track', {pos: i, play: false})" />
<DropdownItem text="Add to playlist" icon-class="fa fa-list-ul" @click="$emit('add-to-playlist', track)" />
<DropdownItem text="Remove" icon-class="fa fa-trash" @click="$emit('remove-track', [...(new Set([...selectedTracks, i]))])" />
<DropdownItem text="Show info" icon-class="fa fa-info" @click.stop="$emit('track-info', tracks[i])" />
</Dropdown>
</span>
</div>
</div>
</div>
</div>
<div class="playlists fade-in" v-else>
<div class="header-container">
<MusicHeader ref="header">
<div class="col-8 filter">
<label>
<input type="search" placeholder="Filter" v-model="filter">
</label>
</div>
</MusicHeader>
</div>
<div class="body" ref="body">
<div class="no-content" v-if="!playlists?.length">
No playlists found
</div>
<div class="row playlist" :class="{hidden: !displayedPlaylists.has(i)}"
v-for="(playlist, i) in playlists" :key="i" @click="$emit('playlist-edit', i)"
@dblclick="$emit('load', i)">
<div class="col-10">
<div class="name" v-text="playlist.name || '[No Name]'" />
</div>
<div class="col-2 right-side">
<span class="actions">
<Dropdown title="Actions" icon-class="fa fa-ellipsis-h">
<DropdownItem text="Play" icon-class="fa fa-play" @click.stop="$emit('play', i)" />
<DropdownItem text="Load" icon-class="fa fa-list-ul" @click.stop="$emit('load', i)" />
<DropdownItem text="Edit" icon-class="fa fa-edit" @click.stop="$emit('playlist-edit', i)" />
<DropdownItem text="Remove" icon-class="fa fa-trash" @click.stop="$emit('remove', i)" />
</Dropdown>
</span>
</div>
</div>
</div>
</div>
</template>
<script>
import MusicHeader from "@/components/panels/Music/Header";
import MediaUtils from "@/components/Media/Utils";
import Dropdown from "@/components/elements/Dropdown";
import DropdownItem from "@/components/elements/DropdownItem";
export default {
name: "Playlists",
mixins: [MediaUtils],
components: {DropdownItem, Dropdown, MusicHeader},
emits: ['play', 'load', 'remove', 'playlist-edit', 'search', 'remove-track', 'load-track', 'track-info',
'playlist-add', 'add-to-playlist', 'track-move'],
props: {
playlists: {
type: Array,
default: () => [],
},
loading: {
type: Boolean,
default: false,
},
tracks: {
type: Array,
default: () => [],
},
editedPlaylist: {
type: Number,
},
},
data() {
return {
selectedTracks: [],
filter: '',
trackFilter: '',
sourcePos: null,
targetPos: null,
}
},
computed: {
selectedTracksSet() {
return new Set(this.selectedTracks)
},
displayedPlaylists() {
const positions = [...Array(this.playlists.length).keys()]
if (!this.filter?.length)
return new Set(positions)
const self = this
const filter = (self.filter || '').toLowerCase()
return new Set(
positions.filter((pos) => {
const track = this.playlists[pos]
return (track?.name || '').toLowerCase().indexOf(filter) >= 0
})
)
},
displayedTracks() {
const positions = [...Array(this.tracks.length).keys()]
if (!this.trackFilter?.length)
return new Set(positions)
const self = this
const filter = (self.trackFilter || '').toLowerCase()
return new Set(
positions.filter((pos) => {
const track = this.tracks[pos]
return (track?.artist || '').toLowerCase().indexOf(filter) >= 0
|| (track?.title || '').toLowerCase().indexOf(filter) >= 0
|| (track?.album || '').toLowerCase().indexOf(filter) >= 0
})
)
},
},
methods: {
onTrackClick(event, pos) {
if (event.shiftKey) {
const selectedTracks = this.selectedTracks.sort()
if (!selectedTracks.length) {
this.selectedTracks = [pos]
} else if (pos < selectedTracks[0]) {
this.selectedTracks = [
...this.selectedTracks,
...[...Array(selectedTracks[0] - pos).keys()].map((i) => i + pos)
]
} else if (pos > selectedTracks[selectedTracks.length - 1]) {
this.selectedTracks = [
...this.selectedTracks,
...[...Array(pos - selectedTracks[selectedTracks.length - 1] + 1).keys()].
map((i) => i + selectedTracks[selectedTracks.length - 1])
]
}
} else {
const idx = this.selectedTracks.indexOf(pos)
if (event.ctrlKey) {
if (idx >= 0)
this.selectedTracks.splice(idx, 1)
else
this.selectedTracks.push(pos)
} else {
if (idx >= 0)
this.selectedTracks = []
else
this.selectedTracks = [pos]
}
}
},
addTrack() {
const track = prompt('Track path or URL')
if (!track?.length)
return
this.$emit('playlist-add', track)
},
onTrackDragStart(track) {
this.sourcePos = track
},
onTrackDragEnd() {
this.$refs.editor.querySelectorAll('.track').forEach((track) => track.classList.remove('dragover'));
if (this.sourcePos == null || this.targetPos == null || this.sourcePos === this.targetPos)
return
this.$emit('track-move', {from: this.sourcePos, to: this.targetPos, playlist: this.editedPlaylist})
this.sourcePos = null
this.targetPos = null
},
onTrackDragOver(track) {
this.targetPos = track
const tracks = this.$refs.editor.querySelectorAll('.track')
tracks.forEach((track) => track.classList.remove('dragover'));
[...tracks][track].classList.add('dragover')
},
},
}
</script>
<style lang="scss" scoped>
@import 'vars.scss';
@import 'track.scss';
.playlists {
width: 100%;
display: flex;
flex-direction: column;
.header-container {
.filter {
input {
width: 100%;
}
}
}
.body {
height: calc(100% - #{$music-header-height});
overflow: auto;
}
.no-content {
height: 100%;
}
.playlist {
display: flex;
justify-content: center;
padding: .75em .25em .25em .25em;
box-shadow: 0 2.5px 2px -1px $default-shadow-color;
cursor: pointer;
&:hover {
background: $hover-bg;
}
&.active {
background: $active-bg;
}
&.selected {
background: $selected-bg;
}
.right-side {
display: flex;
justify-content: right;
}
}
}
.editor-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.header-container {
width: 100%;
}
::v-deep(.header) {
.back-btn {
padding-left: .25em;
}
.add-btn {
float: right;
}
.search-box {
input {
width: 65%;
}
}
}
.editor {
width: 100%;
height: calc(100% - #{$music-header-height});
display: flex;
flex-direction: column;
overflow: auto;
}
}
</style>

View file

@ -0,0 +1,78 @@
.track {
display: flex;
justify-content: center;
padding: .75em .25em .25em .25em;
box-shadow: 0 2.5px 2px -1px $default-shadow-color;
cursor: pointer;
&:hover {
background: $hover-bg;
}
&.active {
background: $active-bg;
}
&.selected {
background: $selected-bg;
}
&.dragover {
border-top: 2px solid $default-hover-fg;
}
.title, .artist, .album, .duration {
&::selection {
background: rgba(0, 0, 0, 0) !important;
}
}
.title {
font-size: 1em;
font-weight: normal;
margin: 0;
}
.artist, .album {
display: inline-flex;
opacity: 0.7;
font-size: .9em;
}
.artist {
margin-right: .25em;
}
.album {
@include until($tablet) {
display: none;
}
&::before {
content: "\2022";
margin-right: .25em;
}
}
.right-side {
display: flex;
justify-content: right;
}
.duration,
.actions {
display: inline-flex;
align-items: center;
}
.duration {
font-size: .85em;
opacity: .7;
}
.actions {
::v-deep(button) {
opacity: .7;
}
}
}

View file

@ -1,10 +1,17 @@
<template> <template>
<Loading v-if="loading" /> <Loading v-if="loading" />
<MusicPlugin plugin-name="music.mpd" :loading="loading" :config="config" :tracks="tracks" :status="status" <MusicPlugin plugin-name="music.mpd" :loading="loading" :config="config" :tracks="tracks" :status="status"
@play="play" @pause="pause" @stop="stop" @previous="previous" @next="next" @clear="clear" :playlists="playlists" :edited-playlist="editedPlaylist" :edited-playlist-tracks="editedPlaylistTracks"
@set-volume="setVolume" @seek="seek" @consume="consume" @random="random" @repeat="repeat" :track-info="trackInfo" @play="play" @pause="pause" @stop="stop" @previous="previous" @next="next"
@status-update="refreshStatus(true)" @playlist-update="refreshTracks(true)" @clear="clear" @set-volume="setVolume" @seek="seek" @consume="consume" @random="random" @repeat="repeat"
@new-playing-track="refreshStatus(true)" /> @status-update="refreshStatus(true)" @playlist-update="refresh(true)"
@new-playing-track="refreshStatus(true)" @remove-from-tracklist="removeFromTracklist"
@add-to-tracklist="addToTracklist" @swap-tracks="swapTracks" @load-playlist="loadPlaylist"
@play-playlist="playPlaylist" @remove-playlist="removePlaylist" @tracklist-move="moveTracklistTracks"
@tracklist-save="saveToPlaylist" @playlist-edit="playlistEditChanged"
@add-to-tracklist-from-edited-playlist="addToTracklistFromEditedPlaylist"
@remove-from-playlist="removeFromPlaylist" @track-info="trackInfo = $event" @playlist-add="playlistAdd"
@add-to-playlist="addToPlaylist" @playlist-track-move="playlistTrackMove" />
</template> </template>
<script> <script>
@ -27,7 +34,11 @@ export default {
return { return {
loading: false, loading: false,
tracks: [], tracks: [],
playlists: [],
status: {}, status: {},
editedPlaylist: null,
editedPlaylistTracks: [],
trackInfo: null,
} }
}, },
@ -85,12 +96,32 @@ export default {
} }
}, },
async refreshPlaylists(background) {
if (!background)
this.loading = true
try {
this.playlists = (await this.request('music.mpd.listplaylists')).map((playlist) => {
return {
name: playlist.playlist,
lastModified: playlist['last-modified'],
}
}).sort((a, b) => a.name.localeCompare(b.name))
} finally {
this.loading = false
}
},
async refresh(background) { async refresh(background) {
if (!background) if (!background)
this.loading = true this.loading = true
try { try {
await Promise.all([this.refreshTracks(background), this.refreshStatus(background)]) await Promise.all([
this.refreshTracks(background),
this.refreshStatus(background),
this.refreshPlaylists(background),
])
} finally { } finally {
this.loading = false this.loading = false
} }
@ -145,19 +176,125 @@ export default {
}, },
async repeat(value) { async repeat(value) {
await this.request('music.mpd.repeat', {value: value}) await this.request('music.mpd.repeat', {value: parseInt(+value)})
await this.refreshStatus(true) await this.refreshStatus(true)
}, },
async random(value) { async random(value) {
await this.request('music.mpd.random', {value: value}) await this.request('music.mpd.random', {value: parseInt(+value)})
await this.refreshStatus(true) await this.refreshStatus(true)
}, },
async consume(value) { async consume(value) {
await this.request('music.mpd.consume', {value: value}) await this.request('music.mpd.consume', {value: parseInt(+value)})
await this.refreshStatus(true) await this.refreshStatus(true)
}, },
async addToTracklist(resource) {
await this.request('music.mpd.add', {resource: resource})
await this.refresh(true)
},
async addToTracklistFromEditedPlaylist(event) {
const track = this.editedPlaylistTracks[event.pos]
if (!track)
return
await this.request('music.mpd.add', {resource: track.file})
await this.refresh(true)
if (event.play)
await this.request('music.mpd.play_pos', {pos: this.tracks.length-1})
},
async removeFromPlaylist(positions) {
await this.request('music.mpd.playlistdelete',
{pos: positions, name: this.playlists[this.editedPlaylist].name})
await this.playlistEditChanged(this.editedPlaylist)
},
async removeFromTracklist(positions) {
await this.request('music.mpd.delete', {positions: positions.sort()})
await this.refresh(true)
},
async swapTracks(positions) {
await this.request('music.mpd.move', {from_pos: positions[0], to_pos: positions[1]})
await this.refresh(true)
},
async playPlaylist(position) {
await this._loadPlaylist(position, true)
},
async loadPlaylist(position) {
await this._loadPlaylist(position, false)
},
async _loadPlaylist(position, play) {
const playlist = this.playlists[position]
await this.request('music.mpd.load', {playlist: playlist.name, play: play})
await this.refresh(true)
},
async removePlaylist(position) {
const playlist = this.playlists[position]
if (!confirm(`Are you REALLY sure that you want to remove the playlist ${playlist.name}?`))
return
await this.request('music.mpd.rm', {playlist: playlist.name})
await this.refreshPlaylists(true)
},
async saveToPlaylist(name) {
await this.request('music.mpd.save', {name: name})
await this.refreshPlaylists(true)
},
async moveTracklistTracks(event) {
await this.request('music.mpd.move', {from_pos: event.from, to_pos: event.to})
await this.refreshTracks(true)
},
async playlistAdd(track) {
await this.request('music.mpd.playlistadd', {uri: track, name: this.playlists[this.editedPlaylist].name})
await this.playlistEditChanged(this.editedPlaylist)
},
async playlistEditChanged(playlist) {
this.editedPlaylist = playlist
if (playlist == null)
return
this.loading = true
try {
this.editedPlaylistTracks = await this.request('music.mpd.listplaylistinfo',
{name: this.playlists[playlist].name})
} finally {
this.loading = false
}
},
async addToPlaylist(event) {
await Promise.all(event.playlists.map(async (playlistIdx) => {
await this.request('music.mpd.playlistadd', {
uri: event.track.file,
name: this.playlists[playlistIdx].name
})
await this.playlistEditChanged(playlistIdx)
}))
},
async playlistTrackMove(event) {
await this.request('music.mpd.playlistmove', {
name: this.playlists[event.playlist].name,
from_pos: event.from,
to_pos: event.to,
})
await this.playlistEditChanged(event.playlist)
},
}, },
mounted() { mounted() {

View file

@ -6,6 +6,7 @@ $default-bg-4: #f1f3f2 !default;
$default-bg-5: #edf0ee !default; $default-bg-5: #edf0ee !default;
$default-bg-6: #e4eae8 !default; $default-bg-6: #e4eae8 !default;
$default-bg-7: #e4e4e4 !default; $default-bg-7: #e4e4e4 !default;
$default-fg: black !default;
//// Notifications //// Notifications
$notification-bg: rgba(185, 255, 193, 0.9) !default; $notification-bg: rgba(185, 255, 193, 0.9) !default;
@ -68,6 +69,7 @@ $active-glow-bg-2: #9cdfb0 !default;
$default-hover-fg: #35b870 !default; $default-hover-fg: #35b870 !default;
$default-hover-fg-2: #38cf80 !default; $default-hover-fg-2: #38cf80 !default;
$hover-bg: #bef6da !default; $hover-bg: #bef6da !default;
$active-bg: #8fefb7 !default;
/// Navigator /// Navigator
$nav-bg: #002626 !default; $nav-bg: #002626 !default;

View file

@ -645,7 +645,7 @@ class MusicMpdPlugin(MusicPlugin):
if isinstance(pos, int): if isinstance(pos, int):
pos = [pos] pos = [pos]
for p in pos: for p in sorted(pos, reverse=True):
self._exec('playlistdelete', name, p) self._exec('playlistdelete', name, p)
@action @action