GR-Jukebox/manage1.html
2024-08-06 20:52:02 -04:00

329 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Manage Queue</title>
<style>
body {
display: flex;
margin: 0;
padding: 0;
height: 100vh;
background-color: #0f0f0f;
}
.column {
flex: 1;
padding: 10px;
align-items: center;
text-align: center;
}
#musicQueue, #allMusic {
height: 80vh;
overflow-y: auto;
}
.queueItem {
padding: 5px;
margin: 5px;
background-color: #f0f0f0;
border-radius: 5px;
display: flex;
justify-content: space-between;
align-items: center;
}
.queueItem button {
margin-left: 10px;
}
input[type="text"] {
width: calc(100% - 22px); /* Full width minus padding and border */
padding: 10px;
box-sizing: border-box;
}
.loader {
border: 5px solid #f3f3f3; /* Light grey */
border-top: 5px solid #3498db; /* Blue */
border-radius: 50%;
width: 20px;
height: 20px;
animation: spin 2s linear infinite;
}
.musicItem {
padding: 5px;
margin: 5px;
background-color: #f0f0f0;
border-radius: 5px;
display: flex;
align-items: center;
}
.musicItem button {
margin-right: 10px; /* Adds space between the button and the title */
}
.musicItem span {
flex-grow: 1; /* Allows the title span to take up the remaining space */
text-align: left; /* Ensures text is left-aligned */
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Hide loader by default */
.hidden {
display: none;
}
h2 {
color: #999;
font-size: 3vh;
}
.progress-container {
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
height: 5vh;
width: 30vw;
}
.progress-bar {
width: 100%;
background-color: #eee;
height: 2vh;
border-radius: 1vh;
overflow: hidden;
}
.progress {
height: 2vh;
background-color: #007BFF;
width: 0%;
border-radius: 1vh;
transition: width 0.5s ease;
}
#album-art {
/*width: 200px; /* Adjust width as needed */
height: 20vh; /* Maintain aspect ratio */
width: auto;
border-radius: 1vh; /* Rounded corners */
margin-bottom: 1vh; /* Space between the image and text */
}
span{
color:#999;
font-size: 1vw;
margin: 1vw;
}
</style>
</head>
<body>
<div class="column">
<h2>Download New Song</h2>
<form id="downloadForm">
<input type="text" id="youtubeUrl" name="youtube_url" placeholder="Enter YouTube URL here" required>
<button type="button" id="downloadButton" onclick="submitDownload()">Download</button>
<div id="loader" class="loader hidden"></div>
</form>
<div>
<img id="album-art" src="mao.jpg" alt="Album Art">
<div class="progress-container">
<span id="current-time">0:00</span>
<div class="progress-bar">
<div class="progress" id="progress" style="width: 0%;"></div>
</div>
<span id="duration">4:00</span>
</div>
</div>
</div>
<div class="column" id="queueControls">
<h2>Music Queue</h2>
<!--<button onclick="skipTrack()">Skip</button>
<button onclick="toggleLoop()">Loop</button>
<button onclick="toggleShuffle()">Shuffle</button>
<button onclick="clearQueue()">Clear</button>-->
<div id="musicQueue">
<!-- Dynamically filled with JavaScript -->
</div>
</div>
<div class="column">
<h2>All Music</h2>
<input type="text" id="searchMusic" placeholder="Search music..." onkeyup="filterMusic()">
<div id="allMusic">
<!-- Dynamically filled with JavaScript -->
</div>
</div>
<script>
function skipTrack() {
// Implementation of skipping the current track
}
function toggleLoop() {
// Toggle loop mode
}
function toggleShuffle() {
// Toggle shuffle mode
}
function clearQueue() {
// Clear the entire queue
}
function playSong(songId, songTitle) {
fetch('/play', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ songId: songId, songTitle: songTitle })
})
.then(response => {
if (!response.ok) {
throw new Error('Failed to add song to queue');
}
return response.json();
})
.then(data => {
console.log('Song added to queue:', data);
})
.catch(error => console.error('Error adding song to queue:', error));
loadQueue(); // Reloads the queue after a song is added
}
function loadMusic() {
const musicList = document.getElementById('allMusic');
//musicList.innerHTML = ''; // Clear the list before populating it again
fetch('/music')
.then(response => response.json())
.then(musicFiles => {
musicList.innerHTML = '';
musicFiles.forEach(song => {
const div = document.createElement('div');
div.className = 'musicItem';
// Create a button for adding to the queue
const addButton = document.createElement('button');
addButton.textContent = 'Add to Queue';
addButton.onclick = function() { playSong(song.id,song.title); };
// Create a span to hold the song title
const titleSpan = document.createElement('span');
titleSpan.textContent = song.title;
// Append the button and title to the div
div.appendChild(addButton);
div.appendChild(titleSpan);
musicList.appendChild(div);
});
})
.catch(error => console.error('Failed to load music:', error));
}
function filterMusic() {
const search = document.getElementById('searchMusic').value.toLowerCase();
const musicItems = document.getElementById('allMusic').getElementsByClassName('musicItem');
for (let i = 0; i < musicItems.length; i++) {
let item = musicItems[i];
let text = item.textContent || item.innerText;
if (text.toLowerCase().indexOf(search) > -1) {
item.style.display = "";
} else {
item.style.display = "none";
}
}
}
function loadQueue() {
const queueElement = document.getElementById('musicQueue');
//queueElement.innerHTML = ''; // Clear the queue before loading new items
fetch('/queue')
.then(response => response.json())
.then(queue => {
queueElement.innerHTML = '';
queue.forEach(song => {
const div = document.createElement('div');
div.className = 'queueItem';
// Create a button for removing from the queue
const removeButton = document.createElement('button');
removeButton.textContent = 'Remove';
removeButton.onclick = function() { removeFromQueue(song.id); };
// Create a span to hold the song title
const titleSpan = document.createElement('span');
titleSpan.textContent = song.title;
// Append the button and title to the div
div.appendChild(removeButton);
div.appendChild(titleSpan);
queueElement.appendChild(div);
});
})
.catch(error => console.error('Failed to load queue:', error));
}
function removeFromQueue(songId) {
fetch('/remove_from_queue', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ songId: songId })
})
.then(response => {
if (!response.ok) {
throw new Error('Failed to remove song from queue');
}
loadQueue(); // Reloads the queue after removing a song
})
.catch(error => console.error('Error removing song from queue:', error));
}
function submitDownload() {
const formData = new FormData(document.getElementById('downloadForm'));
const loader = document.getElementById('loader');
const youtubeUrl = document.getElementById('youtubeUrl');
const downloadButton = document.getElementById('downloadButton');
youtubeUrl.disabled = true;
downloadButton.disabled = true;
loader.classList.remove('hidden'); // Show the loader
fetch('/download', {
method: 'POST',
body: formData
})
.then(response => {
youtubeUrl.disabled = false;
downloadButton.disabled = false;
loader.classList.add('hidden'); // Hide the loader
youtubeUrl.value = ''; // Clear the input field
if (response.ok) {
loadMusic(); // Reloads the music list after successful download
} else {
throw new Error('Failed to download song');
}
})
.catch(error => {
console.error('Error:', error);
youtubeUrl.disabled = false;
downloadButton.disabled = false;
loader.classList.add('hidden'); // Ensure loader is hidden on error
});
}
setInterval(loadQueue, 1000);
//setInterval(loadMusic, 5000);
document.addEventListener('DOMContentLoaded', loadMusic); // Ensure music loads when the page is ready
// Functionality to dynamically populate queues and handle music items could be added here.
</script>
</body>
</html>