Selaa lähdekoodia

Added Song Item component

Owen Diffey 4 vuotta sitten
vanhempi
sitoutus
49b0ef2063

+ 3 - 2
frontend/src/App.vue

@@ -449,7 +449,7 @@ a {
 		width: 146px;
 	}
 
-	.queue-actions,
+	.song-actions,
 	.addToPlaylistDropdown {
 		display: inline-block;
 	}
@@ -785,6 +785,7 @@ h4.section-title {
 .universal-item {
 	display: flex;
 	flex-direction: row;
+	flex-grow: 1;
 	align-items: center;
 	justify-content: space-between;
 	padding: 7.5px;
@@ -828,7 +829,7 @@ h4.section-title {
 			color: var(--primary-color);
 		}
 
-		.queue-actions {
+		.song-actions {
 			display: flex;
 		}
 

+ 28 - 28
frontend/src/components/modals/EditPlaylist/index.vue → frontend/src/components/modals/EditPlaylist.vue

@@ -243,7 +243,7 @@
 									v-for="(song, index) in playlist.songs"
 									:key="'key-' + index"
 								>
-									<playlist-song-item
+									<song-item
 										:song="song"
 										:class="{
 											'item-draggable': isEditable()
@@ -251,14 +251,30 @@
 									>
 										<div
 											v-if="isEditable()"
-											class="queue-actions"
+											class="song-actions"
 											slot="actions"
 										>
+											<i
+												v-if="
+													userId ===
+														playlist.createdBy ||
+														isEditable()
+												"
+												@click="
+													removeSongFromPlaylist(
+														song.songId
+													)
+												"
+												class="material-icons delete-icon"
+												content="Remove Song from Playlist"
+												v-tippy
+												>delete_forever</i
+											>
 											<i
 												class="material-icons"
 												v-if="index > 0"
 												@click="moveSongToTop(index)"
-												content="Move to top of Queue"
+												content="Move to top of Playlist"
 												v-tippy
 												>vertical_align_top</i
 											>
@@ -270,28 +286,12 @@
 												"
 												@click="moveSongToBottom(index)"
 												class="material-icons"
-												content="Move to bottom of Queue"
+												content="Move to bottom of Playlist"
 												v-tippy
 												>vertical_align_bottom</i
 											>
 										</div>
-										<i
-											slot="remove"
-											v-if="
-												userId === playlist.createdBy ||
-													isEditable()
-											"
-											@click="
-												removeSongFromPlaylist(
-													song.songId
-												)
-											"
-											class="material-icons delete-icon"
-											content="Remove Song from Playlist"
-											v-tippy
-											>delete</i
-										>
-									</playlist-song-item>
+									</song-item>
 								</li>
 							</transition-group>
 						</draggable>
@@ -345,17 +345,17 @@ import { mapState, mapGetters, mapActions } from "vuex";
 import draggable from "vuedraggable";
 import Toast from "toasters";
 
-import SearchYoutube from "../../../mixins/SearchYoutube.vue";
+import SearchYoutube from "../../mixins/SearchYoutube.vue";
 
-import Modal from "../../Modal.vue";
-import SearchQueryItem from "../../ui/SearchQueryItem.vue";
-import PlaylistSongItem from "./components/PlaylistSongItem.vue";
+import Modal from "../Modal.vue";
+import SearchQueryItem from "../ui/SearchQueryItem.vue";
+import SongItem from "../ui/SongItem.vue";
 
-import validation from "../../../validation";
-import utils from "../../../../js/utils";
+import validation from "../../validation";
+import utils from "../../../js/utils";
 
 export default {
-	components: { Modal, draggable, SearchQueryItem, PlaylistSongItem },
+	components: { Modal, draggable, SearchQueryItem, SongItem },
 	mixins: [SearchYoutube],
 	data() {
 		return {

+ 0 - 209
frontend/src/components/modals/EditPlaylist/components/PlaylistSongItem.vue

@@ -1,209 +0,0 @@
-<template>
-	<div class="universal-item playlist-song-item">
-		<div id="thumbnail-and-info">
-			<song-thumbnail :song="song" />
-			<div id="song-info">
-				<h4 class="item-title" :title="song.title">
-					{{ song.title }}
-					<i
-						v-if="song.status === 'verified'"
-						class="material-icons verified-song"
-						content="Verified Song"
-						v-tippy
-					>
-						check_circle
-					</i>
-				</h4>
-				<h5
-					class="item-description"
-					v-if="song.artists"
-					:style="
-						song.artists.length < 1 ? { fontSize: '16px' } : null
-					"
-					:title="song.artists.join(', ')"
-				>
-					{{ song.artists.join(", ") }}
-				</h5>
-			</div>
-		</div>
-		<div class="universal-item-actions">
-			<tippy
-				v-if="loggedIn"
-				interactive="true"
-				placement="left"
-				theme="songActions"
-				ref="songActions"
-				trigger="click"
-			>
-				<template #trigger>
-					<i
-						class="material-icons action-dropdown-icon"
-						content="Song Options"
-						v-tippy
-						>more_horiz</i
-					>
-				</template>
-				<a
-					target="_blank"
-					:href="`https://www.youtube.com/watch?v=${song.songId}`"
-					content="View on Youtube"
-					v-tippy
-				>
-					<div class="youtube-icon"></div>
-				</a>
-				<i
-					class="material-icons report-icon"
-					@click="reportSongInPlaylist(song)"
-					content="Report Song"
-					v-tippy
-				>
-					flag
-				</i>
-				<add-to-playlist-dropdown :song="song">
-					<i
-						slot="button"
-						class="material-icons add-to-playlist-icon"
-						content="Add Song to Playlist"
-						v-tippy
-						>queue</i
-					>
-				</add-to-playlist-dropdown>
-				<i
-					v-if="userRole === 'admin'"
-					class="material-icons edit-icon"
-					@click="editSongInPlaylist(song)"
-					content="Edit Song"
-					v-tippy
-				>
-					edit
-				</i>
-				<slot name="remove" />
-				<slot name="actions" />
-			</tippy>
-			<a
-				v-else
-				target="_blank"
-				:href="`https://www.youtube.com/watch?v=${song.songId}`"
-				content="View on Youtube"
-				v-tippy
-			>
-				<div class="youtube-icon"></div>
-			</a>
-		</div>
-	</div>
-</template>
-
-<script>
-import { mapState, mapActions } from "vuex";
-
-import AddToPlaylistDropdown from "../../../ui/AddToPlaylistDropdown.vue";
-import SongThumbnail from "../../../ui/SongThumbnail.vue";
-
-export default {
-	components: { AddToPlaylistDropdown, SongThumbnail },
-	props: {
-		song: {
-			type: Object,
-			default: () => {}
-		}
-	},
-	computed: mapState({
-		loggedIn: state => state.user.auth.loggedIn,
-		userRole: state => state.user.auth.role
-	}),
-	methods: {
-		hideTippyElements() {
-			this.$refs.songActions.tip.hide();
-
-			setTimeout(
-				() =>
-					Array.from(
-						document.querySelectorAll(".tippy-popper")
-					).forEach(popper => popper._tippy.hide()),
-				500
-			);
-		},
-		editSongInPlaylist(song) {
-			this.hideTippyElements();
-			this.editSong(song);
-			this.openModal({ sector: "admin", modal: "editSong" });
-		},
-		reportSongInPlaylist(song) {
-			this.hideTippyElements();
-			this.reportSong(song);
-			this.openModal({ sector: "station", modal: "report" });
-		},
-		...mapActions("modals/editSong", ["editSong"]),
-		...mapActions("modals/report", ["reportSong"]),
-		...mapActions("modalVisibility", ["openModal"])
-	}
-};
-</script>
-
-<style lang="scss" scoped>
-.night-mode {
-	.playlist-song-item {
-		background-color: var(--dark-grey-3) !important;
-		border: 0 !important;
-	}
-}
-
-/deep/ #nav-dropdown {
-	margin-top: 36px;
-	width: 0;
-	height: 0;
-
-	.nav-dropdown-items {
-		width: 250px;
-		max-width: 100vw;
-		position: relative;
-		right: 250px;
-	}
-}
-
-.playlist-song-item {
-	width: 100%;
-	min-height: 50px;
-
-	#thumbnail-and-info,
-	.universal-item-actions div {
-		display: flex;
-		align-items: center;
-	}
-
-	.universal-item-actions {
-		margin-left: 5px;
-
-		i {
-			margin-left: 5px;
-		}
-	}
-
-	.thumbnail {
-		min-width: 55px;
-		width: 55px;
-		height: 55px;
-	}
-
-	#thumbnail-and-info {
-		width: calc(100% - 50px);
-	}
-
-	#song-info {
-		display: flex;
-		flex-direction: column;
-		justify-content: center;
-		margin-left: 20px;
-		width: calc(100% - 50px);
-
-		.item-title {
-			font-size: 16px;
-		}
-
-		*:not(i) {
-			margin: 0;
-			font-family: Karla, Arial, sans-serif;
-		}
-	}
-}
-</style>

+ 58 - 40
frontend/src/pages/Station/components/Sidebar/Queue/QueueItem.vue → frontend/src/components/ui/SongItem.vue

@@ -1,8 +1,9 @@
 <template>
-	<div class="universal-item queue-item">
-		<div id="thumbnail-and-info">
-			<song-thumbnail :song="song" />
-			<div id="song-info">
+	<div class="universal-item song-item">
+		<div class="thumbnail-and-info">
+			<song-thumbnail :class="{ large: largeThumbnail }" :song="song" />
+			<div class="song-info">
+				<h6 v-if="header">{{ header }}</h6>
 				<h4
 					class="item-title"
 					:style="
@@ -28,11 +29,8 @@
 					{{ song.artists.join(", ") }}
 				</h5>
 				<p
-					id="song-request-time"
-					v-if="
-						station.type === 'community' &&
-							station.partyMode === true
-					"
+					class="song-request-time"
+					v-if="requestedBy && song.requestedBy"
 				>
 					Requested by
 					<strong>
@@ -55,13 +53,13 @@
 			</div>
 		</div>
 
-		<div id="duration-and-actions">
-			<p id="song-duration">
+		<div class="duration-and-actions">
+			<p v-if="duration" class="song-duration">
 				{{ utils.formatTime(song.duration) }}
 			</p>
 			<div class="universal-item-actions">
 				<tippy
-					v-if="$parent.loggedIn"
+					v-if="loggedIn"
 					interactive="true"
 					placement="left"
 					theme="songActions"
@@ -102,7 +100,7 @@
 						>
 					</add-to-playlist-dropdown>
 					<i
-						v-if="$parent.isAdminOnly()"
+						v-if="loggedIn && userRole === 'admin'"
 						class="material-icons edit-icon"
 						@click="edit(song)"
 						content="Edit Song"
@@ -110,14 +108,6 @@
 					>
 						edit
 					</i>
-					<i
-						v-if="$parent.isOwnerOnly() || $parent.isAdminOnly()"
-						class="material-icons delete-icon"
-						@click="$parent.removeFromQueue(song.songId)"
-						content="Remove Song from Queue"
-						v-tippy
-						>delete_forever</i
-					>
 					<slot name="actions" />
 				</tippy>
 				<a
@@ -135,13 +125,13 @@
 </template>
 
 <script>
-import { mapActions } from "vuex";
+import { mapActions, mapState } from "vuex";
 import { formatDistance, parseISO } from "date-fns";
 
-import AddToPlaylistDropdown from "../../../../../components/ui/AddToPlaylistDropdown.vue";
-import UserIdToUsername from "../../../../../components/common/UserIdToUsername.vue";
-import SongThumbnail from "../../../../../components/ui/SongThumbnail.vue";
-import utils from "../../../../../../js/utils";
+import AddToPlaylistDropdown from "./AddToPlaylistDropdown.vue";
+import UserIdToUsername from "../common/UserIdToUsername.vue";
+import SongThumbnail from "./SongThumbnail.vue";
+import utils from "../../../js/utils";
 
 export default {
 	components: { UserIdToUsername, AddToPlaylistDropdown, SongThumbnail },
@@ -150,11 +140,21 @@ export default {
 			type: Object,
 			default: () => {}
 		},
-		station: {
-			type: Object,
-			default: () => {
-				return { type: "community", partyMode: false };
-			}
+		requestedBy: {
+			type: Boolean,
+			default: false
+		},
+		duration: {
+			type: Boolean,
+			default: true
+		},
+		largeThumbnail: {
+			type: Boolean,
+			default: false
+		},
+		header: {
+			type: String,
+			default: null
 		}
 	},
 	data() {
@@ -162,6 +162,12 @@ export default {
 			utils
 		};
 	},
+	computed: {
+		...mapState({
+			loggedIn: state => state.user.auth.loggedIn,
+			userRole: state => state.user.auth.role
+		})
+	},
 	methods: {
 		hideTippyElements() {
 			this.$refs.songActions.tip.hide();
@@ -195,7 +201,7 @@ export default {
 
 <style lang="scss" scoped>
 .night-mode {
-	.queue-item {
+	.song-item {
 		background-color: var(--dark-grey-2) !important;
 		border: 0 !important;
 	}
@@ -214,14 +220,14 @@ export default {
 	}
 }
 
-.queue-item {
-	#thumbnail-and-info,
-	#duration-and-actions {
+.song-item {
+	.thumbnail-and-info,
+	.duration-and-actions {
 		display: flex;
 		align-items: center;
 	}
 
-	#duration-and-actions {
+	.duration-and-actions {
 		margin-left: 5px;
 
 		.universal-item-actions div i {
@@ -229,7 +235,7 @@ export default {
 		}
 	}
 
-	#thumbnail-and-info {
+	.thumbnail-and-info {
 		width: calc(100% - 90px);
 	}
 
@@ -238,9 +244,14 @@ export default {
 		width: 65px;
 		height: 65px;
 		margin: -7.5px;
+		&.large {
+			min-width: 130px;
+			width: 130px;
+			height: 130px;
+		}
 	}
 
-	#song-info {
+	.song-info {
 		display: flex;
 		flex-direction: column;
 		justify-content: center;
@@ -252,13 +263,20 @@ export default {
 			font-family: Karla, Arial, sans-serif;
 		}
 
-		#song-request-time {
+		h6 {
+			color: var(--primary-color) !important;
+			font-weight: bold;
+			font-size: 17px;
+			margin-bottom: 5px;
+		}
+
+		.song-request-time {
 			font-size: 12px;
 			margin-top: 7px;
 		}
 	}
 
-	#song-duration {
+	.song-duration {
 		font-size: 20px;
 	}
 

+ 1 - 1
frontend/src/pages/Admin/tabs/Playlists.vue

@@ -88,7 +88,7 @@ import utils from "../../../../js/utils";
 export default {
 	components: {
 		EditPlaylist: () =>
-			import("../../../components/modals/EditPlaylist/index.vue"),
+			import("../../../components/modals/EditPlaylist.vue"),
 		UserIdToUsername,
 		Report: () => import("../../../components/modals/Report.vue"),
 		EditSong: () => import("../../../components/modals/EditSong.vue")

+ 1 - 2
frontend/src/pages/Profile/index.vue

@@ -114,8 +114,7 @@ export default {
 		ProfilePicture,
 		RecentActivity,
 		Playlists,
-		EditPlaylist: () =>
-			import("../../components/modals/EditPlaylist/index.vue"),
+		EditPlaylist: () => import("../../components/modals/EditPlaylist.vue"),
 		Report: () => import("../../components/modals/Report.vue"),
 		EditSong: () => import("../../components/modals/EditSong.vue")
 	},

+ 2 - 2
frontend/src/pages/Station/components/Sidebar/MyPlaylists.vue → frontend/src/pages/Station/Sidebar/Playlists.vue

@@ -80,8 +80,8 @@ import { mapState, mapActions, mapGetters } from "vuex";
 import Toast from "toasters";
 import draggable from "vuedraggable";
 
-import PlaylistItem from "../../../../components/ui/PlaylistItem.vue";
-import SortablePlaylists from "../../../../mixins/SortablePlaylists.vue";
+import PlaylistItem from "../../../components/ui/PlaylistItem.vue";
+import SortablePlaylists from "../../../mixins/SortablePlaylists.vue";
 
 export default {
 	components: { PlaylistItem, draggable },

+ 17 - 11
frontend/src/pages/Station/components/Sidebar/Queue/index.vue → frontend/src/pages/Station/Sidebar/Queue.vue

@@ -1,26 +1,32 @@
 <template>
 	<div id="queue">
 		<div
-			id="queue-items"
 			:class="{
 				'actionable-button-hidden': !actionableButtonVisible,
 				'scrollable-list': true
 			}"
 		>
-			<queue-item
+			<song-item
 				v-for="(song, index) in songsList"
 				:key="index + song.songId"
 				:song="song"
-				:station="{
-					type: station.type,
-					partyMode: station.partyMode
-				}"
+				:requested-by="
+					station.type === 'community' && station.partyMode === true
+				"
 			>
 				<div
 					v-if="isAdminOnly() || isOwnerOnly()"
-					class="queue-actions"
+					class="song-actions"
 					slot="actions"
 				>
+					<i
+						v-if="isOwnerOnly() || isAdminOnly()"
+						class="material-icons delete-icon"
+						@click="removeFromQueue(song.songId)"
+						content="Remove Song from Queue"
+						v-tippy
+						>delete_forever</i
+					>
 					<i
 						class="material-icons"
 						v-if="index > 0"
@@ -38,7 +44,7 @@
 						>vertical_align_bottom</i
 					>
 				</div>
-			</queue-item>
+			</song-item>
 			<p class="nothing-here-text" v-if="songsList.length < 1">
 				There are no songs currently queued
 			</p>
@@ -106,10 +112,10 @@
 import { mapActions, mapState, mapGetters } from "vuex";
 import Toast from "toasters";
 
-import QueueItem from "./QueueItem.vue";
+import SongItem from "../../../components/ui/SongItem.vue";
 
 export default {
-	components: { QueueItem },
+	components: { SongItem },
 	data() {
 		return {
 			dismissedWarning: false,
@@ -183,7 +189,7 @@ export default {
 		max-height: 100%;
 	}
 
-	.queue-item:not(:last-of-type) {
+	.song-item:not(:last-of-type) {
 		margin-bottom: 10px;
 	}
 

+ 1 - 1
frontend/src/pages/Station/components/Sidebar/Users.vue → frontend/src/pages/Station/Sidebar/Users.vue

@@ -69,7 +69,7 @@
 import { mapState } from "vuex";
 import Toast from "toasters";
 
-import ProfilePicture from "../../../../components/ui/ProfilePicture.vue";
+import ProfilePicture from "../../../components/ui/ProfilePicture.vue";
 
 export default {
 	components: { ProfilePicture },

+ 9 - 9
frontend/src/pages/Station/components/Sidebar/index.vue → frontend/src/pages/Station/Sidebar/index.vue

@@ -18,8 +18,8 @@
 			<button
 				v-if="loggedIn"
 				class="button is-default"
-				:class="{ selected: tab === 'my-playlists' }"
-				@click="showTab('my-playlists')"
+				:class="{ selected: tab === 'playlists' }"
+				@click="showTab('playlists')"
 			>
 				My Playlists
 			</button>
@@ -34,21 +34,21 @@
 		</div>
 		<queue class="tab" v-show="tab === 'queue'" />
 		<users class="tab" v-show="tab === 'users'" />
-		<my-playlists class="tab" v-show="tab === 'my-playlists'" />
+		<playlists class="tab" v-show="tab === 'playlists'" />
 	</div>
 </template>
 
 <script>
 import { mapActions, mapState } from "vuex";
 
-import TabQueryHandler from "../../../../mixins/TabQueryHandler.vue";
+import TabQueryHandler from "../../../mixins/TabQueryHandler.vue";
 
-import Queue from "./Queue/index.vue";
+import Queue from "./Queue.vue";
 import Users from "./Users.vue";
-import MyPlaylists from "./MyPlaylists.vue";
+import Playlists from "./Playlists.vue";
 
 export default {
-	components: { Queue, Users, MyPlaylists },
+	components: { Queue, Users, Playlists },
 	mixins: [TabQueryHandler],
 	data() {
 		return {
@@ -64,7 +64,7 @@ export default {
 		if (
 			this.$route.query.tab === "queue" ||
 			this.$route.query.tab === "users" ||
-			this.$route.query.tab === "my-playlists"
+			this.$route.query.tab === "playlists"
 		)
 			this.tab = this.$route.query.tab;
 	},
@@ -142,7 +142,7 @@ export default {
 	max-height: calc(100% - 20px - 40px);
 	padding: 10px;
 
-	.queue-item:not(:last-of-type) {
+	.song-item:not(:last-of-type) {
 		margin-bottom: 10px;
 	}
 }

+ 0 - 242
frontend/src/pages/Station/components/CurrentlyPlaying.vue

@@ -1,242 +0,0 @@
-<template>
-	<div class="currently-playing">
-		<song-thumbnail :song="song" />
-		<div class="song-info">
-			<div class="song-details">
-				<h6 v-if="type === 'current'">Currently Playing...</h6>
-				<h6 v-if="type === 'next'">Next Up...</h6>
-				<h4
-					class="song-title"
-					:style="!song.artists ? { fontSize: '17px' } : null"
-					:title="song.title"
-				>
-					{{ song.title }}
-					<i
-						v-if="song.status === 'verified'"
-						class="material-icons verified-song"
-						content="Verified Song"
-						v-tippy
-					>
-						check_circle
-					</i>
-				</h4>
-				<h5
-					class="song-artists"
-					v-if="song.artists"
-					:title="song.artists.join(', ')"
-				>
-					{{ song.artists.join(", ") }}
-				</h5>
-				<p
-					class="song-request-time"
-					v-if="
-						station.type === 'community' &&
-							station.partyMode === true
-					"
-				>
-					Requested by
-					<strong>
-						<user-id-to-username
-							:user-id="song.requestedBy"
-							:link="true"
-						/>
-						{{
-							formatDistance(
-								parseISO(song.requestedAt),
-								new Date(),
-								{
-									includeSeconds: true
-								}
-							)
-						}}
-						ago
-					</strong>
-				</p>
-			</div>
-		</div>
-		<tippy
-			class="song-actions"
-			interactive="true"
-			placement="right"
-			theme="songActions"
-			ref="songActions"
-			trigger="click"
-		>
-			<template #trigger>
-				<i
-					class="material-icons action-dropdown-icon"
-					content="Song Options"
-					v-tippy
-					>more_horiz</i
-				>
-			</template>
-			<a
-				target="_blank"
-				:href="`https://www.youtube.com/watch?v=${song.songId}`"
-				content="View on Youtube"
-				v-tippy
-			>
-				<div class="youtube-icon"></div>
-			</a>
-			<i
-				v-if="$parent.loggedIn"
-				class="material-icons report-icon"
-				@click="report(song)"
-				content="Report Song"
-				v-tippy
-			>
-				flag
-			</i>
-			<add-to-playlist-dropdown v-if="$parent.loggedIn" :song="song">
-				<i
-					slot="button"
-					class="material-icons add-to-playlist-icon"
-					content="Add Song to Playlist"
-					v-tippy
-					>queue</i
-				>
-			</add-to-playlist-dropdown>
-			<i
-				v-if="$parent.isAdminOnly()"
-				class="material-icons edit-icon"
-				@click="edit(song)"
-				content="Edit Song"
-				v-tippy
-			>
-				edit
-			</i>
-		</tippy>
-	</div>
-</template>
-
-<script>
-import { mapState, mapActions } from "vuex";
-import { formatDistance, parseISO } from "date-fns";
-
-import AddToPlaylistDropdown from "../../../components/ui/AddToPlaylistDropdown.vue";
-import UserIdToUsername from "../../../components/common/UserIdToUsername.vue";
-import SongThumbnail from "../../../components/ui/SongThumbnail.vue";
-
-export default {
-	components: { AddToPlaylistDropdown, UserIdToUsername, SongThumbnail },
-	props: {
-		song: {
-			type: Object,
-			default: () => {}
-		},
-		type: {
-			type: String,
-			default: "current"
-		}
-	},
-	computed: {
-		...mapState("station", {
-			station: state => state.station
-		}),
-		...mapState({
-			loggedIn: state => state.user.auth.loggedIn
-		})
-	},
-	methods: {
-		hideTippyElements() {
-			this.$refs.songActions.tip.hide();
-
-			setTimeout(
-				() =>
-					Array.from(
-						document.querySelectorAll(".tippy-popper")
-					).forEach(popper => popper._tippy.hide()),
-				500
-			);
-		},
-		edit(song) {
-			this.hideTippyElements();
-			this.editSong(song);
-			this.openModal({ sector: "admin", modal: "editSong" });
-		},
-		report(song) {
-			this.hideTippyElements();
-			this.reportSong(song);
-			this.openModal({ sector: "station", modal: "report" });
-		},
-		...mapActions("modals/editSong", ["editSong"]),
-		...mapActions("modals/report", ["reportSong"]),
-		...mapActions("modalVisibility", ["openModal"]),
-		formatDistance,
-		parseISO
-	}
-};
-</script>
-
-<style lang="scss" scoped>
-.currently-playing {
-	display: flex;
-	flex-direction: row;
-	align-items: center;
-	width: 100%;
-	height: 100%;
-	padding: 10px;
-	min-height: 130px;
-
-	.song-info {
-		display: flex;
-		flex-direction: column;
-		flex-wrap: wrap;
-		margin-left: 20px;
-		width: calc(100% - 130px - 34px);
-		height: 100%;
-
-		*:not(i) {
-			margin: 0;
-			font-family: Karla, Arial, sans-serif;
-		}
-
-		.song-details {
-			display: flex;
-			justify-content: center;
-			flex-direction: column;
-			flex-grow: 1;
-			width: 100%;
-
-			h6 {
-				color: var(--primary-color) !important;
-				font-weight: bold;
-				font-size: 17px;
-			}
-
-			.song-title {
-				margin-top: 7px;
-				font-size: 22px;
-				overflow: hidden;
-				text-overflow: ellipsis;
-				white-space: nowrap;
-			}
-
-			.song-artists {
-				font-size: 16px;
-				margin-bottom: 5px;
-				overflow: hidden;
-				text-overflow: ellipsis;
-				white-space: nowrap;
-			}
-
-			.song-request-time {
-				font-size: 12px;
-				margin-top: 7px;
-				color: var(--dark-grey);
-			}
-		}
-	}
-
-	.song-actions {
-		display: flex;
-		cursor: pointer;
-		color: var(--primary-color);
-
-		&:hover,
-		&:focus {
-			filter: brightness(90%);
-		}
-	}
-}
-</style>

+ 31 - 9
frontend/src/pages/Station/index.vue

@@ -420,7 +420,16 @@
 								class="quadrant"
 								:class="{ 'no-currently-playing': noSong }"
 							>
-								<currently-playing :song="currentSong" />
+								<song-item
+									:song="currentSong"
+									:duration="false"
+									:large-thumbnail="true"
+									:requested-by="
+										station.type === 'community' &&
+											station.partyMode === true
+									"
+									header="Currently Playing.."
+								/>
 								<!-- <p v-else class="nothing-here-text">
 								No song is currently playing
 							</p> -->
@@ -430,9 +439,15 @@
 								id="next-up-container"
 								class="quadrant"
 							>
-								<currently-playing
-									type="next"
+								<song-item
 									:song="nextSong"
+									:duration="false"
+									:large-thumbnail="true"
+									:requested-by="
+										station.type === 'community' &&
+											station.partyMode === true
+									"
+									header="Next Up.."
 								/>
 							</div>
 						</div>
@@ -628,13 +643,13 @@ import Z404 from "../404.vue";
 
 import FloatingBox from "../../components/ui/FloatingBox.vue";
 import AddToPlaylistDropdown from "../../components/ui/AddToPlaylistDropdown.vue";
+import SongItem from "../../components/ui/SongItem.vue";
 
 import ws from "../../ws";
 import keyboardShortcuts from "../../keyboardShortcuts";
 import utils from "../../../js/utils";
 
-import CurrentlyPlaying from "./components/CurrentlyPlaying.vue";
-import StationSidebar from "./components/Sidebar/index.vue";
+import StationSidebar from "./Sidebar/index.vue";
 
 export default {
 	components: {
@@ -642,18 +657,17 @@ export default {
 		MainHeader,
 		MainFooter,
 		SongQueue: () => import("../../components/modals/AddSongToQueue.vue"),
-		EditPlaylist: () =>
-			import("../../components/modals/EditPlaylist/index.vue"),
+		EditPlaylist: () => import("../../components/modals/EditPlaylist.vue"),
 		CreatePlaylist: () =>
 			import("../../components/modals/CreatePlaylist.vue"),
 		EditStation: () => import("../../components/modals/EditStation.vue"),
 		Report: () => import("../../components/modals/Report.vue"),
 		Z404,
 		FloatingBox,
-		CurrentlyPlaying,
 		StationSidebar,
 		AddToPlaylistDropdown,
-		EditSong: () => import("../../components/modals/EditSong.vue")
+		EditSong: () => import("../../components/modals/EditSong.vue"),
+		SongItem
 	},
 	data() {
 		return {
@@ -2056,6 +2070,14 @@ export default {
 			#next-up-container {
 				overflow: hidden;
 				flex-basis: 50%;
+				.song-item {
+					border: unset;
+					.thumbnail {
+						min-width: 130px !important;
+						width: 130px !important;
+						height: 130px !important;
+					}
+				}
 				.nothing-here-text {
 					height: 100%;
 				}

+ 2 - 0
musare.sh

@@ -1,5 +1,7 @@
 #!/bin/bash
 
+export PATH=/usr/local/bin:/usr/bin:/bin
+
 CYAN='\033[33;36m';
 RED='\033[0;31m'
 YELLOW='\033[0;93m'