Browse Source

Added Playlists functionality on frontend

theflametrooper 8 năm trước cách đây
mục cha
commit
d49b9c95a1

+ 1 - 12
frontend/App.vue

@@ -56,7 +56,7 @@
 			},
 			'submitOnEnter': (cb, event) => {
 				if (event.which == 13) b(); return false;
-			},
+			}
 		},
 		ready() {
 			let _this = this;
@@ -127,17 +127,6 @@
 						break;
 				}
 			}
-			/*'joinStation': function (id) {
-				let mergedStations = this.stations.community.concat(this.stations.official);
-				this.socket.emit('stations.join', id, result => {
-					mergedStations.find(station => station.id === id).users = result.userCount;
-				});
-			},
-			'leaveStation': function () {
-				this.socket.emit('stations.leave', result => {
-					//this.stations.find(station => station.id === id).users = result.userCount;
-				});
-			}*/
 		},
 		components: { Toast, WhatIsNew, LoginModal, RegisterModal, CreateCommunityStation }
 	}

+ 152 - 0
frontend/components/Modals/EditPlaylist.vue

@@ -0,0 +1,152 @@
+<template>
+	<div class='modal is-active'>
+		<div class='modal-background'></div>
+		<div class='modal-card'>
+			<header class='modal-card-head'>
+				<p class='modal-card-title'>Editing: {{ 'Ultimate Playlist' }}</p>
+				<button class='delete' @click='$parent.toggleModal("editPlaylist")'></button>
+			</header>
+			<section class='modal-card-body'>
+				<aside class='menu'>
+					<ul class='menu-list'>
+						<li>
+							<!--repeat for each song in playlist-->
+							<a :href='' target='_blank'>Clean Bandit - Rockabye ft. Sean Paul & Anne-Marie</a>
+							<div class='controls'>
+								<a href='#' @click=''><i class='material-icons'>keyboard_arrow_down</i></a>
+								<a href='#' @click=''><i class='material-icons'>keyboard_arrow_up</i></a>
+								<a href='#' @click=''><i class='material-icons'>delete</i></a>
+							</div>
+						</li>
+					</ul>
+				</aside>
+				<br />
+				<div class='control is-grouped'>
+					<p class='control is-expanded'>
+						<input class='input' type='text' placeholder='Search for Song to add' v-model='songQuery'>
+					</p>
+					<p class='control'>
+						<a class='button is-info' @click='searchForSongs()'>Search</a>
+					</p>
+				</div>
+				<table class='table' v-if='songQueryResults.length > 0'>
+					<tbody>
+						<tr v-for='result in songQueryResults'>
+							<td>
+								<img :src='result.thumbnail' />
+							</td>
+							<td>{{ result.title }}</td>
+							<td>
+								<a class='button is-success' @click='addSongToPlaylist(result.id)'>
+									Add
+								</a>
+							</td>
+						</tr>
+					</tbody>
+				</table>
+				<div class='control is-grouped'>
+					<p class='control is-expanded'>
+						<input class='input' type='text' placeholder='YouTube Playlist URL'>
+					</p>
+					<p class='control'>
+						<a class='button is-info' @click='submitQuery()'>Import</a>
+					</p>
+				</div>
+				<h5>Edit playlist details:</h5>
+				<div class='control is-grouped'>
+					<p class='control is-expanded'>
+						<input class='input' type='text' placeholder='Playlist Display Name'>
+					</p>
+					<p class='control'>
+						<a class='button is-info' @click='renamePlaylist()'>Rename</a>
+					</p>
+				</div>
+			</section>
+			<footer class='modal-card-foot'>
+				<a class='button is-danger' @click=''>Delete Playlist</a>
+			</footer>
+		</div>
+	</div>
+</template>
+
+<script>
+	import { Toast } from 'vue-roaster';
+
+	export default {
+		data() {
+			return {
+				playlist: {},
+				songQuery: '',
+				songQueryResults: []
+			}
+		},
+		methods: {
+			searchForSongs: function () {
+				let _this = this;
+				_this.socket.emit('apis.searchYoutube', _this.querySearch, res => {
+					if (res.status == 'success') {
+						_this.songQueryResults = [];
+						for (let i = 0; i < res.data.items.length; i++) {
+							_this.songQueryResults.push({
+								id: res.data.items[i].id.videoId,
+								url: `https://www.youtube.com/watch?v=${this.id}`,
+								title: res.data.items[i].snippet.title,
+								thumbnail: res.data.items[i].snippet.thumbnails.default.url
+							});
+						}
+					} else if (res.status == 'error') Toast.methods.addToast(res.message, 3000);
+				});
+			},
+			addSongToPlaylist: function () {
+
+			},
+			addPlaylist: function () {
+
+			},
+			renamePlaylist: function () {
+
+			}
+		},
+		ready: function () {
+			let _this = this;
+			let socketInterval = setInterval(() => {
+				if (!!_this.$parent.$parent.socket) {
+					_this.socket = _this.$parent.$parent.socket;
+					// _this.$parent.playlistBeingEdited - get that playlist id from socket
+					clearInterval(socketInterval);
+				}
+			}, 100);
+		}
+	}
+</script>
+
+<style type='scss' scoped>
+	.menu { padding: 0 20px; }
+
+	.menu-list li {
+		display: flex;
+		justify-content: space-between;
+	}
+
+	.menu-list a:hover { color: #000 !important; }
+
+	li a {
+		display: flex;
+    	align-items: center;
+	}
+
+	.controls {
+		display: flex;
+
+		a {
+			display: flex;
+    		align-items: center;
+		}
+	}
+
+	.table {
+		margin-bottom: 0;
+	}
+
+	h5 { padding: 20px 0; }
+</style>

+ 83 - 0
frontend/components/Modals/createPlaylist.vue

@@ -0,0 +1,83 @@
+<template>
+	<div class='modal is-active'>
+		<div class='modal-background'></div>
+		<div class='modal-card'>
+			<header class='modal-card-head'>
+				<p class='modal-card-title'>Create Playlist</p>
+				<button class='delete' @click='$parent.toggleModal("createPlaylist")'></button>
+			</header>
+			<section class='modal-card-body'>
+				<p class='control is-expanded'>
+					<input class='input' type='text' placeholder='Playlist ID' v-model='playlist.id'>
+				</p>
+				<p class='control is-expanded'>
+					<input class='input' type='text' placeholder='Playlist Display Name' v-model='playlist.displayName'>
+				</p>
+			</section>
+			<footer class='modal-card-foot'>
+				<a class='button is-info' @click='createPlaylist()'>Create Playlist</a>
+			</footer>
+		</div>
+	</div>
+</template>
+
+<script>
+	import { Toast } from 'vue-roaster';
+
+	export default {
+		data() {
+			return {
+				playlist: {
+					id: null,
+					displayName: null
+				}
+			}
+		},
+		methods: {
+			createPlaylist: function () {
+				// socket
+				this.$parent.toggleModal("createPlaylist");
+			}
+		},
+		ready: function () {
+			let _this = this;
+			let socketInterval = setInterval(() => {
+				if (!!_this.$parent.$parent.socket) {
+					_this.socket = _this.$parent.$parent.socket;
+					clearInterval(socketInterval);
+				}
+			}, 100);
+		}
+	}
+</script>
+
+<style type='scss' scoped>
+	.menu { padding: 0 20px; }
+
+	.menu-list li {
+		display: flex;
+		justify-content: space-between;
+	}
+
+	.menu-list a:hover { color: #000 !important; }
+
+	li a {
+		display: flex;
+    	align-items: center;
+	}
+
+	.controls {
+		display: flex;
+
+		a {
+			display: flex;
+    		align-items: center;
+		}
+	}
+
+	.table {
+		margin-bottom: 0;
+	}
+
+	h5 { padding: 20px 0; }
+</style>

+ 19 - 6
frontend/components/Sidebars/Playlist.vue

@@ -3,15 +3,18 @@
 		<div class='inner-wrapper'>
 			<div class='title'>Playlists</div>
 
-			<aside class="menu">
-				<ul class="menu-list">
-					<li><a href="#">Top 40</a></li>
-					<li><a href="#">Good Mood</a></li>
-					<li><a href="#">Chills</a></li>
+			<aside class='menu'>
+				<ul class='menu-list'>
+					<li>
+						<a href='#'>Top 40</a>
+						<a href='#' @click='$parent.editPlaylist(56);'>
+							<i class='material-icons'>edit</i>
+						</a>
+					</li>
 				</ul>
 			</aside>
 
-			<a class='button create-playlist'>Create Playlist</a>
+			<a class='button create-playlist' @click='$parent.toggleModal("createPlaylist")'>Create Playlist</a>
 		</div>
 	</div>
 </template>
@@ -77,4 +80,14 @@
 	.menu { padding: 0 20px; }
 
 	.menu-list li a:hover { color: #000 !important; }
+
+	.menu-list li {
+		display: flex;
+		justify-content: space-between;
+	}
+
+	li a {
+		display: flex;
+    	align-items: center;
+	}
 </style>

+ 15 - 3
frontend/components/Station/Station.vue

@@ -2,6 +2,8 @@
 	<station-header></station-header>
 
 	<song-queue v-if='modals.addSongToQueue'></song-queue>
+	<edit-playlist v-if='modals.editPlaylist'></edit-playlist>
+	<create-playlist v-if='modals.createPlaylist'></create-playlist>
 
 	<queue-sidebar v-if='sidebars.queue'></queue-sidebar>
 	<playlist-sidebar v-if='sidebars.playlist'></playlist-sidebar>
@@ -59,6 +61,8 @@
 	import { Toast } from 'vue-roaster';
 
 	import SongQueue from '../Modals/AddSongToQueue.vue';
+	import EditPlaylist from '../Modals/EditPlaylist.vue';
+	import CreatePlaylist from '../Modals/CreatePlaylist.vue';
 
 	import QueueSidebar from '../Sidebars/Queue.vue';
 	import PlaylistSidebar from '../Sidebars/Playlist.vue';
@@ -79,20 +83,28 @@
 				liked: false,
 				disliked: false,
 				modals: {
-					addSongToQueue: false
+					addSongToQueue: false,
+					editPlaylist: false,
+					createPlaylist: false
 				},
 				sidebars: {
 					queue: false,
 					users: false,
-					playlist: false
+					playlist: true
 				},
 				noSong: false,
 				simpleSong: false
 			}
 		},
 		methods: {
+			editPlaylist: function (id) {
+				this.playlistBeingEdited = id;
+				this.toggleModal('editPlaylist');
+			},
 			toggleModal: function (type) {
 				if (type == 'addSongToQueue') this.modals.addSongToQueue = !this.modals.addSongToQueue;
+				else if (type == 'editPlaylist') this.modals.editPlaylist = !this.modals.editPlaylist;
+				else if (type == 'createPlaylist') this.modals.createPlaylist = !this.modals.createPlaylist;
 			},
 			youtubeReady: function() {
 				let local = this;
@@ -374,7 +386,7 @@
 			volume = (typeof volume === "number") ? volume : 20;
 			$("#volumeSlider").val(volume);
 		},
-		components: { StationHeader, SongQueue, QueueSidebar, PlaylistSidebar, UsersSidebar }
+		components: { StationHeader, SongQueue, EditPlaylist, CreatePlaylist, QueueSidebar, PlaylistSidebar, UsersSidebar }
 	}
 </script>