Updated interface

- added a bar on the top which shows some info
- moved mod buttons to the bar
- added some information about your queue to the bar
- merged the table for current song and full queue
- some more small fixes
This commit is contained in:
Olaf Slomp
2019-03-28 18:54:46 +01:00
committed by Gerdriaan Mulder
parent 568f7c6a50
commit d0c82f33df
5 changed files with 190 additions and 146 deletions

View File

@ -168,12 +168,25 @@ def managesongs(request):
@api_auth_required @api_auth_required
def queue(request): def queue(request):
queue = request.user.queue queue = request.user.queue
return JsonResponse({ infobar = {"start_personal_queue": 0, "length_personal_queue": 0, "length_total_queue": 0, "end_personal_queue": 0}
for song in queue.queue():
infobar["length_total_queue"] += song.song.duration
if song.user == request.user:
infobar["length_personal_queue"] += song.song.duration
infobar["end_personal_queue"] = infobar["length_total_queue"]
if infobar["start_personal_queue"] == 0:
infobar["start_personal_queue"] = infobar["length_total_queue"] - song.song.duration
json = {
'current_song': playlist_song_to_dict(queue.current_song()), 'current_song': playlist_song_to_dict(queue.current_song()),
'queue': [playlist_song_to_dict(playlist_song, user=request.user) for playlist_song in queue.queue()], 'queue': [playlist_song_to_dict(playlist_song, user=request.user) for playlist_song in queue.queue()],
'started_at': 0 if queue.started_at is None else int(queue.started_at.timestamp()), 'started_at': 0 if queue.started_at is None else int(queue.started_at.timestamp()),
'current_time': int(time.time()) 'current_time': int(time.time()),
}) 'user_name': request.user.name,
'infobar': infobar,
}
return JsonResponse(json)
@api_auth_required @api_auth_required
@ -230,6 +243,7 @@ def report(request):
msg = request.POST.get('msg') msg = request.POST.get('msg')
err = song.report(request.user, msg) err = song.report(request.user, msg)
return JsonResponse({'success': True}) return JsonResponse({'success': True})

View File

@ -11,7 +11,7 @@
padding: 8px; padding: 8px;
background: silver; background: silver;
white-space: nowrap; white-space: nowrap;
z-index: 9999; z-index: 1;
} }
#queue-time-header { #queue-time-header {
@ -26,6 +26,26 @@ footer {
color: #777777; color: #777777;
} }
.marietjequeue-start { .marietjequeue-pre-start td {
border-top: 4px double #777777; border-bottom: 3px double #777777;
}
.block-button {
border-color: #cccccc;
color: #337ab7;
transition: 1s transform ease-in-out;
}
.currentsong{
border-bottom: 1px solid #DDDDDD;
}
.requested_song .plays-at, .requested_song .requested-by {
font-weight: bold;
}
.table-header-style td, .table-header-style{
border-top: 3px solid #FFFFFF;
background-color: #f9f9f9;
border-bottom: 2px solid #777777;
} }

View File

@ -3,18 +3,19 @@ var timeOffset = 0;
var timeStarted = 0; var timeStarted = 0;
var currentSong = null; var currentSong = null;
var queue = null; var queue = null;
var infobar = null;
var songs = []; var songs = [];
var refreshing = false; var refreshing = false;
var iteration = 0; var iteration = 0;
var requestViewOpen = false; var requestViewOpen = false;
var showTimeToPlay = true; var showTimeToPlay = true;
var noRemove = false; var noRemove = false;
var user_name;
var playNextAt = 0;
$(function () { $(function () {
$('.pagesize').val(Cookies.get('pagesize')); $('.pagesize').val(Cookies.get('pagesize'));
showTimeToPlay = (Cookies.get('showtimetoplay') || '1') === '1' ? true : false; showTimeToPlay = ((Cookies.get('showtimetoplay') || '1') === '1' ? true : false);
$('#queue-time-header').text(showTimeToPlay ? 'Plays In' : 'Plays At'); $('#queue-time-header').text(showTimeToPlay ? 'Plays In' : 'Plays At');
refreshQueue(); refreshQueue();
setInterval(updateTime, 1000); setInterval(updateTime, 1000);
@ -48,12 +49,12 @@ $(function () {
$(document).on('click', '[data-report-song-id]', function () { $(document).on('click', '[data-report-song-id]', function () {
var songId = $(this).data('report-song-id'); var songId = $(this).data('report-song-id');
var message = prompt("What is wrong with the song?"); var message = prompt("What is wrong with the song?");
if (message == "") { if (message === "") {
createAlert('danger', 'Please enter a message.'); createAlert('danger', 'Please enter a message.');
return false return false;
} }
if (message == null) { if (message === null) {
return false return false;
} }
$.post('/api/report', {id: songId, msg: message, csrfmiddlewaretoken: csrf_token}, function (result) { $.post('/api/report', {id: songId, msg: message, csrfmiddlewaretoken: csrf_token}, function (result) {
if (result.success) { if (result.success) {
@ -105,12 +106,12 @@ $(function () {
getSongs(); getSongs();
}); });
$('#volume-down').click(function(e){ $('#volume_down').click(function(e){
e.preventDefault(); e.preventDefault();
$.post('/api/volumedown', {csrfmiddlewaretoken: csrf_token}); $.post('/api/volumedown', {csrfmiddlewaretoken: csrf_token});
}); });
$('#volume-up').click(function(e){ $('#volume_up').click(function(e){
e.preventDefault(); e.preventDefault();
$.post('/api/volumeup', {csrfmiddlewaretoken: csrf_token}); $.post('/api/volumeup', {csrfmiddlewaretoken: csrf_token});
}); });
@ -127,7 +128,7 @@ $(function () {
var row = $(this).parent(); var row = $(this).parent();
var timeLeft = row.find('.time-left'); var timeLeft = row.find('.time-left');
var playsAt = row.find('.plays-at'); var playsAt = row.find('.plays-at');
var text = timeLeft[0] ? 'Time Left: ' + timeLeft.text() : 'Plays At: ' + playsAt.text(); var text = (timeLeft[0] ? 'Time Left: ' + timeLeft.text() : 'Plays At: ' + playsAt.text());
$('body').append('<span class="song-info">Requested By: ' + row.find('.requested-by').text() + '<br>' + text $('body').append('<span class="song-info">Requested By: ' + row.find('.requested-by').text() + '<br>' + text
+ '</span>'); + '</span>');
var offset = row.offset(); var offset = row.offset();
@ -141,104 +142,107 @@ $(function () {
} }
}); });
$('#queue-time-header').click(function(){ $('#timeswitch').click(function(){
showTimeToPlay = !showTimeToPlay; showTimeToPlay = !showTimeToPlay;
$('#queue-time-header').text(showTimeToPlay ? 'Plays In' : 'Plays At'); $('.timeswitcher').toggleClass('active');
Cookies.set('showtimetoplay', showTimeToPlay ? '1' : '0', { expires: 365 }); $('#timeswitch').text(showTimeToPlay ? 'Plays In' : 'Plays At');
Cookies.set('showtimetoplay', (showTimeToPlay ? '1' : '0'), { expires: 365 });
refreshQueue();
}); });
getSongs(); getSongs();
}); });
function cancelSong(id) function cancelSong(id) {
{
$.post('/api/cancel', {id: id, csrfmiddlewaretoken: csrf_token}, function () { $.post('/api/cancel', {id: id, csrfmiddlewaretoken: csrf_token}, function () {
refreshQueue(); refreshQueue();
}); });
return false; return false;
} }
function moveUp(id) function moveUp(id) {
{
$.post('/api/moveup', {id: id, csrfmiddlewaretoken: csrf_token}, function () { $.post('/api/moveup', {id: id, csrfmiddlewaretoken: csrf_token}, function () {
refreshQueue(); refreshQueue();
}); });
return false; return false;
} }
function moveDown(id) function moveDown(id) {
{
$.post('/api/movedown', {id: id, csrfmiddlewaretoken: csrf_token}, function () { $.post('/api/movedown', {id: id, csrfmiddlewaretoken: csrf_token}, function () {
refreshQueue(); refreshQueue();
}); });
return false; return false;
} }
function updateTime() function updateTime() {
{
var timestamp = Date.now() / 1000 | 0; var timestamp = Date.now() / 1000 | 0;
var secondsLeft = currentSong.song.duration - (timestamp - timeStarted) + timeOffset; var secondsLeft = currentSong.song.duration - (timestamp - timeStarted) + timeOffset;
iteration = (iteration + 1) % 10; iteration = (iteration + 1) % 10;
if (secondsLeft >= 0) function showExactOrRelative(time) {
{ return (!showTimeToPlay) ? "at: " + (secondsLeft + timestamp + time).timestampToHHMMSS() : "in: " + (secondsLeft + time).secondsToMMSS();
}
if (infobar['end_personal_queue'] !== 0){
$('.start-queue').text("First song starts " + showExactOrRelative(infobar['start_personal_queue']));
$('.duration-queue').text( " (" + (infobar['length_personal_queue']).secondsToMMSS() + ")");
$('.end-queue').text("Last song ends " + showExactOrRelative(infobar['end_personal_queue']));
}
if (secondsLeft >= 0) {
$('.currentsong .time-left').text(secondsLeft.secondsToMMSS()); $('.currentsong .time-left').text(secondsLeft.secondsToMMSS());
refreshSeconds(secondsLeft + timestamp, timestamp); refreshSeconds(secondsLeft + timestamp, timestamp);
} }
// Refresh every ten seconds, or if the song has ended in the last ten // Refresh every ten seconds, or if the song has ended in the last ten
// seconds. Only if it is not refreshing already. // seconds. Only if it is not refreshing already.
if ((iteration === 0 || secondsLeft <= 0 && secondsLeft > -10) && !refreshing) if ((iteration === 0 || (secondsLeft <= 0 && secondsLeft > -10)) && !refreshing){
{
refreshQueue(); refreshQueue();
} }
} }
function renderQueue(playNextAt, now) function renderQueue(playNextAt, now) {
{
$('.queuebody').empty(); $('.queuebody').empty();
var timeToPlay = playNextAt - now; var timeToPlay = playNextAt - now;
var canDeletePrevious = false; var canDeletePrevious = false;
$.each(queue, function (id, song) { $.each(queue, function (id, song) {
var userRequested = user_name;
var requestedBy = song.requested_by; var requestedBy = song.requested_by;
var reqMarietje = requestedBy != 'Marietje'; var reqMarietje = requestedBy !== 'Marietje';
var startMarietje = false var startMarietje = false;
var requestNext = false;
var requestPrev = false;
//checks if id is the last item and returns false if the next song is Marietje, while the current song is not. //checks if id is the last item and returns false if the next song is Marietje, while the current song is not.
if(id === queue.length-1){ if(id !== queue.length - 1) {
var requestNext = false requestNext = !((queue[id + 1].requested_by === 'Marietje') && (requestedBy !== 'Marietje'));
} else {
var requestNext = !((queue[id+1].requested_by === 'Marietje') && (requestedBy !== 'Marietje'))
} }
//checks if id is the first item and returns false if the previous song is not Marietje, while the current song is. //checks if id is the first item and returns false if the previous song is not Marietje, while the current song is.
if(id === 0){ if(id !== 0){
var requestPrev = false var prevItem = queue[id - 1].id;
} else {
var prevItem = queue[id-1].id
if(queue[id-1].requested_by !== 'Marietje') { if(queue[id-1].requested_by !== 'Marietje') {
var requestPrev = false requestPrev = false;
if (requestedBy == 'Marietje'){ if (requestedBy === 'Marietje') {
var startMarietje = true startMarietje = true;
} else { } else {
var requestPrev = true requestPrev = true;
}
} else {
requestPrev = true;
} }
} else {var requestPrev = true}
} }
var canDelete = song.can_move_down || canMoveSongs; var canDelete = song.can_move_down || canMoveSongs;
var canMoveUp = canMoveSongs && requestPrev || canDeletePrevious && reqMarietje && requestPrev; var canMoveUp = canMoveSongs && requestPrev || (canDeletePrevious && reqMarietje && requestPrev);
var canMoveDown = canMoveSongs && requestNext || canDelete && reqMarietje && requestNext; var canMoveDown = canMoveSongs && requestNext || (canDelete && reqMarietje && requestNext);
var artist = song.song.artist.trim() === '' ? '?' : song.song.artist; var artist = (song.song.artist.trim() === '' ? '?' : song.song.artist);
var title = song.song.title.trim() === '' ? '?' : song.song.title; var title = (song.song.title.trim() === '' ? '?' : song.song.title);
var marietjeclass = reqMarietje ? '' : ' class="marietjequeue"'; var songclass = ' class="normal_song' + (reqMarietje ? '' : ' marietjequeue')
var marietjestartclass = startMarietje ? ' class="marietjequeue marietjequeue-start"' : ''; + (!requestNext ? ' marietjequeue-pre-start' : '')
+ (startMarietje ? ' marietjequeue-post-start':'')
+ (userRequested === requestedBy ? ' requested_song':'');
showTime = showTimeToPlay ? (timeToPlay < 0 ? '' : timeToPlay.secondsToMMSS()) : (playNextAt < now ? '' : playNextAt.timestampToHHMMSS()) var showTime = (showTimeToPlay ? (timeToPlay < 0 ? '' : timeToPlay.secondsToMMSS()) : (playNextAt < now ? '' : playNextAt.timestampToHHMMSS()));
$('.queuebody:last-child').append('<tr' + marietjestartclass + marietjeclass + '>' + '<td class="artist">' + artist $('.queuebody:last-child').append('<tr' + songclass + '">' + '<td class="artist">' + artist
+ '</td><td class="title">' + title + '</td><td class="hidden-xs requested-by">' + requestedBy + '</td><td class="title">' + title + '</td><td class="hidden-xs requested-by">' + requestedBy
+ '</td><td class="hidden-xs plays-at" style="text-align: right;">' + showTime + '</td><td class="hidden-xs plays-at" style="text-align: right;">' + showTime
+ '</td><td>' + '<a href="#" class="glyphicon glyphicon-arrow-up' + '</td><td>' + '<a href="#" class="glyphicon glyphicon-arrow-up'
+ (canMoveUp && id !== 0 ? '' : ' invisible') + ((canMoveUp && id !== 0) ? '' : ' invisible')
+ '" onclick=" return moveDown(' + prevItem + '" onclick=" return moveDown(' + prevItem
+ ')"></a>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#" class="glyphicon glyphicon-arrow-down' + ')"></a>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#" class="glyphicon glyphicon-arrow-down'
+ (canMoveDown ? '' : ' invisible') + '" onclick="return moveDown(' + (canMoveDown ? '' : ' invisible') + '" onclick="return moveDown('
@ -246,21 +250,18 @@ function renderQueue(playNextAt, now)
+ (canDelete ? '' : ' invisible') + '" onclick="return cancelSong(' + (canDelete ? '' : ' invisible') + '" onclick="return cancelSong('
+ song.id + ')"></a></td></tr>'); + song.id + ')"></a></td></tr>');
timeToPlay += parseInt(song.song.duration); timeToPlay += parseInt(song.song.duration);
canDeletePrevious = canDelete canDeletePrevious = canDelete;
if(playNextAt >= now) if(playNextAt >= now)
{ {
playNextAt += parseInt(song.song.duration); playNextAt += parseInt(song.song.duration);
} }
});
} }
);}
function refreshQueue() function refreshQueue() {
{
refreshing = true; refreshing = true;
$.get('/api/queue', function (result) { $.get('/api/queue', function (result) {
var now = Date.now() / 1000 | 0; var now = Date.now() / 1000 | 0;
if (timeOffset === 0) if (timeOffset === 0) {
{
// Calculate time offset with the server. // Calculate time offset with the server.
timeOffset = now - result.current_time; timeOffset = now - result.current_time;
} }
@ -268,19 +269,19 @@ function refreshQueue()
timeStarted = result.started_at; timeStarted = result.started_at;
currentSong = result.current_song; currentSong = result.current_song;
queue = result.queue; queue = result.queue;
var playNextAt = timeStarted + timeOffset + parseInt(currentSong.song.duration); infobar = result.infobar;
user_name = result.user_name;
playNextAt = timeStarted + timeOffset + parseInt(currentSong.song.duration);
var requestedBy = currentSong.requested_by; var requestedBy = currentSong.requested_by;
$('.currentsong .artist').text(currentSong.song.artist); $('.currentsong .artist').text(currentSong.song.artist);
$('.currentsong .title').text(currentSong.song.title); $('.currentsong .title').text(currentSong.song.title);
$('.currentsong .requested-by').text(requestedBy); $('.currentsong .requested-by').text(requestedBy);
if (currentSong.can_skip || canSkip) if (currentSong.can_skip || canSkip) {
{ $('#skip').removeClass('hidden');
$('#skip').addClass('glyphicon glyphicon-fast-forward');
} }
else else {
{ $('#skip').addClass('hidden');
$('#skip').removeClass('glyphicon glyphicon-fast-forward');
} }
renderQueue(playNextAt, now); renderQueue(playNextAt, now);
@ -290,21 +291,19 @@ function refreshQueue()
}); });
} }
function refreshSeconds(playNextAt, now) function refreshSeconds(playNextAt, now) {
{
if(!showTimeToPlay) { if(!showTimeToPlay) {
return; return;
} }
var timeToPlay = playNextAt - now; var timeToPlay = playNextAt - now;
times = $('.plays-at'); var times = $('.plays-at');
$.each(queue, function (id, song) { $.each(queue, function (id, song) {
$(times[id]).text(timeToPlay < 0 ? '' : timeToPlay.secondsToMMSS()); $(times[id]).text(timeToPlay < 0 ? '' : timeToPlay.secondsToMMSS());
timeToPlay += parseInt(song.song.duration); timeToPlay += parseInt(song.song.duration);
}); });
} }
function getSongs() function getSongs() {
{
var all = $('#search-all').val(); var all = $('#search-all').val();
var uploader = $('#search-uploader').val(); var uploader = $('#search-uploader').val();
var page = $('.pagenum').val(); var page = $('.pagenum').val();
@ -313,38 +312,34 @@ function getSongs()
$('#request-table tbody').empty(); $('#request-table tbody').empty();
songs = result.data; songs = result.data;
$.each(songs, function (id, song) { $.each(songs, function (id, song) {
var artist = song.artist.trim() === '' ? '?' : song.artist; var artist = (song.artist.trim() === '' ? '?' : song.artist);
var title = song.title.trim() === '' ? '?' : song.title; var title = (song.title.trim() === '' ? '?' : song.title);
$('#request-table tbody:last-child').append('<tr><td>' + artist + $('#request-table tbody:last-child').append('<tr><td>' + artist +
'</td><td><a href="#" data-song-id="' + song.id + '">' + title + '</td><td><a href="#" data-song-id="' + song.id + '">' + title +
'</a></td><td>' + (song.uploader_name ? song.uploader_name : 'Marietje') + '</a></td><td>' + ((song.uploader_name) ? song.uploader_name : 'Marietje') +
'</td><td style="text-align: right;">' + song.duration.secondsToMMSS() + '</td><td style="text-align: right;">' + song.duration.secondsToMMSS() +
'</td><td><a href="#" data-report-song-id="'+ song.id + '">⚑</a></td></tr>'); '</td><td><a href="#" data-report-song-id="'+ song.id + '">⚑</a></td></tr>');
}); });
var pageNumSelect = $('.pagenum'); var pageNumSelect = $('.pagenum');
pageNumSelect.empty(); pageNumSelect.empty();
for(var i = 1; i < result.last_page + 1; i++) for (var i = 1; i < result.last_page + 1; i++) {
{
pageNumSelect.append($("<option></option>") pageNumSelect.append($("<option></option>")
.attr("value", i) .attr("value", i)
.text(i)); .text(i));
} }
pageNumSelect.val(result.current_page); pageNumSelect.val(result.current_page);
$('.pagesize').val(result.per_page); $('.pagesize').val(result.per_page);
$('button.first').prop('disabled', result.current_page == 1); $('button.first').prop('disabled', result.current_page === 1);
$('button.prev').prop('disabled', result.current_page == 1); $('button.prev').prop('disabled', result.current_page === 1);
$('button.next').prop('disabled', result.current_page == result.last_page); $('button.next').prop('disabled', result.current_page === result.last_page);
$('button.last').prop('disabled', result.current_page == result.last_page); $('button.last').prop('disabled', result.current_page === result.last_page);
refreshingSongs = false; refreshingSongs = false;
if(requestViewOpen) { if(requestViewOpen) {
window.scrollTo(0, 0); window.scrollTo(0, 0);
} }
}); });
} }
function showRequestTable() {
function showRequestTable()
{
$('#request-button').text('Close'); $('#request-button').text('Close');
$('#queue-container').hide(); $('#queue-container').hide();
$('#request-container').removeClass('hidden'); $('#request-container').removeClass('hidden');
@ -353,8 +348,7 @@ function showRequestTable()
requestViewOpen = true; requestViewOpen = true;
} }
function hideRequestTable() function hideRequestTable() {
{
$('#request-button').text('Request'); $('#request-button').text('Request');
$('#request-container').hide(); $('#request-container').hide();
$('#queue-container').show(); $('#queue-container').show();
@ -366,7 +360,7 @@ function hideRequestTable()
if (!Date.now) { if (!Date.now) {
Date.now = function () { Date.now = function () {
return new Date().getTime(); return new Date().getTime();
} };
} }
// Edited from https://stackoverflow.com/a/6313008. // Edited from https://stackoverflow.com/a/6313008.
@ -375,17 +369,17 @@ Number.prototype.secondsToMMSS = function () {
var minutes = Math.floor((this - (hours * 3600)) / 60); var minutes = Math.floor((this - (hours * 3600)) / 60);
var seconds = this - (hours * 3600) - (minutes * 60); var seconds = this - (hours * 3600) - (minutes * 60);
var sep1 = '' var sep1 = '';
if (hours > 0) { if (hours > 0) {
hours = hours; hours = hours;
sep1 = ':'; sep1 = ':';
} else { } else {
hours = ''; hours = '';
} }
if (hours > 0 && minutes < 10) minutes = '0' + minutes; if (hours > 0 && minutes < 10) {minutes = '0' + minutes;}
if (seconds < 10) seconds = '0' + seconds; if (seconds < 10) {seconds = '0' + seconds;}
return hours + sep1 + minutes + ':' + seconds; return hours + sep1 + minutes + ':' + seconds;
} };
Number.prototype.timestampToHHMMSS = function () { Number.prototype.timestampToHHMMSS = function () {
var date = new Date(this * 1000); var date = new Date(this * 1000);
@ -403,7 +397,7 @@ Number.prototype.timestampToHHMMSS = function () {
seconds = '0' + seconds; seconds = '0' + seconds;
} }
return hours + ':' + minutes + ':' + seconds; return hours + ':' + minutes + ':' + seconds;
} };
function createAlert(type, message) { function createAlert(type, message) {
alertText = '<div class="alert alert-' + type + ' alert-dismissable">'+ alertText = '<div class="alert alert-' + type + ' alert-dismissable">'+
@ -413,5 +407,5 @@ function createAlert(type, message) {
'</button>' + '</button>' +
message + message +
'</div>'; '</div>';
$('body > div.container').prepend(alertText); $('body > div.container > div.alert-location').prepend(alertText);
} }

View File

@ -5,7 +5,6 @@ from django.utils import timezone
from songs.models import Song from songs.models import Song
class Playlist(models.Model): class Playlist(models.Model):
def __str__(self): def __str__(self):
return 'Playlist #' + str(self.id) return 'Playlist #' + str(self.id)

View File

@ -4,9 +4,47 @@
{% block title %}Queue{% endblock %} {% block title %}Queue{% endblock %}
{% block content %} {% block content %}
<h1 class="h1">Request</h1>
<button id="request-button" class="btn btn-primary">Request</button>
<nav class="navbar navbar-default navbar-fixed-top" style="top: 50px; border-top: 1px solid #bbbbbb; max-height: 50px; box-shadow: 2px 2px 4px #BBBBBB;">
<div class="container-fluid">
<ul class="navbar-nav" style="max-height: 50px; margin: 0;">
<li class="btn-toolbar nav navbar-nav" style="margin: 0;">
<button id="request-button" class="btn navbar-btn btn-primary">
Request
</button>
<div id="infobar-buttons" class="btn-group">
{% if perms.queues.can_control_volume %}
<button type="button" id="mute" class="btn navbar-btn btn-sm block-button">
<span id="mute-button-span" class="glyphicon glyphicon-volume-off"></span>
</button>
<button type="button" id="volume_down" class="btn navbar-btn btn-sm block-button">
<span id="voldown-button-span" class="glyphicon glyphicon-volume-down"></span>
</button>
<button type="button" id="volume_up" class="btn navbar-btn btn-sm block-button">
<span id="volup-button-span" class="glyphicon glyphicon-volume-up"></span>
</button>
{% endif %}
<button type="button" id="skip" class="btn navbar-btn btn-sm block-button">
<span id="skip-button-span" class="glyphicon glyphicon-fast-forward"></span>
</button>
</div>
</li>
</ul>
<ul class="nav navbar-nav navbar-right hidden-xs">
<li>
<div class="infobar">
<p class="navbar-text start-queue"></p>
<p class="navbar-text end-queue"></p>
<p class="navbar-text duration-queue"></p>
</div>
</li>
</ul>
</div>
</nav>
<br><br> <br><br>
<div class="alert-location">
</div>
<div id="request-container" class="hidden"> <div id="request-container" class="hidden">
<table id="request-table" class="table table-striped"> <table id="request-table" class="table table-striped">
<thead> <thead>
@ -19,7 +57,7 @@
</tr> </tr>
<tr> <tr>
<th colspan="2"><input id="search-all" class="search-input" type="text"></th> <th colspan="2"><input id="search-all" class="search-input" type="text"></th>
<th><input id="search-uploader" class="search-input" type="text"></th> <th colspan="3"><input id="search-uploader" class="search-input" type="text"></th>
</tr> </tr>
</thead> </thead>
<tfoot> <tfoot>
@ -39,49 +77,28 @@
</select> </select>
<select class="pagenum input-mini" title="Select page number"></select> <select class="pagenum input-mini" title="Select page number"></select>
</th> </th>
<th colspan="2"></th>
</tr> </tr>
</tfoot> </tfoot>
<tbody> <tbody>
</tbody> </tbody>
</table> </table>
</div> </div>
<div id="queue-container"> <div id="queue-container">
<h1 class="h1">
Now Playing{% if perms.queues.can_control_volume %}
<a id="mute" class="glyphicon glyphicon-volume-off" href="#"></a>{% endif %}
</h1>
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
<tr> <tr class="table-header-style">
<th class="col-md-4">Artist</th> <td class="col-md-4">Artist</td>
<th class="col-md-4">Title</th> <td class="col-md-4">Title</td>
<th class="col-md-2 hidden-xs">Requested By</th> <td class="col-md-2 hidden-xs">Requested By</td>
<th class="col-md-1 hidden-xs" style="text-align: right;">Time Left</th> <td id="timeswitch" class="col-md-1 hidden-xs text-info" >Plays In</td>
<th class="col-md-1 control-icons">Control</th> <td class="col-md-1 control-icons">Control</td>
</tr> </tr>
</thead> <tr class="currentsong" style="font-weight: bold">
<tbody>
<tr class="currentsong">
<td class="artist"></td> <td class="artist"></td>
<td class="title"></td> <td class="title"></td>
<td class="requested-by hidden-xs"></td> <td class="requested-by hidden-xs"></td>
<td class="time-left hidden-xs" style="text-align: right;"></td> <td colspan="2"></td>
<td>
<a id="skip" href="#"></a>{% if perms.queues.can_control_volume %}&nbsp;&nbsp;&nbsp;&nbsp;<a id="volume-down" class="glyphicon glyphicon-volume-down" href="#"></a>&nbsp;&nbsp;&nbsp;&nbsp;<a id="volume-up" class="glyphicon glyphicon-volume-up" href="#"></a>{% endif %}
</td>
</tr>
</tbody>
</table>
<h1 class="h1">Queue</h1>
<table class="table table-striped">
<thead>
<tr>
<th class="col-md-4">Artist</th>
<th class="col-md-4">Title</th>
<th class="col-md-2 hidden-xs">Requested By</th>
<th id="queue-time-header" class="col-md-1 hidden-xs" style="text-align: right;">Plays At</th>
<th class="col-md-1 control-icons">Control</th>
</tr> </tr>
</thead> </thead>
<tbody class="queuebody"> <tbody class="queuebody">