Bladeren bron

Basically finished private playlists for now.

KrisVos130 8 jaren geleden
bovenliggende
commit
608a985d1c

+ 84 - 26
backend/logic/actions/playlists.js

@@ -9,6 +9,50 @@ const async = require('async');
 const playlists = require('../playlists');
 const songs = require('../songs');
 
+cache.sub('playlist.create', playlistId => {
+	playlists.getPlaylist(playlistId, (err, playlist) => {
+		if (!err) {
+			utils.socketsFromUser(playlist.createdBy, (sockets) => {
+				sockets.forEach((socket) => {
+					socket.emit('event:playlist.create', playlist);
+				});
+			});
+		}
+	});
+});
+
+cache.sub('playlist.delete', res => {
+	utils.socketsFromUser(res.userId, (sockets) => {
+		sockets.forEach((socket) => {
+			socket.emit('event:playlist.delete', res.playlistId);
+		});
+	});
+});
+
+cache.sub('playlist.addSong', res => {
+	utils.socketsFromUser(res.userId, (sockets) => {
+		sockets.forEach((socket) => {
+			socket.emit('event:playlist.addSong', {playlistId: res.playlistId, song: res.song});
+		});
+	});
+});
+
+cache.sub('playlist.removeSong', res => {
+	utils.socketsFromUser(res.userId, (sockets) => {
+		sockets.forEach((socket) => {
+			socket.emit('event:playlist.removeSong', {playlistId: res.playlistId, songId: res.songId});
+		});
+	});
+});
+
+cache.sub('playlist.updateDisplayName', res => {
+	utils.socketsFromUser(res.userId, (sockets) => {
+		sockets.forEach((socket) => {
+			socket.emit('event:playlist.updateDisplayName', {playlistId: res.playlistId, displayName: res.displayName});
+		});
+	});
+});
+
 let lib = {
 
 	indexForUser: hooks.loginRequired((session, cb, userId) => {
@@ -40,7 +84,7 @@ let lib = {
 
 		], (err, playlist) => {
 			if (err) return cb({ 'status': 'failure', 'message': 'Something went wrong'});
-			cache.pub('playlist.create', data._id);
+			cache.pub('playlist.create', playlist._id);
 			return cb({ 'status': 'success', 'message': 'Successfully created playlist' });
 		});
 	}),
@@ -68,6 +112,20 @@ let lib = {
 
 	addSongToPlaylist: hooks.loginRequired((session, songId, playlistId, cb, userId) => {
 		async.waterfall([
+			(next) => {
+				playlists.getPlaylist(playlistId, (err, playlist) => {
+					if (err || !playlist || playlist.createdBy !== userId) return next('Something went wrong when trying to get the playlist.');
+
+					let found = false;
+					playlist.songs.forEach((song) => {
+						if (songId === song._id) {
+							found = true;
+						}
+					});
+					if (found) return next('That song is already in the playlist.');
+					return next(null);
+				});
+			},
 			(next) => {
 				songs.getSong(songId, (err, song) => {
 					if (err) {
@@ -84,32 +142,28 @@ let lib = {
 				});
 			},
 			(newSong, next) => {
-				playlists.getPlaylist(_id, (err, playlist) => {
-					if (err || !playlist || playlist.createdBy !== userId) return next('Something went wrong when trying to get the playlist.');
-
-					if (Array.isArray(playlist.songs)) {
-						playlist.songs.push(newSong);
-						playlist.save(err => {
-							if (err) {
-								console.error(err);
-								return next('Failed to add song to playlist');
-							}
-
-							playlists.updatePlaylist(_id, () => {
-								next(null, playlist);
-							});
-						});
+				db.models.playlist.update({_id: playlistId}, {$push: {songs: newSong}}, (err) => {
+					if (err) {
+						console.error(err);
+						return next('Failed to add song to playlist');
 					}
+
+					playlists.updatePlaylist(playlistId, (err, playlist) => {
+						next(err, playlist, newSong);
+					});
 				});
 			}
 		],
-		(err, playlist) => {
+		(err, playlist, newSong) => {
 			if (err) return cb({ status: 'error', message: err });
-			else if (playlist.songs) return cb({ status: 'success', message: 'Song has been successfully added to the playlist', data: playlist.songs });
+			else if (playlist.songs) {
+				cache.pub('playlist.addSong', {playlistId: playlist._id, song: newSong, userId: userId});
+				return cb({ status: 'success', message: 'Song has been successfully added to the playlist', data: playlist.songs });
+			}
 		});
 	}),
 	
-	addSetToPlaylist: hooks.loginRequired((session, url, playlistId, cb, userId) => {
+	/*addSetToPlaylist: hooks.loginRequired((session, url, playlistId, cb, userId) => {
 		async.waterfall([
 			(next) => {
 				utils.getPlaylistFromYouTube(url, songs => {
@@ -123,7 +177,7 @@ let lib = {
 				next(null);
 			},
 			(next) => {
-				playlists.getPlaylist(_id, (err, playlist) => {
+				playlists.getPlaylist(playlistId, (err, playlist) => {
 					if (err || !playlist || playlist.createdBy !== userId) return next('Something went wrong while trying to get the playlist.');
 
 					next(null, playlist);
@@ -134,7 +188,7 @@ let lib = {
 			if (err) return cb({ status: 'failure', message: err });
 			else if (playlist.songs) return cb({ status: 'success', message: 'Playlist has been successfully added', data: playlist.songs });
 		});
-	}),
+	}),*/
 
 
 	removeSongFromPlaylist: hooks.loginRequired((session, songId, playlistId, cb, userId) => {
@@ -145,13 +199,15 @@ let lib = {
 				if (playlist.songs[z]._id == songId) playlist.songs.shift(playlist.songs[z]);
 			}
 
-			db.models.playlist.update({_id: playlistId}, {$pull: {_id: songId}}, (err) => {
+			db.models.playlist.update({_id: playlistId}, {$pull: {songs: {_id: songId}}}, (err) => {
 				if (err) {
 					console.error(err);
 					return cb({ status: 'failure', message: 'Something went wrong when saving the playlist.'});
 				}
-
-				return cb({ status: 'success', message: 'Song has been successfully removed from playlist', data: playlist.songs });
+				playlists.updatePlaylist(playlistId, (err, playlist) => {
+					cache.pub('playlist.removeSong', {playlistId: playlist._id, songId: songId, userId: userId});
+					return cb({ status: 'success', message: 'Song has been successfully removed from playlist', data: playlist.songs });
+				});
 			});
 		});
 	}),
@@ -161,10 +217,11 @@ let lib = {
 			if (err) return cb({ status: 'failure', message: 'Something went wrong when saving the playlist.'});
 			playlists.updatePlaylist(_id, (err) => {
 				if (err) return cb({ status: 'failure', message: err});
+				cache.pub('playlist.updateDisplayName', {playlistId: _id, displayName: displayName, userId: userId});
 				return cb({ status: 'success', message: 'Playlist has been successfully updated' });
 			})
 		});
-	}),
+	}),/*
 
 	promoteSong: hooks.loginRequired((session, playlistId, fromIndex, cb, userId) => {
 		db.models.playlist.findOne({ _id: playlistId }, (err, playlist) => {
@@ -210,12 +267,13 @@ let lib = {
 
 			});
 		});
-	}),
+	}),*/
 
 	remove: hooks.loginRequired((session, _id, cb, userId) => {
 		db.models.playlist.remove({ _id, createdBy: userId }).exec(err => {
 			if (err) return cb({ status: 'failure', message: 'Something went wrong when removing the playlist.'});
 			cache.hdel('playlists', _id, () => {
+				cache.pub('playlist.delete', {userId: userId, playlistId: _id});
 				return cb({ status: 'success', message: 'Playlist successfully removed' });
 			});
 		});

+ 4 - 1
backend/logic/playlists.js

@@ -51,7 +51,10 @@ module.exports = {
 
 			(playlist, next) => {
 				if (!playlist) return next('Playlist not found');
-				cache.hset('playlists', _id, playlist, next);
+				cache.hset('playlists', _id, playlist, (err) => {
+					if (err) return next(err);
+					return next(null, playlist);
+				});
 			}
 
 		], (err, playlist) => {

+ 4 - 1
backend/logic/songs.js

@@ -57,7 +57,10 @@ module.exports = {
 			(song, next) => {
 				if (!song) return next('Song not found.');
 
-				cache.hset('songs', _id, song, next);
+				cache.hset('songs', _id, song, (err) => {
+					if (err) return next(err);
+					return next(null, song);
+				});
 			}
 
 		], (err, song) => {

+ 31 - 13
frontend/components/Modals/Playlists/Edit.vue

@@ -7,19 +7,19 @@
 				<button class='delete' @click='$parent.toggleModal("editPlaylist")'></button>
 			</header>
 			<section class='modal-card-body'>
-				<aside class='menu' v-if='playlist.songs.length > 0'>
+				<aside class='menu' v-if='playlist.songs && playlist.songs.length > 0'>
 					<ul class='menu-list'>
 						<li v-for='song in playlist.songs' track-by='$index'>
-							<a :href='' target='_blank'>{{ song.title }} - {{ song.artists.join(', ') }}</a>
+							<a :href='' target='_blank'>{{ song.title }}</a>
 							<div class='controls'>
-								<a href='#'>
+								<!--a href='#'>
 									<i class='material-icons' v-if='playlist.songs[0] !== song' @click='promoteSong($index)'>keyboard_arrow_up</i>
 									<i class='material-icons' style='opacity: 0' v-else>error</i>
 								</a>
-								<a href='#' @click=''>
+								<a href='#'>
 									<i class='material-icons' v-if='playlist.songs.length - 1 !== $index' @click='demoteSong($index)'>keyboard_arrow_down</i>
 									<i class='material-icons' style='opacity: 0' v-else>error</i>
-								</a>
+								</a-->
 								<a href='#' @click='removeSongFromPlaylist(song._id)'><i class='material-icons'>delete</i></a>
 							</div>
 						</li>
@@ -49,14 +49,14 @@
 						</tr>
 					</tbody>
 				</table>
-				<div class='control is-grouped'>
+				<!--div class='control is-grouped'>
 					<p class='control is-expanded'>
 						<input class='input' type='text' placeholder='YouTube Playlist URL' v-model='importQuery'>
 					</p>
 					<p class='control'>
 						<a class='button is-info' @click='importPlaylist()'>Import</a>
 					</p>
-				</div>
+				</div-->
 				<h5>Edit playlist details:</h5>
 				<div class='control is-grouped'>
 					<p class='control is-expanded'>
@@ -106,22 +106,20 @@
 				_this.socket.emit('playlists.addSongToPlaylist', id, _this.playlist._id, res => {
 					if (res.status == 'success') {
 						Toast.methods.addToast(res.message, 3000);
-						_this.playlist.songs = res.data;
 					}
 				});
 			},
-			importPlaylist: function () {
+			/*importPlaylist: function () {
 				let _this = this;
 				this.socket.emit('playlists.addSetToPlaylist', _this.importQuery, _this.playlist._id, res => {
 					if (res.status == 'success') _this.playlist.songs = res.data;
 				});
-			},
+			},*/
 			removeSongFromPlaylist: function (id) {
 				let _this = this;
 				this.socket.emit('playlists.removeSongFromPlaylist', id, _this.playlist._id, res => {
 					if (res.status == 'success') {
 						Toast.methods.addToast(res.message, 3000);
-						_this.playlist.songs = res.data;
 					}
 				});
 			},
@@ -138,7 +136,7 @@
 						_this.$parent.toggleModal('editPlaylist');
 					}
 				});
-			},
+			},/*
 			promoteSong: function (fromIndex) {
 				let _this = this;
 				_this.socket.emit('playlists.promoteSong', _this.playlist._id, fromIndex, res => {
@@ -150,7 +148,7 @@
 				_this.socket.emit('playlists.demoteSong', _this.playlist._id, fromIndex, res => {
 					if (res.status == 'success') _this.$set('playlist.songs', res.data); // bug: v-for is not updating
 				});
-			}
+			}*/
 		},
 		ready: function () {
 			let _this = this;
@@ -160,6 +158,26 @@
 					_this.socket.emit('playlists.getPlaylist', _this.$parent.playlistBeingEdited, res => {
 						if (res.status == 'success') _this.playlist = res.data; _this.playlist.oldId = res.data._id;
 					});
+					_this.socket.on('event:playlist.addSong', (data) => {
+						if (_this.playlist._id === data.playlistId) {
+							console.log("PUSH!");
+							_this.playlist.songs.push(data.song);
+						}
+					});
+					_this.socket.on('event:playlist.removeSong', (data) => {
+						if (_this.playlist._id === data.playlistId) {
+							_this.playlist.songs.forEach((song, index) => {
+								if (song._id === data.songId) {
+									_this.playlist.songs.splice(index, 1);
+								}
+							});
+						}
+					});
+					_this.socket.on('event:playlist.updateDisplayName', (data) => {
+						if (_this.playlist._id === data.playlistId) {
+							_this.playlist.displayName = data.displayName;
+						}
+					});
 					clearInterval(socketInterval);
 				}
 			}, 100);

+ 45 - 2
frontend/components/Sidebars/Playlist.vue

@@ -9,7 +9,7 @@
 						<a href='#'>{{ playlist.displayName }}</a>
 						<!--Will play playlist in community station Kris-->
 						<div class='icons-group'>
-							<a href='#' @click='selectPlaylist(playlist._id)' v-if="$parent.station && !$parent.station.privatePlaylist === playlist._id">
+							<a href='#' @click='selectPlaylist(playlist._id)' v-if="isNotSelected(playlist._id)">
 								<i class='material-icons'>play_arrow</i>
 							</a>
 							<a href='#' @click='editPlaylist(playlist._id)'>
@@ -29,6 +29,7 @@
 
 <script>
 	import { Toast } from 'vue-roaster';
+	import { Edit } from '../Modals/Playlists/Edit.vue';
 
 	export default {
 		data() {
@@ -45,6 +46,13 @@
 					if (res.status === 'failure') return Toast.methods.addToast(res.message, 8000);
 					Toast.methods.addToast(res.message, 4000);
 				});
+			},
+			isNotSelected: function(id) {
+				let _this = this;
+				console.log(_this.$parent.station);
+				//TODO Also change this once it changes for a station
+				if (_this.$parent.station && _this.$parent.station.privatePlaylist === id) return false;
+				return true;
 			}
 		},
 		ready: function () {
@@ -53,9 +61,44 @@
 			let socketInterval = setInterval(() => {
 				if (!!_this.$parent.$parent.socket) {
 					_this.socket = _this.$parent.$parent.socket;
-					_this.socket.emit('playlists.indexForUser', _this.$parent.$parent.username, res => {
+					_this.socket.emit('playlists.indexForUser', res => {
 						if (res.status == 'success') _this.playlists = res.data;
 					});
+					_this.socket.on('event:playlist.create', (playlist) => {
+						_this.playlists.push(playlist);
+					});
+					_this.socket.on('event:playlist.delete', (playlistId) => {
+						_this.playlists.forEach((playlist, index) => {
+							if (playlist._id === playlistId) {
+								_this.playlists.splice(index, 1);
+							}
+						});
+					});
+					_this.socket.on('event:playlist.addSong', (data) => {
+						_this.playlists.forEach((playlist, index) => {
+							if (playlist._id === data.playlistId) {
+								_this.playlists[index].songs.push(data.song);
+							}
+						});
+					});
+					_this.socket.on('event:playlist.removeSong', (data) => {
+						_this.playlists.forEach((playlist, index) => {
+							if (playlist._id === data.playlistId) {
+								_this.playlists[index].songs.forEach((song, index2) => {
+									if (song._id === data.songId) {
+										_this.playlists[index].songs.splice(index2, 1);
+									}
+								});
+							}
+						});
+					});
+					_this.socket.on('event:playlist.updateDisplayName', (data) => {
+						_this.playlists.forEach((playlist, index) => {
+							if (playlist._id === data.playlistId) {
+								_this.playlists[index].displayName = data.displayName;
+							}
+						});
+					});
 					clearInterval(socketInterval);
 				}
 			}, 100);