UI improvements + support for MPD playlists and folders
This commit is contained in:
parent
fc608317fd
commit
28bc4c748e
6 changed files with 199 additions and 10 deletions
|
@ -1,14 +1,13 @@
|
||||||
body {
|
body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
overflow-x: hidden;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #f4f5f6;
|
background: #f4f5f6;
|
||||||
padding: 25px;
|
padding: 25px;
|
||||||
margin: -10px 10px 35px -10px;
|
margin: 0px 10px 35px -10px;
|
||||||
border-bottom: 1px solid #e1e4e8;
|
border-bottom: 1px solid #e1e4e8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,8 +19,21 @@ header {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#date-time {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#date-time > .date {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
#date-time > .time {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
width: 80%;
|
width: 95%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,10 +46,13 @@ main {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
margin-top: -25px;
|
margin-top: -25px;
|
||||||
|
border-radius: 0 0 7.5px 7.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playback-controls {
|
.playback-controls {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
border-bottom: 1px solid #e8eaf0;
|
||||||
|
padding-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button[disabled] {
|
.button[disabled] {
|
||||||
|
@ -46,7 +61,7 @@ main {
|
||||||
|
|
||||||
.track-info {
|
.track-info {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: -20px -20px 15px -20px;
|
margin: -20px -20px 0 -20px;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,3 +70,28 @@ main {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#playlist-content {
|
||||||
|
margin-left: 0;
|
||||||
|
width: 78%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-pane {
|
||||||
|
height: 360px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
padding: 15px 15px 0 5px;
|
||||||
|
background: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-item {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-item:nth-child(odd) {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-track > .track-time {
|
||||||
|
text-align: right;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
var websocket;
|
var websocket;
|
||||||
|
var dateTimeInterval;
|
||||||
var eventListeners = [];
|
var eventListeners = [];
|
||||||
|
|
||||||
var initWebsocket = function() {
|
var initWebsocket = function() {
|
||||||
|
@ -16,12 +17,53 @@ $(document).ready(function() {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var initDateTime = function() {
|
||||||
|
var getDateString = function(t) {
|
||||||
|
var s = '';
|
||||||
|
switch (t.getDay()) {
|
||||||
|
case 1: s += 'Mon '; break; case 2: s += 'Tue '; break; case 3: s += 'Wed '; break;
|
||||||
|
case 4: s += 'Thu '; break; case 5: s += 'Fri '; break; case 6: s += 'Sat '; break;
|
||||||
|
case 7: s += 'Sun '; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s += (t.getDate() < 10 ? '0' : '') + t.getDate() + ' ';
|
||||||
|
switch (t.getMonth()) {
|
||||||
|
case 0: s += 'Jan '; break; case 1: s += 'Feb '; break; case 2: s += 'Mar '; break;
|
||||||
|
case 3: s += 'Apr '; break; case 4: s += 'May '; break; case 5: s += 'Jun '; break;
|
||||||
|
case 6: s += 'Jul '; break; case 7: s += 'Ago '; break; case 8: s += 'Sep '; break;
|
||||||
|
case 9: s += 'Oct '; break; case 10: s += 'Nov '; break; case 11: s += 'Dec '; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s += t.getFullYear();
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
|
||||||
|
var setDateTime = function() {
|
||||||
|
var $dateTime = $('#date-time');
|
||||||
|
var $date = $dateTime.find('.date');
|
||||||
|
var $time = $dateTime.find('.time');
|
||||||
|
var now = new Date();
|
||||||
|
|
||||||
|
$date.text(getDateString(now));
|
||||||
|
$time.text((now.getHours() < 10 ? '0' : '') + now.getHours() + ':' +
|
||||||
|
(now.getMinutes() < 10 ? '0' : '') + now.getMinutes());
|
||||||
|
};
|
||||||
|
|
||||||
|
if (dateTimeInterval) {
|
||||||
|
clearInterval(dateTimeInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
setDateTime();
|
||||||
|
dateTimeInterval = setInterval(setDateTime, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
var registerEventListener = function(listener) {
|
var registerEventListener = function(listener) {
|
||||||
eventListeners.push(listener);
|
eventListeners.push(listener);
|
||||||
};
|
};
|
||||||
|
|
||||||
var init = function() {
|
var init = function() {
|
||||||
initWebsocket();
|
initWebsocket();
|
||||||
|
initDateTime();
|
||||||
};
|
};
|
||||||
|
|
||||||
window.registerEventListener = registerEventListener;
|
window.registerEventListener = registerEventListener;
|
||||||
|
|
|
@ -97,6 +97,89 @@ $(document).ready(function() {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var initPlaylist = function() {
|
||||||
|
execute(
|
||||||
|
{
|
||||||
|
type: 'request',
|
||||||
|
action: 'music.mpd.playlistinfo',
|
||||||
|
},
|
||||||
|
|
||||||
|
onSuccess = function(response) {
|
||||||
|
var $playlistContent = $('#playlist-content');
|
||||||
|
var tracks = response.response.output;
|
||||||
|
|
||||||
|
for (var track of tracks) {
|
||||||
|
var $element = $('<div></div>')
|
||||||
|
.addClass('playlist-track')
|
||||||
|
.addClass('row').addClass('music-item')
|
||||||
|
.data('file', track.file);
|
||||||
|
|
||||||
|
var $artist = $('<div></div>')
|
||||||
|
.addClass('four').addClass('columns')
|
||||||
|
.addClass('track-artist').text(track.artist);
|
||||||
|
|
||||||
|
var $title = $('<div></div>')
|
||||||
|
.addClass('six').addClass('columns')
|
||||||
|
.addClass('track-title').text(track.title);
|
||||||
|
|
||||||
|
var $time = $('<div></div>')
|
||||||
|
.addClass('two').addClass('columns')
|
||||||
|
.addClass('track-time').text(
|
||||||
|
'' + parseInt(parseInt(track.time)/60) +
|
||||||
|
':' + (parseInt(track.time)%60 < 10 ? '0' : '') +
|
||||||
|
parseInt(track.time)%60);
|
||||||
|
|
||||||
|
$artist.appendTo($element);
|
||||||
|
$title.appendTo($element);
|
||||||
|
$time.appendTo($element);
|
||||||
|
$element.appendTo($playlistContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
var initBrowser = function() {
|
||||||
|
execute(
|
||||||
|
{
|
||||||
|
type: 'request',
|
||||||
|
action: 'music.mpd.lsinfo',
|
||||||
|
},
|
||||||
|
|
||||||
|
onSuccess = function(response) {
|
||||||
|
var $browserContent = $('#music-browser');
|
||||||
|
var items = response.response.output;
|
||||||
|
var directories = [];
|
||||||
|
var playlists = [];
|
||||||
|
|
||||||
|
for (var item of items) {
|
||||||
|
if ('directory' in item) {
|
||||||
|
directories.push(item.directory);
|
||||||
|
} else if ('playlist' in item) {
|
||||||
|
playlists.push(item.playlist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var directory of directories.sort()) {
|
||||||
|
var $element = $('<div></div>')
|
||||||
|
.addClass('browser-directory').addClass('music-item')
|
||||||
|
.addClass('browser-item').addClass('row')
|
||||||
|
.html('<i class="fa fa-folder-open-o"></i> ' + directory);
|
||||||
|
|
||||||
|
$element.appendTo($browserContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var playlist of playlists.sort()) {
|
||||||
|
var $element = $('<div></div>')
|
||||||
|
.addClass('browser-playlist').addClass('music-item')
|
||||||
|
.addClass('browser-item').addClass('row')
|
||||||
|
.html('<i class="fa fa-music"></i> ' + playlist);
|
||||||
|
|
||||||
|
$element.appendTo($browserContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
var initBindings = function() {
|
var initBindings = function() {
|
||||||
window.registerEventListener(onEvent);
|
window.registerEventListener(onEvent);
|
||||||
var $playbackControls = $('.playback-controls').find('button');
|
var $playbackControls = $('.playback-controls').find('button');
|
||||||
|
@ -122,6 +205,8 @@ $(document).ready(function() {
|
||||||
|
|
||||||
var init = function() {
|
var init = function() {
|
||||||
initStatus();
|
initStatus();
|
||||||
|
initPlaylist();
|
||||||
|
initBrowser();
|
||||||
initBindings();
|
initBindings();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,16 @@
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<div class="logo">
|
<div class="row">
|
||||||
<span class="logo-1">Platypush</span>
|
<div class="logo nine columns">
|
||||||
<span class="logo-2">Web Panel</span>
|
<span class="logo-1">Platypush</span>
|
||||||
|
<span class="logo-2">Web Panel</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="date-time" class="three columns">
|
||||||
|
<div class="date"></div>
|
||||||
|
<div class="time"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<span class="track"></span>
|
<span class="track"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row playback-controls">
|
||||||
<div class="eight columns offset-by-two playback-controls">
|
<div class="eight columns offset-by-two">
|
||||||
<button data-action="previous">
|
<button data-action="previous">
|
||||||
<i class="fa fa-step-backward"></i>
|
<i class="fa fa-step-backward"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -30,3 +30,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div id="music-browser" class="three columns music-pane"></div>
|
||||||
|
<div id="playlist-content" class="nine columns music-pane"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,16 @@ class MusicMpdPlugin(MusicPlugin):
|
||||||
def currentsong(self):
|
def currentsong(self):
|
||||||
return Response(output=self.client.currentsong())
|
return Response(output=self.client.currentsong())
|
||||||
|
|
||||||
|
def playlistinfo(self):
|
||||||
|
return Response(output=self.client.playlistinfo())
|
||||||
|
|
||||||
|
def listplaylists(self):
|
||||||
|
return Response(output=sorted(self.client.listplaylists(),
|
||||||
|
key=lambda p: p['playlist']))
|
||||||
|
|
||||||
|
def lsinfo(self):
|
||||||
|
return Response(output=self.client.lsinfo())
|
||||||
|
|
||||||
|
|
||||||
# vim:sw=4:ts=4:et:
|
# vim:sw=4:ts=4:et:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue