Jelajahi Sumber

Added included/excluded playlists action and playlist items

Owen Diffey 3 tahun lalu
induk
melakukan
51076092ed

+ 3 - 0
frontend/src/components/Modal.vue

@@ -91,6 +91,9 @@ p {
 	& > div {
 		display: flex;
 		flex-grow: 1;
+		div:not(:first-of-type) {
+			margin-left: 10px;
+		}
 	}
 	.right {
 		margin-left: auto;

+ 77 - 6
frontend/src/components/modals/ManageStation/Tabs/Playlists.vue

@@ -26,14 +26,15 @@
 				</button>
 			</div>
 			<div class="tab" v-show="tab === 'current'">
-				<!-- <div v-if="station.includedPlaylists.length > 0">
+				<div v-if="includedPlaylists.length > 0">
 					<playlist-item
 						:playlist="playlist"
-						v-for="(playlist, index) in station.includedPlaylists"
+						v-for="(playlist, index) in includedPlaylists"
 						:key="'key-' + index"
 					>
 						<div class="icons-group" slot="actions">
 							<i
+								@click="deselectPlaylist(playlist._id)"
 								class="material-icons stop-icon"
 								content="Stop playing songs from this playlist
 							"
@@ -58,8 +59,8 @@
 							>
 						</div>
 					</playlist-item>
-				</div> -->
-				<p class="nothing-here-text scrollable-list">
+				</div>
+				<p v-else class="nothing-here-text scrollable-list">
 					No playlists currently selected.
 				</p>
 			</div>
@@ -104,6 +105,11 @@
 						>
 							<div slot="actions">
 								<i
+									v-if="
+										station.type === 'community' &&
+											isNotSelected(playlist._id)
+									"
+									@click="selectPlaylist(playlist._id)"
 									class="material-icons play-icon"
 									:content="
 										station.partyMode
@@ -114,6 +120,11 @@
 									>play_arrow</i
 								>
 								<i
+									v-if="
+										station.type === 'community' &&
+											!isNotSelected(playlist._id)
+									"
+									@click="deselectPlaylist(playlist._id)"
 									class="material-icons stop-icon"
 									:content="
 										station.partyMode
@@ -144,7 +155,7 @@
 <script>
 import { mapActions, mapState, mapGetters } from "vuex";
 
-// import Toast from "toasters";
+import Toast from "toasters";
 import draggable from "vuedraggable";
 import PlaylistItem from "@/components/PlaylistItem.vue";
 
@@ -179,7 +190,9 @@ export default {
 		}),
 		...mapState("modals/manageStation", {
 			station: state => state.station,
-			originalStation: state => state.originalStation
+			originalStation: state => state.originalStation,
+			includedPlaylists: state => state.includedPlaylists,
+			excludedPlaylists: state => state.excludedPlaylists
 		}),
 		...mapGetters({
 			socket: "websockets/getSocket"
@@ -282,6 +295,64 @@ export default {
 			this.editPlaylist(playlistId);
 			this.openModal({ sector: "station", modal: "editPlaylist" });
 		},
+		selectPlaylist(id) {
+			if (this.station.type === "community" && this.station.partyMode) {
+				new Toast(
+					"Error: Party mode playlist selection not added yet."
+				);
+			} else {
+				this.socket.dispatch(
+					"stations.selectPrivatePlaylist",
+					this.station._id,
+					id,
+					res => {
+						if (res.status === "error") {
+							new Toast(res.message);
+						} else {
+							this.station.includedPlaylists.push(id);
+							new Toast(res.message);
+						}
+					}
+				);
+			}
+		},
+		deselectPlaylist(id) {
+			if (this.station.type === "community" && this.station.partyMode) {
+				new Toast(
+					"Error: Party mode playlist selection not added yet."
+				);
+			} else {
+				this.socket.dispatch(
+					"stations.deselectPrivatePlaylist",
+					this.station._id,
+					id,
+					res => {
+						if (res.status === "error")
+							return new Toast(res.message);
+
+						this.station.includedPlaylists.splice(
+							this.station.includedPlaylists.indexOf(id),
+							1
+						);
+
+						return new Toast(res.message);
+					}
+				);
+			}
+		},
+		isNotSelected(id) {
+			if (this.station.type === "community" && this.station.partyMode) {
+				// Party mode playlist selection not added yet
+				return true;
+			}
+			// TODO Also change this once it changes for a station
+			if (
+				this.station &&
+				this.station.includedPlaylists.indexOf(id) !== -1
+			)
+				return false;
+			return true;
+		},
 		...mapActions("station", ["updatePrivatePlaylistQueueSelected"]),
 		...mapActions("modalVisibility", ["openModal"]),
 		...mapActions("user/playlists", ["editPlaylist", "setPlaylists"])

+ 22 - 0
frontend/src/components/modals/ManageStation/Tabs/Settings.vue

@@ -143,6 +143,7 @@
 			<div class="small-section">
 				<label class="label">Station Mode</label>
 				<tippy
+					v-if="station.type === 'community'"
 					class="button-wrapper"
 					theme="addToPlaylist"
 					interactive="true"
@@ -182,10 +183,21 @@
 						Party
 					</button>
 				</tippy>
+				<div v-else class="button-wrapper">
+					<button
+						class="blue"
+						content="Can not be changed on official stations."
+						v-tippy
+					>
+						<i class="material-icons">playlist_play</i>
+						Playlist
+					</button>
+				</div>
 			</div>
 			<div v-if="!station.partyMode" class="small-section">
 				<label class="label">Play Mode</label>
 				<tippy
+					v-if="station.type === 'community'"
 					class="button-wrapper"
 					theme="addToPlaylist"
 					interactive="true"
@@ -224,6 +236,16 @@
 						Sequential
 					</button>
 				</tippy>
+				<div v-else class="button-wrapper">
+					<button
+						class="blue"
+						content="Can not be changed on official stations."
+						v-tippy
+					>
+						<i class="material-icons">shuffle</i>
+						Random
+					</button>
+				</div>
 			</div>
 			<div
 				v-if="

+ 25 - 3
frontend/src/components/modals/ManageStation/index.vue

@@ -20,7 +20,10 @@
 								Playlists
 							</button>
 							<button
-								v-if="station.type === 'community'"
+								v-if="
+									station.type === 'community' &&
+										station.partyMode
+								"
 								class="button is-default"
 								:class="{ selected: tab === 'youtube' }"
 								@click="showTab('youtube')"
@@ -30,7 +33,10 @@
 						</div>
 						<settings class="tab" v-show="tab === 'settings'" />
 						<youtube-search
-							v-if="station.type === 'community'"
+							v-if="
+								station.type === 'community' &&
+									station.partyMode
+							"
 							class="tab"
 							v-show="tab === 'youtube'"
 						/>
@@ -47,6 +53,19 @@
 			</div>
 		</template>
 		<template #footer>
+			<button
+				class="button is-primary tab-actionable-button"
+				v-if="loggedIn && station.type === 'official'"
+				@click="
+					openModal({
+						sector: 'station',
+						modal: 'requestSong'
+					})
+				"
+			>
+				<i class="material-icons icon-with-button">queue</i>
+				<span class="optional-desktop-only-text"> Request Song </span>
+			</button>
 			<div class="right">
 				<confirm @confirm="clearAndRefillStationQueue()">
 					<a class="button is-danger">
@@ -98,6 +117,9 @@ export default {
 		};
 	},
 	computed: {
+		...mapState({
+			loggedIn: state => state.user.auth.loggedIn
+		}),
 		...mapState("modals/manageStation", {
 			station: state => state.station,
 			originalStation: state => state.originalStation
@@ -164,7 +186,7 @@ export default {
 			"setExcludedPlaylists",
 			"clearStation"
 		]),
-		...mapActions("modalVisibility", ["closeModal"])
+		...mapActions("modalVisibility", ["openModal", "closeModal"])
 	}
 };
 </script>

+ 18 - 0
frontend/src/pages/Admin/tabs/Stations.vue

@@ -61,6 +61,9 @@
 							<a class="button is-info" @click="edit(station)"
 								>Edit</a
 							>
+							<a class="button is-info" @click="manage(station)"
+								>Manage</a
+							>
 							<confirm @confirm="removeStation(index)">
 								<a class="button is-danger">Remove</a>
 							</confirm>
@@ -182,6 +185,11 @@
 			:station-id="editingStationId"
 			sector="admin"
 		/>
+		<manage-station
+			v-if="modals.manageStation"
+			:station-id="editingStationId"
+			sector="admin"
+		/>
 	</div>
 </template>
 
@@ -196,6 +204,8 @@ import ws from "@/ws";
 export default {
 	components: {
 		EditStation: () => import("@/components/modals/EditStation.vue"),
+		ManageStation: () =>
+			import("@/components/modals/ManageStation/index.vue"),
 		UserIdToUsername,
 		Confirm
 	},
@@ -286,6 +296,13 @@ export default {
 				modal: "editStation"
 			});
 		},
+		manage(station) {
+			this.editingStationId = station._id;
+			this.openModal({
+				sector: "admin",
+				modal: "manageStation"
+			});
+		},
 		addGenre() {
 			const genre = this.$refs["new-genre"].value.toLowerCase().trim();
 			if (this.newStation.genres.indexOf(genre) !== -1)
@@ -333,6 +350,7 @@ export default {
 		...mapActions("modalVisibility", ["openModal"]),
 		...mapActions("admin/stations", [
 			"editStation",
+			"manageStation",
 			"loadStations",
 			"stationRemoved",
 			"stationAdded"

+ 1 - 0
frontend/src/store/modules/modalVisibility.js

@@ -23,6 +23,7 @@ const state = {
 			editUser: false,
 			editSong: false,
 			editStation: false,
+			manageStation: false,
 			editPlaylist: false,
 			viewReport: false,
 			viewPunishment: false

+ 3 - 20
frontend/src/store/modules/modals/manageStation.js

@@ -1,19 +1,16 @@
 /* eslint no-param-reassign: 0 */
 
-import Vue from "vue";
-
 export default {
 	namespaced: true,
 	state: {
 		originalStation: {},
-		station: {}
+		station: {},
+		includedPlaylists: [],
+		excludedPlaylists: []
 	},
 	getters: {},
 	actions: {
 		editStation: ({ commit }, station) => commit("editStation", station),
-		setGenres: ({ commit }, genres) => commit("setGenres", genres),
-		setBlacklistedGenres: ({ commit }, blacklistedGenres) =>
-			commit("setBlacklistedGenres", blacklistedGenres),
 		setIncludedPlaylists: ({ commit }, includedPlaylists) =>
 			commit("setIncludedPlaylists", includedPlaylists),
 		setExcludedPlaylists: ({ commit }, excludedPlaylists) =>
@@ -25,20 +22,6 @@ export default {
 			state.originalStation = JSON.parse(JSON.stringify(station));
 			state.station = JSON.parse(JSON.stringify(station));
 		},
-		setGenres(state, genres) {
-			Vue.set(
-				state.station,
-				"genres",
-				JSON.parse(JSON.stringify(genres))
-			);
-		},
-		setBlacklistedGenres(state, blacklistedGenres) {
-			Vue.set(
-				state.station,
-				"blacklistedGenres",
-				JSON.parse(JSON.stringify(blacklistedGenres))
-			);
-		},
 		setIncludedPlaylists(state, includedPlaylists) {
 			state.includedPlaylists = JSON.parse(
 				JSON.stringify(includedPlaylists)