Browse Source

fix(AddSongToQueue): improved design and user feedback on importing of youtube playlist

Signed-off-by: Jonathan <theflametrooper@gmail.com>
Jonathan 4 years ago
parent
commit
c0af8c06dc
3 changed files with 85 additions and 17 deletions
  1. 15 3
      backend/logic/utils.js
  2. 21 1
      frontend/src/App.vue
  3. 49 13
      frontend/src/pages/Station/AddSongToQueue.vue

+ 15 - 3
backend/logic/utils.js

@@ -556,13 +556,25 @@ class UtilsModule extends CoreClass {
     }
 
     GET_PLAYLIST_FROM_YOUTUBE(payload) {
-        //url, musicOnly, cb
+        // payload includes: url, musicOnly
         return new Promise((resolve, reject) => {
             let local = this;
 
             let name = "list".replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
-            var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
-            let playlistId = regex.exec(payload.url)[1];
+
+            const regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
+            const splitQuery = regex.exec(payload.url);
+
+            if (!splitQuery) {
+                console.log(
+                    "ERROR",
+                    "GET_PLAYLIST_FROM_YOUTUBE",
+                    "Invalid YouTube playlist URL query."
+                );
+                return reject(new Error("An error has occured. Please try again later."));
+            }
+
+            let playlistId = splitQuery[1];
 
             function getPage(pageToken, songs) {
                 let nextPageToken = pageToken ? `pageToken=${pageToken}` : "";

+ 21 - 1
frontend/src/App.vue

@@ -367,10 +367,23 @@ a {
 	}
 }
 
+.select {
+	&:after {
+		border-color: $musare-blue;
+		border-width: 1.5px;
+		margin-top: -3px;
+	}
+
+	select {
+		height: 36px;
+	}
+}
+
 .button:focus,
 .button:active {
 	border-color: #dbdbdb !important;
 }
+
 .input:focus,
 .input:active,
 .textarea:focus,
@@ -379,6 +392,7 @@ a {
 .select select:active {
 	border-color: $primary-color !important;
 }
+
 button.delete:focus {
 	background-color: rgba(10, 10, 10, 0.3);
 }
@@ -425,6 +439,11 @@ button.delete:focus {
 	}
 }
 
+.input,
+.button {
+	height: 36px;
+}
+
 .input-with-button {
 	.control {
 		margin-right: 0px !important;
@@ -432,7 +451,8 @@ button.delete:focus {
 
 	input {
 		height: 36px;
-		border-radius: 3px 0 3px 0;
+		border-radius: 3px 0 0 3px;
+		border-right: 0;
 	}
 
 	.button {

+ 49 - 13
frontend/src/pages/Station/AddSongToQueue.vue

@@ -116,23 +116,33 @@
 								@keyup.enter="importPlaylist(false)"
 							/>
 						</p>
-						<p class="control">
+						<p class="control has-addons">
+							<span class="select" id="playlist-import-type">
+								<select
+									v-model="isImportingOnlyMusicOfPlaylist"
+								>
+									<option :value="false">Import all</option>
+									<option :value="true"
+										>Import only music</option
+									>
+								</select>
+							</span>
 							<a
 								class="button is-info"
-								v-on:click="importPlaylist(false)"
+								v-on:click="importPlaylist()"
 								href="#"
 								><i class="material-icons icon-with-button"
 									>publish</i
 								>Import</a
 							>
-							<a
+							<!-- <a
 								class="button is-info"
 								v-on:click="importPlaylist(true)"
 								href="#"
 								><i class="material-icons icon-with-button"
 									>publish</i
 								>Import only music</a
-							>
+							> -->
 						</p>
 					</div>
 				</div>
@@ -229,7 +239,8 @@ export default {
 			querySearch: "",
 			queryResults: [],
 			playlists: [],
-			importQuery: ""
+			importQuery: "",
+			isImportingOnlyMusicOfPlaylist: false
 		};
 	},
 	computed: mapState({
@@ -291,18 +302,33 @@ export default {
 				});
 			}
 		},
-		importPlaylist(musicOnly) {
-			new Toast({
-				content:
-					"Starting to import your playlist. This can take some time to do.",
-				timeout: 4000
-			});
+		importPlaylist() {
+			let isImportingPlaylist = true;
+
+			// import query is blank
+			if (!this.importQuery)
+				return new Toast({
+					content: "Please enter a YouTube playlist URL.",
+					timeout: 4000
+				});
 
-			this.socket.emit(
+			// don't give starting import message instantly in case of instant error
+			setTimeout(() => {
+				if (isImportingPlaylist) {
+					new Toast({
+						content:
+							"Starting to import your playlist. This can take some time to do.",
+						timeout: 4000
+					});
+				}
+			}, 750);
+
+			return this.socket.emit(
 				"queueSongs.addSetToQueue",
 				this.importQuery,
-				musicOnly,
+				this.isImportingOnlyMusicOfPlaylist,
 				res => {
+					isImportingPlaylist = false;
 					return new Toast({ content: res.message, timeout: 4000 });
 				}
 			);
@@ -423,6 +449,16 @@ tr td {
 	}
 }
 
+#playlist-import-type {
+	&:hover {
+		z-index: initial;
+	}
+
+	select {
+		border-radius: 0;
+	}
+}
+
 .vertical-padding {
 	padding: 20px;
 }