Selaa lähdekoodia

refactor: Replaced create official station form with updated createStation modal

Owen Diffey 3 vuotta sitten
vanhempi
commit
0203863290

+ 64 - 229
backend/logic/actions/stations.js

@@ -2600,242 +2600,84 @@ export default {
 					);
 				},
 
-				// eslint-disable-next-line consistent-return
 				(station, next) => {
 					this.log(station);
 
 					if (station) return next("A station with that name or display name already exists.");
-					const { name, displayName, description, /* playlist, */ type, genres, blacklistedGenres } = data;
-					const stationId = mongoose.Types.ObjectId();
 
-					if (type === "official") {
+					if (blacklist.indexOf(data.name) !== -1)
+						return next("That name is blacklisted. Please use a different name.");
+
+					if (data.type === "official") {
 						return userModel.findOne({ _id: session.userId }, (err, user) => {
 							if (err) return next(err);
 							if (!user) return next("User not found.");
 							if (user.role !== "admin") return next("Admin required.");
-
-							return async.waterfall(
-								[
-									next => {
-										const playlists = [];
-										async.eachLimit(
-											genres,
-											1,
-											(genre, next) => {
-												PlaylistsModule.runJob(
-													"GET_GENRE_PLAYLIST",
-													{ genre, includeSongs: false },
-													this
-												)
-													.then(response => {
-														playlists.push(response.playlist);
-														next();
-													})
-													.catch(err => {
-														next(
-															`An error occurred when trying to get genre playlist for genre ${genre}. Error: ${err}.`
-														);
-													});
-											},
-											err => {
-												next(
-													err,
-													playlists.map(playlist => playlist._id.toString())
-												);
-											}
-										);
-									},
-
-									(genrePlaylistIds, next) => {
-										const playlists = [];
-										async.eachLimit(
-											blacklistedGenres,
-											1,
-											(genre, next) => {
-												PlaylistsModule.runJob(
-													"GET_GENRE_PLAYLIST",
-													{ genre, includeSongs: false },
-													this
-												)
-													.then(response => {
-														playlists.push(response.playlist);
-														next();
-													})
-													.catch(err => {
-														next(
-															`An error occurred when trying to get genre playlist for genre ${genre}. Error: ${err}.`
-														);
-													});
-											},
-											err => {
-												next(
-													err,
-													genrePlaylistIds,
-													playlists.map(playlist => playlist._id.toString())
-												);
-											}
-										);
-									},
-
-									(genrePlaylistIds, blacklistedGenrePlaylistIds, next) => {
-										const duplicateGenre =
-											genrePlaylistIds.length !== new Set(genrePlaylistIds).size;
-										const duplicateBlacklistedGenre =
-											genrePlaylistIds.length !== new Set(genrePlaylistIds).size;
-										const duplicateCross =
-											genrePlaylistIds.length + blacklistedGenrePlaylistIds.length !==
-											new Set([...genrePlaylistIds, ...blacklistedGenrePlaylistIds]).size;
-										if (duplicateGenre)
-											return next("You cannot have the same genre included twice.");
-										if (duplicateBlacklistedGenre)
-											return next("You cannot have the same blacklisted genre included twice.");
-										if (duplicateCross)
-											return next(
-												"You cannot have the same genre included and blacklisted at the same time."
-											);
-										return next(null, genrePlaylistIds, blacklistedGenrePlaylistIds);
-									}
-								],
-								(err, genrePlaylistIds, blacklistedGenrePlaylistIds) => {
-									if (err) return next(err);
-									return playlistModel.create(
-										{
-											isUserModifiable: false,
-											displayName: `Station - ${displayName}`,
-											songs: [],
-											createdBy: "Musare",
-											createdFor: `${stationId}`,
-											createdAt: Date.now(),
-											type: "station"
-										},
-
-										(err, playlist) => {
-											if (err) next(err);
-											else {
-												stationModel.create(
-													{
-														_id: stationId,
-														name,
-														displayName,
-														description,
-														type,
-														privacy: "private",
-														playlist: playlist._id,
-														currentSong: null,
-														partyMode: false,
-														playMode: "random"
-													},
-													(err, station) => {
-														next(
-															err,
-															station,
-															genrePlaylistIds,
-															blacklistedGenrePlaylistIds
-														);
-													}
-												);
-											}
-										}
-									);
-								}
-							);
+							return next();
 						});
 					}
-					if (type === "community") {
-						if (blacklist.indexOf(name) !== -1)
-							return next("That name is blacklisted. Please use a different name.");
-						return playlistModel.create(
-							{
-								isUserModifiable: false,
-								displayName: `Station - ${name}`,
-								songs: [],
-								createdBy: session.userId,
-								createdFor: `${stationId}`,
-								createdAt: Date.now(),
-								type: "station"
-							},
-
-							(err, playlist) => {
-								if (err) next(err);
-								else {
-									stationModel.create(
-										{
-											_id: stationId,
-											name,
-											displayName,
-											description,
-											playlist: playlist._id,
-											type,
-											privacy: "private",
-											owner: session.userId,
-											queue: [],
-											currentSong: null,
-											partyMode: true,
-											playMode: "random"
-										},
-										(err, station) => {
-											next(err, station, null, null);
-										}
-									);
-								}
-							}
-						);
-					}
+					return next();
 				},
 
-				(station, genrePlaylistIds, blacklistedGenrePlaylistIds, next) => {
-					if (station.type !== "official") return next(null, station);
-
-					const stationId = station._id;
+				next => {
+					const stationId = mongoose.Types.ObjectId();
+					playlistModel.create(
+						{
+							isUserModifiable: false,
+							displayName: `Station - ${data.name}`,
+							songs: [],
+							createdBy: data.type === "official" ? "Musare" : session.userId,
+							createdFor: `${stationId}`,
+							createdAt: Date.now(),
+							type: "station"
+						},
+						(err, playlist) => {
+							next(err, playlist, stationId);
+						}
+					);
+				},
 
-					return async.waterfall(
-						[
-							next => {
-								async.eachLimit(
-									genrePlaylistIds,
-									1,
-									(playlistId, next) => {
-										StationsModule.runJob("INCLUDE_PLAYLIST", { stationId, playlistId }, this)
-											.then(() => next())
-											.catch(next);
-									},
-									next
-								);
+				(playlist, stationId, next) => {
+					const { name, displayName, description, type } = data;
+					if (type === "official") {
+						stationModel.create(
+							{
+								_id: stationId,
+								name,
+								displayName,
+								description,
+								playlist: playlist._id,
+								type,
+								privacy: "private",
+								queue: [],
+								currentSong: null,
+								partyMode: false,
+								playMode: "random"
 							},
-
-							next => {
-								async.eachLimit(
-									blacklistedGenrePlaylistIds,
-									1,
-									(playlistId, next) => {
-										StationsModule.runJob("EXCLUDE_PLAYLIST", { stationId, playlistId }, this)
-											.then(() => next())
-											.catch(next);
-									},
-									next
-								);
+							next
+						);
+					} else {
+						stationModel.create(
+							{
+								_id: stationId,
+								name,
+								displayName,
+								description,
+								playlist: playlist._id,
+								type,
+								privacy: "private",
+								owner: session.userId,
+								queue: [],
+								currentSong: null,
+								partyMode: true,
+								playMode: "random"
 							},
-
-							next => {
-								PlaylistsModule.runJob("AUTOFILL_STATION_PLAYLIST", { stationId }).then().catch();
-								next();
-							}
-						],
-						async err => {
-							if (err) {
-								err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
-								this.log(
-									"ERROR",
-									"STATIONS_CREATE",
-									`Created station ${stationId} successfully, but an error occurred during playing including/excluding. Error: ${err}`
-								);
-							}
-							next(null, station, err);
-						}
-					);
+							next
+						);
+					}
 				}
 			],
-			async (err, station, extraError) => {
+			async (err, station) => {
 				if (err) {
 					err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
 					this.log("ERROR", "STATIONS_CREATE", `Creating station failed. "${err}"`);
@@ -2857,17 +2699,10 @@ export default {
 						}
 					});
 
-					if (!extraError) {
-						cb({
-							status: "success",
-							message: "Successfully created station."
-						});
-					} else {
-						cb({
-							status: "success",
-							message: `Successfully created station, but with one error at the end: ${extraError}`
-						});
-					}
+					cb({
+						status: "success",
+						message: "Successfully created station."
+					});
 				}
 			}
 		);

+ 16 - 9
frontend/src/components/modals/CreateCommunityStation.vue → frontend/src/components/modals/CreateStation.vue

@@ -1,10 +1,14 @@
 <template>
-	<modal title="Create Community Station">
+	<modal
+		:title="
+			official ? 'Create Official Station' : 'Create Community Station'
+		"
+	>
 		<template #body>
 			<label class="label">Name (unique lowercase station id)</label>
 			<p class="control">
 				<input
-					v-model="newCommunity.name"
+					v-model="newStation.name"
 					class="input station-id"
 					type="text"
 					placeholder="Name..."
@@ -14,7 +18,7 @@
 			<label class="label">Display Name</label>
 			<p class="control">
 				<input
-					v-model="newCommunity.displayName"
+					v-model="newStation.displayName"
 					class="input"
 					type="text"
 					placeholder="Display name..."
@@ -23,7 +27,7 @@
 			<label class="label">Description</label>
 			<p class="control">
 				<input
-					v-model="newCommunity.description"
+					v-model="newStation.description"
 					class="input"
 					type="text"
 					placeholder="Description..."
@@ -46,9 +50,12 @@ import Modal from "../Modal.vue";
 
 export default {
 	components: { Modal },
+	props: {
+		official: { type: Boolean, default: false }
+	},
 	data() {
 		return {
-			newCommunity: {
+			newStation: {
 				name: "",
 				displayName: "",
 				description: ""
@@ -60,8 +67,8 @@ export default {
 	}),
 	methods: {
 		submitModal() {
-			this.newCommunity.name = this.newCommunity.name.toLowerCase();
-			const { name, displayName, description } = this.newCommunity;
+			this.newStation.name = this.newStation.name.toLowerCase();
+			const { name, displayName, description } = this.newStation;
 
 			if (!name || !displayName || !description)
 				return new Toast("Please fill in all fields");
@@ -101,14 +108,14 @@ export default {
 				"stations.create",
 				{
 					name,
-					type: "community",
+					type: this.official ? "official" : "community",
 					displayName,
 					description
 				},
 				res => {
 					if (res.status === "success") {
 						new Toast(`You have added the station successfully`);
-						this.closeModal("createCommunityStation");
+						this.closeModal("createStation");
 					} else new Toast(res.message);
 				}
 			);

+ 11 - 208
frontend/src/pages/Admin/tabs/Stations.vue

@@ -3,6 +3,12 @@
 		<page-metadata title="Admin | Stations" />
 		<div class="container">
 			<div class="button-row">
+				<button
+					class="button is-primary"
+					@click="openModal('createStation')"
+				>
+					Create Station
+				</button>
 				<confirm placement="bottom" @confirm="clearEveryStationQueue()">
 					<button class="button is-danger">
 						Clear every station queue
@@ -71,111 +77,6 @@
 				</tbody>
 			</table>
 		</div>
-		<div class="container">
-			<div class="card is-fullwidth">
-				<header class="card-header">
-					<p class="card-header-title">Create official station</p>
-				</header>
-				<div class="card-content">
-					<div class="content">
-						<div class="control is-horizontal">
-							<div class="control is-grouped">
-								<p class="control is-expanded">
-									<input
-										v-model="newStation.name"
-										class="input"
-										type="text"
-										placeholder="Name"
-									/>
-								</p>
-								<p class="control is-expanded">
-									<input
-										v-model="newStation.displayName"
-										class="input"
-										type="text"
-										placeholder="Display Name"
-									/>
-								</p>
-							</div>
-						</div>
-						<label class="label">Description</label>
-						<p class="control is-expanded">
-							<input
-								v-model="newStation.description"
-								class="input"
-								type="text"
-								placeholder="Short description"
-							/>
-						</p>
-						<div class="control is-grouped genre-wrapper">
-							<div class="sector">
-								<p class="control has-addons">
-									<input
-										ref="new-genre"
-										class="input"
-										type="text"
-										placeholder="Genre"
-										@keyup.enter="addGenre()"
-									/>
-									<button
-										class="button is-info"
-										@click="addGenre()"
-									>
-										Add genre
-									</button>
-								</p>
-								<span
-									v-for="(genre, index) in newStation.genres"
-									:key="genre"
-									class="tag is-info"
-								>
-									{{ genre }}
-									<button
-										class="delete is-info"
-										@click="removeGenre(index)"
-									/>
-								</span>
-							</div>
-							<div class="sector">
-								<p class="control has-addons">
-									<input
-										ref="new-blacklisted-genre"
-										class="input"
-										type="text"
-										placeholder="Blacklisted Genre"
-										@keyup.enter="addBlacklistedGenre()"
-									/>
-									<button
-										class="button is-info"
-										@click="addBlacklistedGenre()"
-									>
-										Add blacklisted genre
-									</button>
-								</p>
-								<span
-									v-for="(
-										genre, index
-									) in newStation.blacklistedGenres"
-									:key="genre"
-									class="tag is-info"
-								>
-									{{ genre }}
-									<button
-										class="delete is-info"
-										@click="removeBlacklistedGenre(index)"
-									/>
-								</span>
-							</div>
-						</div>
-					</div>
-				</div>
-				<footer class="card-footer">
-					<a class="card-footer-item" @click="createStation()"
-						>Create</a
-					>
-				</footer>
-			</div>
-		</div>
 
 		<request-song v-if="modals.requestSong" />
 		<edit-playlist v-if="modals.editPlaylist" />
@@ -187,6 +88,7 @@
 		/>
 		<edit-song v-if="modals.editSong" song-type="songs" sector="admin" />
 		<report v-if="modals.report" />
+		<create-station v-if="modals.createStation" :official="true" />
 	</div>
 </template>
 
@@ -219,16 +121,15 @@ export default {
 		EditSong: defineAsyncComponent(() =>
 			import("@/components/modals/EditSong")
 		),
+		CreateStation: defineAsyncComponent(() =>
+			import("@/components/modals/CreateStation.vue")
+		),
 		UserIdToUsername,
 		Confirm
 	},
 	data() {
 		return {
-			editingStationId: "",
-			newStation: {
-				genres: [],
-				blacklistedGenres: []
-			}
+			editingStationId: ""
 		};
 	},
 	computed: {
@@ -254,44 +155,6 @@ export default {
 		);
 	},
 	methods: {
-		createStation() {
-			const {
-				newStation: {
-					name,
-					displayName,
-					description,
-					genres,
-					blacklistedGenres
-				}
-			} = this;
-
-			if (name === undefined)
-				return new Toast("Field (Name) cannot be empty");
-			if (displayName === undefined)
-				return new Toast("Field (Display Name) cannot be empty");
-			if (description === undefined)
-				return new Toast("Field (Description) cannot be empty");
-
-			return this.socket.dispatch(
-				"stations.create",
-				{
-					name,
-					type: "official",
-					displayName,
-					description,
-					genres,
-					blacklistedGenres
-				},
-				res => {
-					new Toast(res.message);
-					if (res.status === "success")
-						this.newStation = {
-							genres: [],
-							blacklistedGenres: []
-						};
-				}
-			);
-		},
 		removeStation(index) {
 			this.socket.dispatch(
 				"stations.remove",
@@ -303,37 +166,6 @@ export default {
 			this.editingStationId = station._id;
 			this.openModal("manageStation");
 		},
-		addGenre() {
-			const genre = this.$refs["new-genre"].value.toLowerCase().trim();
-			if (this.newStation.genres.indexOf(genre) !== -1)
-				return new Toast("Genre already exists");
-			if (genre) {
-				this.newStation.genres.push(genre);
-				this.$refs["new-genre"].value = "";
-				return true;
-			}
-			return new Toast("Genre cannot be empty");
-		},
-		removeGenre(index) {
-			this.newStation.genres.splice(index, 1);
-		},
-		addBlacklistedGenre() {
-			const genre = this.$refs["new-blacklisted-genre"].value
-				.toLowerCase()
-				.trim();
-			if (this.newStation.blacklistedGenres.indexOf(genre) !== -1)
-				return new Toast("Genre already exists");
-
-			if (genre) {
-				this.newStation.blacklistedGenres.push(genre);
-				this.$refs["new-blacklisted-genre"].value = "";
-				return true;
-			}
-			return new Toast("Genre cannot be empty");
-		},
-		removeBlacklistedGenre(index) {
-			this.newStation.blacklistedGenres.splice(index, 1);
-		},
 		clearEveryStationQueue() {
 			this.socket.dispatch("stations.clearEveryStationQueue", res => {
 				if (res.status === "success") new Toast(res.message);
@@ -384,26 +216,6 @@ export default {
 			color: var(--light-grey-2);
 		}
 	}
-
-	.card {
-		background: var(--dark-grey-3);
-
-		.card-header {
-			box-shadow: 0 1px 2px rgba(10, 10, 10, 0.8);
-		}
-
-		p,
-		.label {
-			color: var(--light-grey-2);
-		}
-	}
-}
-
-.tag {
-	margin-top: 5px;
-	&:not(:last-child) {
-		margin-right: 5px;
-	}
 }
 
 td {
@@ -419,13 +231,4 @@ td {
 .is-info:focus {
 	background-color: var(--primary-color);
 }
-
-.genre-wrapper {
-	display: flex;
-	justify-content: space-around;
-}
-
-.card-footer-item {
-	color: var(--primary-color);
-}
 </style>

+ 4 - 4
frontend/src/pages/Home.vue

@@ -234,7 +234,7 @@
 				</div>
 				<a
 					v-if="loggedIn"
-					@click="openModal('createCommunityStation')"
+					@click="openModal('createStation')"
 					class="card station-card createStation"
 				>
 					<div class="card-image">
@@ -434,7 +434,7 @@
 			</div>
 			<main-footer />
 		</div>
-		<create-community-station v-if="modals.createCommunityStation" />
+		<create-station v-if="modals.createStation" />
 	</div>
 </template>
 
@@ -456,8 +456,8 @@ export default {
 		MainHeader,
 		MainFooter,
 		SongThumbnail,
-		CreateCommunityStation: defineAsyncComponent(() =>
-			import("@/components/modals/CreateCommunityStation.vue")
+		CreateStation: defineAsyncComponent(() =>
+			import("@/components/modals/CreateStation.vue")
 		),
 		UserIdToUsername,
 		draggable

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

@@ -7,7 +7,7 @@ const state = {
 		manageStation: false,
 		login: false,
 		register: false,
-		createCommunityStation: false,
+		createStation: false,
 		requestSong: false,
 		editPlaylist: false,
 		createPlaylist: false,