syng/syng/static/index.html

527 lines
29 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>syng 2.0.0</title>
<link rel="stylesheet" href="css/foundation.min.css"/>
<link rel="stylesheet" href="css/app.css"/>
<link rel="stylesheet" href="css/font-awesome.css"/>
<script src="jquery-3.2.1.min.js"></script>
<script src="jquery.serialize-object.min.js"></script>
<script src="js/vendor/foundation.js"></script>
<script src="js/vendor/rivets.bundled.min.js"></script>
<script src="https://cdn.socket.io/4.5.3/socket.io.min.js"></script>
</head>
<body>
<div class="page">
<div class="row" id="main-content">
<div class="hide-for-large">
<div class="splitter">
<div class="comp-column">
<div data-tabs class="tabs" id="main-tab">
<div class="tabs-title is-active"><a href="#simplesearch"><i class="fa fa-search fa-3x"></i></a></div>
<div class="tabs-title"><a href="#queue-list" id="queue-tab"><i class="fa fa-list fa-3x"></i></a></div>
<div class="tabs-title"><a href="#recent-list"><i class="fa fa-history fa-3x"></i></a></div>
</div>
<div class="tabs-container" data-tabs-content="main-tab">
<div class="tabs-panel is-active" id="simplesearch">
<div class="vsplit">
<form id="simple-search-form" class="form">
<div class="input-group">
<input id="search-query" class="input-group-field" type="search" placeholder="Search term or YouTube link (https://www.youtube.com/watch?v=...)" name="q" />
<div class="input-group-button">
<button class="button" type="submit"><i class="fa fa-search"></i></button>
</div>
</div>
</form>
<div id="search-results" class="results">
<ul class="vertical menu" >
<li rv-each-result="results.items">
<div class="row">
<div class="columns small-10">
<span class="artist">{ result.artist }</span>
<span class="title">{ result.title }</span>
<span class="album">{ result.album }</span>
</div>
<div class="columns small-2">
<button class="button alert fright" rv-if="result.type | eq 'youtube'" rv-on-click="results.openNewTab">
<i class="fa fa-play"></i>
</button>
<button class="button fright" rv-on-click="results.addToQueue">
<i class="fa fa-plus"></i>
</button>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
<div class="tabs-panel" id="queue-list">
<div class="vsplit">
<div id="queue-list-wrapper" class="results">
<ul id="queue" class="vertical menu">
<li rv-if="queue.current" id="current">
{% if admin == True -%}
<div class="row">
<div class="columns small-9">
{%- endif %}
<div class="row">
<span class="artist">{ queue.current.artist }</span>
<span class="title">{ queue.current.title }</span>
<span class="album">{ queue.current.album }</span>
</div>
<div class="row">
<span class="singer">{ queue.current.performer }</span>
</div>
{% if admin == True -%}
</div>
<div class="columns small-3">
<div class="button-group">
<button class="button alert fright" rv-on-click="queue.abort"><i class="fa fa-step-forward"></i></button>
<button class="button alert fright" rv-on-click="queue.kill"><i class="fa fa-times"></i></button>
</div>
</div>
</div>
{%- endif %}
</li>
<li rv-each-entry="queue.queue">
{% if admin == True -%}
<div class="row">
<div class="columns small-9">
{%- endif %}
<div class="row">
<span class="artist">{ entry.artist }</span>
<span class="title">{ entry.title }</span>
<span class="album">{ entry.album }</span>
</div>
<div class="row">
<span class="singer">{ entry.performer }</span>
<span class="eta">{ entry.etamin }</span>
</div>
{% if admin == True -%}
</div>
<div class="columns small-3">
<button class="button alert fright" rv-on-click="queue.deleteFromQueue"><i class="fa fa-minus"></i></button>
</div>
</div>
{%- endif %}
</li>
{% if admin == True %}
<li>
<div class="row">
<div class="columns small-12">
<a class="button" download="queue.json" rv-href="queue.data">Save</a>
<label for="small-bulk-upload" class="button bulk-upload-label">Bulk Append</label>
<input type="file" id="small-bulk-upload" rv-on-change="queue.bulk_append" class="show-for-sr">
</div>
</div>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
<div class="tabs-panel" id="recent-list">
<div class="vsplit">
<div id="recent-list-wrapper" class="results">
<ol id="last10" class="vertical menu">
<li rv-each-entry="queue.last10">
<div class="row">
<span class="artist">{ entry.artist }</span>
<span class="title">{ entry.title }</span>
<span class="album">{ entry.album }</span>
</div>
<div class="row">
<span class="singer">{ entry.performer }</span>
</div>
</li>
</ol>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="show-for-large">
<div class="splitter">
<div class="comp-column" id="left-side">
<div class="header">Search</div>
<div id="large-simplesearch">
<div class="vsplit">
<form id="large-simple-search-form" class="form">
<div class="input-group">
<input id="large-search-query" class="input-group-field" type="search" placeholder="Search term or YouTube link (https://www.youtube.com/watch?v=...)" name="q" />
<div class="input-group-button">
<button class="button" type="submit"><i class="fa fa-search"></i></button>
</div>
<div class="input-group-button" style="padding-left: 0.25em">
<button class="button" type="button" data-open="settings-large"><i class="fa fa-sliders"></i></button>
<div class="reveal" id="settings-large" data-reveal>
<div class="grid-x">
<div class="cell small-4 medium-2">
<div class="switch">
<input class="switch-input" name="append-karaoke" id="large-append-karaoke" type="checkbox" checked="checked"> <label class="switch-paddle" for="large-append-karaoke"></label>
</div>
</div>
<div class="cell small-8 medium-4">
<label class="text-left middle" for="large-append-karaoke">Add "Karaoke" to Search</label>
</div>
<div class="cell small-4 medium-2">
<div class="switch">
<input class="switch-input" name="youtube" id="large-youtube" type="checkbox" checked="checked"> <label class="switch-paddle" for="large-youtube"></label>
</div>
</div>
<div class="cell small-8 medium-4">
<label class="text-left middle" for="large-youtube">Search YouTube</label>
</div>
<!-- {%- for channel in channels %} -->
<!-- <div class="cell small-4 medium-2"> -->
<!-- <div class="switch"> -->
<!-- <input class="switch-input" name="{{channel}}" id="large-channel-{{loop.index}}" type="checkbox" checked="checked"> <label class="switch-paddle" for="large-channel-{{loop.index}}"></label> -->
<!-- </div> -->
<!-- </div> -->
<!-- <div class="cell small-8 medium-4"> -->
<!-- <label class="text-left middle" for="large-channel-{{loop.index}}">Search {{ channel }}</label> -->
<!-- </div> -->
<!-- {%- endfor %} -->
<button class="close-button" data-close aria-label="Close modal" type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
</div>
</div>
</div>
</form>
<div id="large-search-results" class="results">
<ul class="vertical menu">
<li rv-each-result="results.items">
<div class="row">
<div class="columns small-10">
<span class="artist">{ result.artist }</span>
<span class="title">{ result.title }</span>
<span class="album">{ result.album }</span>
</div>
<div class="columns small-2">
<button class="button alert fright" rv-if="result.source | eq 'youtube'" rv-on-click="results.openNewTab">
<i class="fa fa-play"></i>
</button>
<button class="button fright" rv-on-click="results.addToQueue">
<i class="fa fa-plus"></i>
</button>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="comp-column" id="middle">
<div class="header">Queue</div>
<div id="large-queue-list">
<div class="vsplit">
<div id="large-queue-list-wrapper" class="results">
<ul id="large-queue" class="vertical menu">
<li rv-if="queue.current" id="large-current">
{% if admin == True -%}
<div class="row">
<div class="columns small-9">
{%- endif %}
<div class="row">
<span class="artist">{ queue.current.artist }</span>
<span class="title">{ queue.current.title }</span>
<span class="album">{ queue.current.album }</span>
</div>
<div class="row">
<span class="singer">{ queue.current.performer }</span>
</div>
{% if admin == True -%}
</div>
<div class="columns small-3">
<div class="button-group">
<button class="button alert fright" rv-on-click="queue.kill">
<i class="fa fa-times"></i>
</button>
<button class="button alert fright" rv-on-click="queue.abort">
<i class="fa fa-step-forward"></i>
</button>
</div>
</div>
</div>
{%- endif %}
</li>
<li {% if admin == True %} draggable="true" {% endif %} rv-each-entry="queue.queue">
{% if admin == True -%}
<div class="row">
<div class="columns small-9">
{%- endif %}
<div class="row">
<span class="artist">{ entry.artist }</span>
<span class="title">{ entry.title }</span>
<span class="album">{ entry.album }</span>
</div>
<div class="row">
<span class="singer">{ entry.performer }</span>
<span class="eta">{ entry.etamin }</span>
</div>
{% if admin == True -%}
</div>
<div class="columns small-3">
<div class="button-group">
<button class="button alert fright" rv-on-click="queue.moveup">
<i class="fa fa-arrow-circle-up"></i>
</button>
<button class="button alert fright" rv-on-click="queue.deleteFromQueue">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
</div>
{%- endif %}
</li>
{% if admin == True %}
<li>
<div class="row">
<div class="columns small-6">
<a class="button" download="queue.json" rv-href="queue.data">Save</a>
<label for="large-bulk-upload" class="button bulk-upload-label">Bulk Append</label>
<input type="file" id="large-bulk-upload" rv-on-change="queue.bulk_append" class="show-for-sr">
</div>
</div>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
</div>
<div class="comp-column" id="right-side">
<div class="header">Recent</div>
<div id="large-recent-list">
<div class="vsplit">
<div id="large-recent-list-wrapper" class="results">
<ol id="large-last10" class="vertical menu">
<li rv-each-entry="queue.last10">
<div class="row">
<span class="artist">{ entry.artist }</span>
<span class="title">{ entry.title }</span>
<span class="album">{ entry.album }</span>
</div>
<div class="row">
<span class="singer">{ entry.performer }</span>
</div>
</li>
</ol>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<script>
const socket = io();
function ytselect(event) {
console.log(event.target.value);
var ytwarning = document.getElementsById("ytwarning");
if(event.target.value === "no_channel") {
ytwarning.style.display = "list-item";
}
ytwarning.style.display = "none";
}
function getQuery() {
var query = {};
$('input').each(function() {
if(this.type == "checkbox") {
query[this.name] = this.checked;
} else {
if(this.disabled == false) {
query[this.name] = this.value;
}
}
});
return query;
}
$(document).foundation();
results = {
items : [],
openNewTab : function(event, item) {
event.preventDefault();
window.open(item.result.id, '_blank');
},
addToQueue : function(event, item) {
event.preventDefault();
var singer = prompt("Performer:");
if(singer !== null) {
// $.post('queue', JSON.stringify({'id': item.result.id, 'singer': singer, 'type': item.result.type, 'location': item.result.location}), addQueueCallback, 'json');
socket.emit("append", {"performer": singer, "source": item.result.source, "id": item.result.id});
}
}
};
queue = {
current: null,
last10: [],
queue: [],
moveup: function (event, item) {
event.preventDefault();
if (item.index === 0) {
alert("You cannot switch places with the currently playing song.");
} else {
$.ajax({
method: 'patch',
url: 'queue',
data: JSON.stringify({'action': 'move', 'param': {'src': item.index, 'dst': item.index - 1}}),
success: updateHandler,
dataType: 'json'
})
}
},
deleteFromQueue: function (event, item) {
event.preventDefault();
$.ajax({
method: 'patch',
url: 'queue',
data: JSON.stringify({'action': 'delete', 'param': {'index': item.index} }),
success: updateHandler,
dataType: 'json'
});
},
bulk_append: function (event) {
var file = event.target.files[0];
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
new_queue = JSON.parse(e.target.result);
$.post('queue', JSON.stringify(new_queue.queue), addQueueCallback, 'json');
}
})(file);
reader.readAsText(file);
},
data: "",
kill: function(event) {
event.preventDefault();
areyousure = confirm("This will kill the players process. Did you try skipping the song?");
if(areyousure === true) {
$.ajax({
method: 'patch',
url: 'queue',
data: JSON.stringify({'action': 'kill'}),
success: updateHandler,
dataType: 'json'
});
}
},
abort: function(event) {
event.preventDefault();
$.ajax({
method: 'patch',
url: 'queue',
data: JSON.stringify({'action': 'skip'}),
success: updateHandler,
dataType: 'json'
});
}
};
rivets.formatters.eq = function(value, arg) {
return value === arg;
};
if(Foundation.MediaQuery.atLeast("large")) {
$('#large-search-query').focus();
$('#search-query').get(0).disabled = true;
$('#large-search-query').get(0).disabled = false;
rivets.bind(document.getElementById("large-search-results"), {results: results});
rivets.bind(document.getElementById("large-queue"), {queue: queue});
rivets.bind(document.getElementById("large-last10"), {queue: queue});
} else {
$('#search-query').focus();
$('#large-search-query').get(0).disabled = true;
$('#search-query').get(0).disabled = false;
rivets.bind(document.getElementById("search-results"), {results: results});
rivets.bind(document.getElementById("queue"), {queue: queue});
rivets.bind(document.getElementById("last10"), {queue: queue});
}
function addQueueCallback(data) {
$("#queue-tab").click();
updateHandler(data)
}
function updateHandler(data) {
queue.queue = data['queue'];
queue.current = data['current'];
queue.last10 = data['last10'];
queue.data = "data:application/json," + (JSON.stringify({
'queue': [queue.current].concat(queue.queue)
}))
}
$("#large-simple-search-form, #simple-search-form").on("submit", function (event) {
event.preventDefault();
if ($(this).serializeObject().q.startsWith("https://www.youtube.com/")) {
results.addToQueue(event, {result: {id: $(this).serializeObject().q, type: "youtube"}});
} else {
results.items = [{title: "Loading...", artist: "Loading...", album: "Loading...", type:"temp"}];
query = {"query": $("#large-search-query").val()}
socket.emit("search", query);
}
});
$(window).on('changed.zf.mediaquery', function() {
if(Foundation.MediaQuery.atLeast("large")) {
$('#large-search-query').focus();
$('#search-query').get(0).disabled = true;
$('#large-search-query').get(0).disabled = false;
rivets.bind(document.getElementById("large-search-results"), {results: results});
rivets.bind(document.getElementById("large-queue"), {queue: queue});
rivets.bind(document.getElementById("large-last10"), {queue: queue});
} else {
$('#search-query').focus();
$('#large-search-query').get(0).disabled = true;
$('#search-query').get(0).disabled = false;
rivets.bind(document.getElementById("search-results"), {results: results});
rivets.bind(document.getElementById("queue"), {queue: queue});
rivets.bind(document.getElementById("last10"), {queue: queue});
}
});
socket.on("connect", () => {
socket.emit("register-web", {"room": "ABCD"})
})
socket.on("state", (data) => {
data['queue'] = data.slice(1);
data['current'] = data[0];
data['last10'] = [];
updateHandler(data);
});
socket.on("search-results", (data) => {
results.items = data;
});
/* $.get("queue", updateHandler);
setInterval(function() {
$.get("queue", updateHandler)
}, 2000); */
</script>
</html>