Browse Source

feat(AddToPlaylist): create-playlist modal can be opened from dropdown

Signed-off-by: Jonathan <theflametrooper@gmail.com>
Jonathan 3 years ago
parent
commit
a59a2723ea

+ 4 - 0
frontend/src/App.vue

@@ -10,6 +10,7 @@
 			<what-is-new v-show="modals.whatIsNew" />
 			<login-modal v-if="modals.login" />
 			<register-modal v-if="modals.register" />
+			<create-playlist-modal v-if="modals.createPlaylist" />
 		</div>
 	</div>
 </template>
@@ -34,6 +35,9 @@ export default {
 		RegisterModal: defineAsyncComponent(() =>
 			import("@/components/modals/Register.vue")
 		),
+		CreatePlaylistModal: defineAsyncComponent(() =>
+			import("@/components/modals/CreatePlaylist.vue")
+		),
 		Banned: defineAsyncComponent(() => import("@/pages/Banned.vue"))
 	},
 	replace: false,

+ 38 - 18
frontend/src/components/AddToPlaylistDropdown.vue

@@ -5,6 +5,7 @@
 		:interactive="true"
 		:placement="placement"
 		theme="addToPlaylist"
+		ref="dropdown"
 		trigger="click"
 		append-to="parent"
 		@show="
@@ -48,6 +49,17 @@
 				</button>
 			</div>
 			<p v-else>You haven't created any playlists.</p>
+
+			<button
+				id="create-playlist"
+				class="button is-primary"
+				@click="createPlaylist()"
+			>
+				<i class="material-icons icon-with-button">
+					edit
+				</i>
+				Create Playlist
+			</button>
 		</template>
 	</tippy>
 </template>
@@ -74,15 +86,10 @@ export default {
 		...mapState({
 			fetchedPlaylists: state => state.user.playlists.fetchedPlaylists
 		}),
-		playlists: {
-			get() {
-				return this.$store.state.user.playlists.playlists.filter(
-					playlist => playlist.isUserModifiable
-				);
-			},
-			set(playlists) {
-				this.$store.commit("user/playlists/setPlaylists", playlists);
-			}
+		playlists() {
+			return this.$store.state.user.playlists.playlists.filter(
+				playlist => playlist.isUserModifiable
+			);
 		}
 	},
 	mounted() {
@@ -94,19 +101,13 @@ export default {
 
 		this.socket.on(
 			"event:playlist.created",
-			res => this.playlists.push(res.data.playlist),
+			res => this.addPlaylist(res.data.playlist),
 			{ replaceable: true }
 		);
 
 		this.socket.on(
 			"event:playlist.deleted",
-			res => {
-				this.playlists.forEach((playlist, index) => {
-					if (playlist._id === res.data.playlistId) {
-						this.playlists.splice(index, 1);
-					}
-				});
-			},
+			res => this.removePlaylist(res.data.playlistId),
 			{ replaceable: true }
 		);
 
@@ -149,7 +150,22 @@ export default {
 				-1
 			);
 		},
-		...mapActions("user/playlists", ["setPlaylists"])
+		createPlaylist() {
+			this.$refs.dropdown.tippy.setProps({
+				zIndex: 0,
+				hideOnClick: false
+			});
+
+			window.addToPlaylistDropdown = this.$refs.dropdown;
+
+			this.openModal("createPlaylist");
+		},
+		...mapActions("user/playlists", [
+			"setPlaylists",
+			"addPlaylist",
+			"removePlaylist"
+		]),
+		...mapActions("modalVisibility", ["openModal"])
 	}
 };
 </script>
@@ -158,4 +174,8 @@ export default {
 .nav-dropdown-items button .control {
 	margin-bottom: 0 !important;
 }
+
+#create-playlist {
+	margin-top: 10px;
+}
 </style>

+ 14 - 2
frontend/src/components/modals/CreatePlaylist.vue

@@ -53,6 +53,15 @@ export default {
 	computed: mapGetters({
 		socket: "websockets/getSocket"
 	}),
+	unmounted() {
+		if (window.addToPlaylistDropdown)
+			window.addToPlaylistDropdown.tippy.setProps({
+				zIndex: 9999,
+				hideOnClick: true
+			});
+
+		window.addToPlaylistDropdown = null;
+	},
 	methods: {
 		createPlaylist() {
 			const { displayName } = this.playlist;
@@ -73,9 +82,12 @@ export default {
 					new Toast(res.message);
 
 					if (res.status === "success") {
+						if (!window.addToPlaylistDropdown) {
+							this.editPlaylist(res.data.playlistId);
+							this.openModal("editPlaylist");
+						}
+
 						this.closeModal("createPlaylist");
-						this.editPlaylist(res.data.playlistId);
-						this.openModal("editPlaylist");
 					}
 				}
 			);

+ 17 - 24
frontend/src/mixins/SortablePlaylists.vue

@@ -1,5 +1,5 @@
 <script>
-import { mapState } from "vuex";
+import { mapState, mapActions } from "vuex";
 import Toast from "toasters";
 import draggable from "vuedraggable";
 
@@ -14,16 +14,9 @@ export default {
 	computed: {
 		...mapState({
 			station: state => state.station.station,
-			myUserId: state => state.user.auth.userId
+			myUserId: state => state.user.auth.userId,
+			playlists: state => state.user.playlists.playlists
 		}),
-		playlists: {
-			get() {
-				return this.$store.state.user.playlists.playlists;
-			},
-			set(playlists) {
-				this.$store.commit("user/playlists/setPlaylists", playlists);
-			}
-		},
 		dragOptions() {
 			return {
 				animation: 200,
@@ -36,19 +29,13 @@ export default {
 	mounted() {
 		this.socket.on(
 			"event:playlist.created",
-			res => this.playlists.push(res.data.playlist),
+			res => this.addPlaylist(res.data.playlist),
 			{ replaceable: true }
 		);
 
 		this.socket.on(
 			"event:playlist.deleted",
-			res => {
-				this.playlists.forEach((playlist, index) => {
-					if (playlist._id === res.data.playlistId) {
-						this.playlists.splice(index, 1);
-					}
-				});
-			},
+			res => this.removePlaylist(res.data.playlistId),
 			{ replaceable: true }
 		);
 
@@ -67,13 +54,18 @@ export default {
 		this.socket.on(
 			"event:playlist.song.removed",
 			res => {
-				this.playlists.forEach((playlist, index) => {
+				this.playlists.forEach((playlist, playlistIndex) => {
 					if (playlist._id === res.data.playlistId) {
-						this.playlists[index].songs.forEach((song, index2) => {
-							if (song.youtubeId === res.data.youtubeId) {
-								this.playlists[index].songs.splice(index2, 1);
+						this.playlists[playlistIndex].songs.forEach(
+							(song, songIndex) => {
+								if (song.youtubeId === res.data.youtubeId) {
+									this.playlists[playlistIndex].songs.splice(
+										songIndex,
+										1
+									);
+								}
 							}
-						});
+						);
 					}
 				});
 			},
@@ -150,7 +142,8 @@ export default {
 					return new Toast(res.message);
 				}
 			);
-		}
+		},
+		...mapActions("user/playlists", ["addPlaylist", "removePlaylist"])
 	}
 };
 </script>

+ 2 - 1
frontend/src/pages/Station/index.vue

@@ -447,8 +447,9 @@
 													>
 														<i
 															class="material-icons"
-															>playlist_add</i
 														>
+															playlist_add
+														</i>
 													</button>
 													<button
 														class="button"

+ 14 - 1
frontend/src/store/modules/user.js

@@ -209,7 +209,11 @@ const modules = {
 		actions: {
 			editPlaylist: ({ commit }, id) => commit("editPlaylist", id),
 			setPlaylists: ({ commit }, playlists) =>
-				commit("setPlaylists", playlists)
+				commit("setPlaylists", playlists),
+			addPlaylist: ({ commit }, playlist) =>
+				commit("addPlaylist", playlist),
+			removePlaylist: ({ commit }, playlistId) =>
+				commit("removePlaylist", playlistId)
 		},
 		mutations: {
 			editPlaylist(state, id) {
@@ -218,6 +222,15 @@ const modules = {
 			setPlaylists(state, playlists) {
 				state.fetchedPlaylists = true;
 				state.playlists = playlists;
+			},
+			addPlaylist(state, playlist) {
+				state.playlists.push(playlist);
+			},
+			removePlaylist(state, playlistId) {
+				state.playlists.forEach((playlist, index) => {
+					if (playlist._id === playlistId)
+						state.playlists.splice(index, 1);
+				});
 			}
 		}
 	},