| 
					
				 | 
			
			
				@@ -3,54 +3,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		<page-metadata title="Admin | Playlists" /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		<div class="container"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			<div class="button-row"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				<confirm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					placement="bottom" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					@confirm="deleteOrphanedStationPlaylists()" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					<button class="button is-danger"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						Delete orphaned station playlists 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					</button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				</confirm> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				<confirm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					placement="bottom" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					@confirm="deleteOrphanedGenrePlaylists()" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					<button class="button is-danger"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						Delete orphaned genre playlists 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					</button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				</confirm> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				<confirm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					placement="bottom" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					@confirm="requestOrphanedPlaylistSongs()" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					<button class="button is-danger"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						Request orphaned playlist songs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					</button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				</confirm> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				<confirm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					placement="bottom" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					@confirm="clearAndRefillAllStationPlaylists()" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					<button class="button is-danger"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						Clear and refill all station playlists 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					</button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				</confirm> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				<confirm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					placement="bottom" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					@confirm="clearAndRefillAllGenrePlaylists()" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					<button class="button is-danger"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						Clear and refill all genre playlists 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					</button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				</confirm> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				<confirm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					placement="bottom" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					@confirm="createMissingGenrePlaylists()" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					<button class="button is-danger"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						Create missing genre playlists 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					</button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				</confirm> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				<run-job-dropdown :jobs="jobs" /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			</div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			<table class="table"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				<thead> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -109,8 +62,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { mapState, mapActions, mapGetters } from "vuex"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { defineAsyncComponent } from "vue"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import Toast from "toasters"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import Confirm from "@/components/Confirm.vue"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import RunJobDropdown from "@/components/RunJobDropdown.vue"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import UserIdToUsername from "@/components/UserIdToUsername.vue"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -129,11 +81,37 @@ export default { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		EditSong: defineAsyncComponent(() => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			import("@/components/modals/EditSong") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		Confirm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		RunJobDropdown 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	data() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			utils 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			utils, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			jobs: [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					name: "Delete orphaned station playlists", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					socket: "playlists.deleteOrphanedStationPlaylists" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					name: "Delete orphaned genre playlists", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					socket: "playlists.deleteOrphanedGenrePlaylists" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					name: "Request orphaned playlist songs", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					socket: "playlists.requestOrphanedPlaylistSongs" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					name: "Clear and refill all station playlists", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					socket: "playlists.clearAndRefillAllStationPlaylists" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					name: "Clear and refill all genre playlists", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					socket: "playlists.clearAndRefillAllGenrePlaylists" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					name: "Create missing genre playlists", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					socket: "playlists.createMissingGenrePlaylists" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	computed: { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -222,74 +200,6 @@ export default { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			return this.utils.formatTimeLong(length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		deleteOrphanedStationPlaylists() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			this.socket.dispatch( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				"playlists.deleteOrphanedStationPlaylists", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				res => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					if (res.status === "success") new Toast(res.message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					else new Toast(`Error: ${res.message}`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		deleteOrphanedGenrePlaylists() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			this.socket.dispatch( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				"playlists.deleteOrphanedGenrePlaylists", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				res => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					if (res.status === "success") new Toast(res.message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					else new Toast(`Error: ${res.message}`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		requestOrphanedPlaylistSongs() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			this.socket.dispatch( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				"playlists.requestOrphanedPlaylistSongs", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				res => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					if (res.status === "success") new Toast(res.message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					else new Toast(`Error: ${res.message}`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		clearAndRefillAllStationPlaylists() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			this.socket.dispatch( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				"playlists.clearAndRefillAllStationPlaylists", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				res => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					if (res.status === "success") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						new Toast({ content: res.message, timeout: 4000 }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						new Toast({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							content: `Error: ${res.message}`, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							timeout: 4000 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		clearAndRefillAllGenrePlaylists() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			this.socket.dispatch( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				"playlists.clearAndRefillAllGenrePlaylists", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				res => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					if (res.status === "success") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						new Toast({ content: res.message, timeout: 4000 }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						new Toast({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							content: `Error: ${res.message}`, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							timeout: 4000 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		createMissingGenrePlaylists() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			this.socket.dispatch( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				"playlists.createMissingGenrePlaylists", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				data => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					if (data.status !== "success") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						new Toast({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							content: `Error: ${data.message}`, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							timeout: 8000 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					else new Toast({ content: data.message, timeout: 4000 }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		...mapActions("modalVisibility", ["openModal"]), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		...mapActions("user/playlists", ["editPlaylist"]), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		...mapActions("admin/playlists", [ 
			 |