diff --git a/platypush/backend/http/static/css/source/common/modal.scss b/platypush/backend/http/static/css/source/common/modal.scss index 1f35afe75..c6deaa362 100644 --- a/platypush/backend/http/static/css/source/common/modal.scss +++ b/platypush/backend/http/static/css/source/common/modal.scss @@ -1,5 +1,5 @@ .modal-container { - position: absolute; + position: fixed; display: flex; align-items: center; justify-content: center; diff --git a/platypush/backend/http/static/css/source/webpanel/plugins/music.snapcast/index.scss b/platypush/backend/http/static/css/source/webpanel/plugins/music.snapcast/index.scss index 89500ede9..53137142a 100644 --- a/platypush/backend/http/static/css/source/webpanel/plugins/music.snapcast/index.scss +++ b/platypush/backend/http/static/css/source/webpanel/plugins/music.snapcast/index.scss @@ -70,11 +70,58 @@ $host-shadow: $default-shadow; .modal { .info { - .row { - &:hover { background: $hover-bg; } - .value { - text-align: right; + padding: 2rem; + + .section { + border: $default-border-2; + border-radius: 1rem; + &:not(last-child) { margin-bottom: 2rem; } + + .title { + border-bottom: $default-border-2; + padding: 1rem; + text-transform: uppercase; } + + &.clients .row { + padding: .5rem; + + label { + margin: 0 0 0 .5rem; + } + } + } + + .row { + padding: .33rem .5rem; + border-radius: .75rem; + display: flex; + align-items: center; + + &:nth-child(odd) { background: rgba(255, 255, 255, 0.0); } + &:nth-child(even) { background: $default-bg-3; } + &:hover { background: $hover-bg; } + + .label { font-weight: bold; } + .value { text-align: right; } + } + } + } +} + +#music-snapcast-client-info { + .info { + .buttons { + background: initial; + margin-top: 1.5rem; + padding-top: 1.5rem; + border-top: $default-border-2; + display: flex; + justify-content: center; + + button { + color: #900; + border-color: #900; } } } @@ -99,7 +146,7 @@ $host-shadow: $default-shadow; @media #{map-get($widths, 'l')} { .music-snapcast-container { .modal { - width: 65vw; + width: 45vw; } } } diff --git a/platypush/backend/http/static/js/plugins/music.snapcast/client.js b/platypush/backend/http/static/js/plugins/music.snapcast/client.js index 7c79eb291..105e118e7 100644 --- a/platypush/backend/http/static/js/plugins/music.snapcast/client.js +++ b/platypush/backend/http/static/js/plugins/music.snapcast/client.js @@ -32,6 +32,35 @@ Vue.component('music-snapcast-client', { }); Vue.component('music-snapcast-client-info', { - props: ['info'], + props: { + info: { type: Object } + }, + + data: function() { + return { + loading: false, + }; + }, + + methods: { + deleteClient: async function(event) { + if (!confirm('Are you SURE that you want to remove this client?')) { + return; + } + + this.loading = true; + await request('music.snapcast.delete_client', { + client: this.info.id, + host: this.info.server.host.name, + port: this.info.server.host.port, + }); + + this.loading = false; + createNotification({ + text: 'Snapcast client successfully removed', + image: { icon: 'check' } + }); + }, + }, }); diff --git a/platypush/backend/http/static/js/plugins/music.snapcast/group.js b/platypush/backend/http/static/js/plugins/music.snapcast/group.js index 91f7d10a5..626bd5fc1 100644 --- a/platypush/backend/http/static/js/plugins/music.snapcast/group.js +++ b/platypush/backend/http/static/js/plugins/music.snapcast/group.js @@ -22,6 +22,59 @@ Vue.component('music-snapcast-group', { }); Vue.component('music-snapcast-group-info', { - props: ['info'], + props: { + info: { type: Object } + }, + + data: function() { + return { + loading: false, + }; + }, + + methods: { + onClientUpdate: async function(event) { + var clients = this.$refs.groupClients + .map(row => row.querySelector('input[type=checkbox]:checked')) + .filter(_ => _ != null) + .map(input => input.value); + + this.loading = true; + await request('music.snapcast.group_set_clients', { + clients: clients, + group: this.info.group.id, + host: this.info.server.host.name, + port: this.info.server.host.port, + }); + + this.loading = false; + createNotification({ + text: 'Snapcast group successfully updated', + image: { + icon: 'check', + } + }); + }, + + onStreamUpdate: async function(event) { + this.loading = true; + await request('music.snapcast.group_set_stream', { + stream_id: event.target.value, + group: this.info.group.id, + host: this.info.server.host.name, + port: this.info.server.host.port, + }); + + this.loading = false; + this.info.group.stream_id = event.target.value; + + createNotification({ + text: 'Snapcast stream successfully updated', + image: { + icon: 'check', + } + }); + }, + }, }); diff --git a/platypush/backend/http/static/js/plugins/music.snapcast/host.js b/platypush/backend/http/static/js/plugins/music.snapcast/host.js index 16b971039..e27ab1472 100644 --- a/platypush/backend/http/static/js/plugins/music.snapcast/host.js +++ b/platypush/backend/http/static/js/plugins/music.snapcast/host.js @@ -15,6 +15,8 @@ Vue.component('music-snapcast-host', { }); Vue.component('music-snapcast-host-info', { - props: ['info'], + props: { + info: { type: Object } + }, }); diff --git a/platypush/backend/http/static/js/plugins/music.snapcast/index.js b/platypush/backend/http/static/js/plugins/music.snapcast/index.js index bec4eae48..812e3d9be 100644 --- a/platypush/backend/http/static/js/plugins/music.snapcast/index.js +++ b/platypush/backend/http/static/js/plugins/music.snapcast/index.js @@ -4,6 +4,7 @@ Vue.component('music-snapcast', { data: function() { return { hosts: {}, + ports: {}, modal: { host: { visible: false, @@ -24,6 +25,31 @@ Vue.component('music-snapcast', { }, methods: { + _parseServerStatus: function(status) { + status.server.host.port = this.ports[status.server.host.name]; + var groups = {}; + + for (const group of status.groups) { + var clients = {}; + for (const client of group.clients) { + clients[client.id] = client; + } + + group.clients = clients; + groups[group.id] = group; + } + + status.groups = groups; + var streams = {}; + + for (const stream of status.streams) { + streams[stream.id] = stream; + } + + status.streams = streams; + Vue.set(this.hosts, status.server.host.name, status); + }, + refresh: async function() { let hosts = await request('music.snapcast.get_backend_hosts'); let promises = Object.keys(hosts).map( @@ -34,28 +60,8 @@ Vue.component('music-snapcast', { this.hosts = {}; for (const status of statuses) { - status.server.host.port = hosts[status.server.host.name]; - var groups = {}; - - for (const group of status.groups) { - var clients = {}; - for (const client of group.clients) { - clients[client.id] = client; - } - - group.clients = clients; - groups[group.id] = group; - } - - status.groups = groups; - var streams = {}; - - for (const stream of status.streams) { - streams[stream.id] = stream; - } - - status.streams = streams; - Vue.set(this.hosts, status.server.host.name, status); + this.ports[status.server.host.name] = hosts[status.server.host.name]; + this._parseServerStatus(status); } }, @@ -72,11 +78,11 @@ Vue.component('music-snapcast', { }, onServerUpdate: function(event) { - this.refresh(); + this._parseServerStatus(event.server); }, onStreamUpdate: function(event) { - this.streams[event.stream_id] = event.stream; + this.hosts[event.host].streams[event.stream.id] = event.stream; }, onClientVolumeChange: function(event) { @@ -103,10 +109,21 @@ Vue.component('music-snapcast', { this.modal[event.type].info = this.hosts[event.host]; break; case 'group': - this.modal[event.type].info = this.hosts[event.host].groups[event.group]; + this.modal[event.type].info.server = this.hosts[event.host].server; + this.modal[event.type].info.group = this.hosts[event.host].groups[event.group]; + this.modal[event.type].info.streams = this.hosts[event.host].streams; + this.modal[event.type].info.clients = {}; + + for (const group of Object.values(this.hosts[event.host].groups)) { + for (const client of Object.values(group.clients)) { + this.modal[event.type].info.clients[client.id] = client; + } + } + break; case 'client': this.modal[event.type].info = this.hosts[event.host].groups[event.group].clients[event.client]; + this.modal[event.type].info.server = this.hosts[event.host].server; break; } diff --git a/platypush/backend/http/templates/plugins/music.snapcast/group.html b/platypush/backend/http/templates/plugins/music.snapcast/group.html index d189a8282..7f7e80ea5 100644 --- a/platypush/backend/http/templates/plugins/music.snapcast/group.html +++ b/platypush/backend/http/templates/plugins/music.snapcast/group.html @@ -5,7 +5,7 @@