Browse Source

Merge branch 'polishing' of https://github.com/Musare/MusareNode into polishing

Kristian Vos 4 years ago
parent
commit
42bda1c6e6

+ 100 - 0
backend/logic/actions/stations.js

@@ -100,6 +100,16 @@ CacheModule.runJob("SUB", {
 	}
 });
 
+CacheModule.runJob("SUB", {
+	channel: "privatePlaylist.deselected",
+	cb: data => {
+		IOModule.runJob("EMIT_TO_ROOM", {
+			room: `station.${data.stationId}`,
+			args: ["event:privatePlaylist.deselected"]
+		});
+	}
+});
+
 CacheModule.runJob("SUB", {
 	channel: "station.pause",
 	cb: stationId => {
@@ -2207,6 +2217,96 @@ export default {
 		);
 	}),
 
+	/**
+	 * Deselects the private playlist selected in a station
+	 *
+	 * @param session
+	 * @param stationId - the station id
+	 * @param cb
+	 */
+	deselectPrivatePlaylist: isOwnerRequired(async function deselectPrivatePlaylist(session, stationId, cb) {
+		const stationModel = await DBModule.runJob(
+			"GET_MODEL",
+			{
+				modelName: "station"
+			},
+			this
+		);
+
+		async.waterfall(
+			[
+				next => {
+					StationsModule.runJob("GET_STATION", { stationId }, this)
+						.then(station => {
+							next(null, station);
+						})
+						.catch(next);
+				},
+
+				(station, next) => {
+					if (!station) return next("Station not found.");
+					if (station.type !== "community") return next("Station is not a community station.");
+					if (!station.privatePlaylist) return next("No private playlist is currently selected.");
+
+					return stationModel.updateOne(
+						{ _id: stationId },
+						{
+							$set: {
+								privatePlaylist: null,
+								currentSongIndex: 0
+							}
+						},
+						{ runValidators: true },
+						next
+					);
+				},
+
+				(res, next) => {
+					StationsModule.runJob("UPDATE_STATION", { stationId }, this)
+						.then(station => {
+							next(null, station);
+						})
+						.catch(next);
+				}
+			],
+			async (err, station) => {
+				if (err) {
+					err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
+					this.log(
+						"ERROR",
+						"STATIONS_DESELECT_PRIVATE_PLAYLIST",
+						`Deselecting private playlist for station "${stationId}" failed. "${err}"`
+					);
+					return cb({ status: "failure", message: err });
+				}
+
+				this.log(
+					"SUCCESS",
+					"STATIONS_DESELECT_PRIVATE_PLAYLIST",
+					`Deselected private playlist for station "${stationId}" successfully.`
+				);
+
+				NotificationsModule.runJob("UNSCHEDULE", {
+					name: `stations.nextSong?id${stationId}`
+				});
+
+				if (!station.partyMode) StationsModule.runJob("SKIP_STATION", { stationId });
+
+				CacheModule.runJob("PUB", {
+					channel: "privatePlaylist.deselected",
+					value: {
+						stationId
+					}
+				});
+
+				return cb({
+					status: "success",
+					message: "Successfully deselected playlist."
+				});
+			}
+		);
+	}),
+
 	favoriteStation: isLoginRequired(async function favoriteStation(session, stationId, cb) {
 		const userModel = await DBModule.runJob("GET_MODEL", { modelName: "user" }, this);
 		async.waterfall(

+ 10 - 2
frontend/src/App.vue

@@ -84,6 +84,11 @@ export default {
 
 		if (nightmode) this.enableNightMode();
 		else this.disableNightMode();
+
+		const autoSkipDisliked =
+			false || JSON.parse(localStorage.getItem("autoSkipDisliked"));
+
+		this.changeAutoSkipDisliked(autoSkipDisliked);
 	},
 	mounted() {
 		document.onkeydown = ev => {
@@ -173,7 +178,10 @@ export default {
 				.classList.remove("night-mode");
 		},
 		...mapActions("modals", ["closeCurrentModal"]),
-		...mapActions("user/preferences", ["changeNightmode"])
+		...mapActions("user/preferences", [
+			"changeNightmode",
+			"changeAutoSkipDisliked"
+		])
 	}
 };
 </script>
@@ -504,7 +512,7 @@ button.delete:focus {
 		height: 36px;
 		border-radius: 3px 0 0 3px;
 		border-right: 0;
-		border-colour: $light-grey-2;
+		border-color: $light-grey-2;
 	}
 
 	.button {

+ 26 - 7
frontend/src/components/modals/EditStation.vue

@@ -185,14 +185,10 @@
 								:key="index"
 							>
 								<div slot="actions">
-									<!-- <a
+									<a
 										class="button is-danger"
 										href="#"
-										@click="
-											togglePlaylistSelection(
-												playlist._id
-											)
-										"
+										@click="deselectPlaylist()"
 										v-if="isPlaylistSelected(playlist._id)"
 									>
 										<i
@@ -200,11 +196,12 @@
 											>stop</i
 										>
 										Stop playing
-									</a> -->
+									</a>
 									<a
 										class="button is-success"
 										href="#"
 										@click="selectPlaylist(playlist._id)"
+										v-else
 										><i
 											class="material-icons icon-with-button"
 											>play_arrow</i
@@ -577,6 +574,20 @@ export default {
 				}
 			);
 		},
+		deselectPlaylist() {
+			this.socket.emit(
+				"stations.deselectPrivatePlaylist",
+				this.station._id,
+				res => {
+					if (res.status === "failure")
+						return new Toast({
+							content: res.message,
+							timeout: 8000
+						});
+					return new Toast({ content: res.message, timeout: 4000 });
+				}
+			);
+		},
 		update() {
 			if (this.station.name !== this.editing.name) this.updateName();
 			if (this.station.displayName !== this.editing.displayName)
@@ -1263,6 +1274,14 @@ export default {
 
 #playlists {
 	overflow: auto;
+
+	.playlist:not(:last-of-type) {
+		margin-bottom: 10px;
+	}
+
+	.button {
+		width: 148px;
+	}
 }
 
 .modal-card {

+ 9 - 2
frontend/src/pages/ResetPassword.vue

@@ -75,8 +75,12 @@
 						<h2 class="content-box-title">
 							Enter the code sent to your email
 						</h2>
-						<p class="content-box-description">
-							A code has been sent to <strong>email</strong>.
+						<p
+							class="content-box-description"
+							v-if="!this.hasEmailBeenSentAlready"
+						>
+							A code has been sent to
+							<strong>{{ email }}.</strong>
 						</p>
 
 						<p class="content-box-optional-helper">
@@ -243,6 +247,7 @@ export default {
 	data() {
 		return {
 			email: "",
+			hasEmailBeenSentAlready: true,
 			code: "",
 			newPassword: "",
 			newPasswordAgain: "",
@@ -337,6 +342,8 @@ export default {
 					timeout: 8000
 				});
 
+			this.hasEmailBeenSentAlready = false;
+
 			if (this.mode === "set") {
 				return this.socket.emit("users.requestPassword", res => {
 					new Toast({ content: res.message, timeout: 8000 });

+ 29 - 3
frontend/src/pages/Settings/tabs/Preferences.vue

@@ -7,6 +7,17 @@
 				<p>Use nightmode</p>
 			</label>
 		</p>
+		<p class="control is-expanded checkbox-control">
+			<input
+				type="checkbox"
+				id="autoSkipDisliked"
+				v-model="localAutoSkipDisliked"
+			/>
+			<label for="autoSkipDisliked">
+				<span></span>
+				<p>Automatically vote to skip disliked songs</p>
+			</label>
+		</p>
 		<button class="button is-primary save-changes" @click="saveChanges()">
 			Save changes
 		</button>
@@ -19,25 +30,40 @@ import { mapState, mapActions } from "vuex";
 export default {
 	data() {
 		return {
-			localNightmode: false
+			localNightmode: false,
+			localAutoSkipDisliked: false
 		};
 	},
 	computed: mapState({
-		nightmode: state => state.user.preferences.nightmode
+		nightmode: state => state.user.preferences.nightmode,
+		autoSkipDisliked: state => state.user.preferences.autoSkipDisliked
 	}),
 	mounted() {
 		this.localNightmode = this.nightmode;
+		this.localAutoSkipDisliked = this.autoSkipDisliked;
 	},
 	methods: {
 		saveChanges() {
 			if (this.localNightmode !== this.nightmode)
 				this.changeNightmodeLocal();
+			if (this.localAutoSkipDisliked !== this.autoSkipDisliked)
+				this.changeAutoSkipDislikedLocal();
 		},
 		changeNightmodeLocal() {
 			localStorage.setItem("nightmode", this.localNightmode);
 			this.changeNightmode(this.localNightmode);
 		},
-		...mapActions("user/preferences", ["changeNightmode"])
+		changeAutoSkipDislikedLocal() {
+			localStorage.setItem(
+				"autoSkipDisliked",
+				this.localAutoSkipDisliked
+			);
+			this.changeAutoSkipDisliked(this.localAutoSkipDisliked);
+		},
+		...mapActions("user/preferences", [
+			"changeNightmode",
+			"changeAutoSkipDisliked"
+		])
 	}
 };
 </script>

+ 25 - 0
frontend/src/pages/Station/components/Sidebar/MyPlaylists.vue

@@ -15,6 +15,17 @@
 						>
 							<i class="material-icons">play_arrow</i>
 						</button>
+						<button
+							v-if="
+								station.type === 'community' &&
+									!isNotSelected(playlist._id) &&
+									!station.partyMode
+							"
+							class="button is-danger"
+							@click="deselectPlaylist()"
+						>
+							<i class="material-icons">stop</i>
+						</button>
 						<button
 							class="button is-primary"
 							@click="edit(playlist._id)"
@@ -128,6 +139,20 @@ export default {
 				}
 			);
 		},
+		deselectPlaylist() {
+			this.socket.emit(
+				"stations.deselectPrivatePlaylist",
+				this.station._id,
+				res => {
+					if (res.status === "failure")
+						return new Toast({
+							content: res.message,
+							timeout: 8000
+						});
+					return new Toast({ content: res.message, timeout: 4000 });
+				}
+			);
+		},
 		isNotSelected(id) {
 			// TODO Also change this once it changes for a station
 			if (this.station && this.station.privatePlaylist === id)

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

@@ -484,7 +484,10 @@ export default {
 							if (this.currentSong.songId === song.songId) {
 								this.liked = song.liked;
 								this.disliked = song.disliked;
-								if (song.disliked === true)
+								if (
+									this.autoSkipDisliked &&
+									song.disliked === true
+								)
 									this.voteSkipStation();
 							}
 						}
@@ -586,6 +589,12 @@ export default {
 				}
 			});
 
+			this.socket.on("event:privatePlaylist.deselected", () => {
+				if (this.station.type === "community") {
+					this.station.privatePlaylist = null;
+				}
+			});
+
 			this.socket.on("event:partyMode.updated", partyMode => {
 				if (this.station.type === "community") {
 					this.station.partyMode = partyMode;

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

@@ -217,16 +217,23 @@ const modules = {
 	preferences: {
 		namespaced: true,
 		state: {
-			nightmode: true
+			nightmode: true,
+			autoSkipDisliked: true
 		},
 		actions: {
 			changeNightmode: ({ commit }, nightmode) => {
 				commit("changeNightmode", nightmode);
+			},
+			changeAutoSkipDisliked: ({ commit }, autoSkipDisliked) => {
+				commit("changeAutoSkipDisliked", autoSkipDisliked);
 			}
 		},
 		mutations: {
 			changeNightmode(state, nightmode) {
 				state.nightmode = nightmode;
+			},
+			changeAutoSkipDisliked(state, autoSkipDisliked) {
+				state.autoSkipDisliked = autoSkipDisliked;
 			}
 		}
 	}