Browse Source

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

Kristian Vos 3 years ago
parent
commit
30533ce601

+ 4 - 2
backend/logic/actions/apis.js

@@ -131,7 +131,8 @@ export default {
 			room.startsWith("edit-song.") ||
 			room.startsWith("view-report.") ||
 			room.startsWith("edit-user.") ||
-			room === "import-album"
+			room === "import-album" ||
+			room === "edit-songs"
 		) {
 			WSModule.runJob("SOCKET_JOIN_ROOM", {
 				socketId: session.socketId,
@@ -160,7 +161,8 @@ export default {
 			room.startsWith("manage-station.") ||
 			room.startsWith("edit-song.") ||
 			room.startsWith("view-report.") ||
-			room === "import-album"
+			room === "import-album" ||
+			room === "edit-songs"
 		) {
 			WSModule.runJob("SOCKET_LEAVE_ROOM", {
 				socketId: session.socketId,

+ 2 - 2
backend/logic/actions/songs.js

@@ -23,7 +23,7 @@ CacheModule.runJob("SUB", {
 
 		songModel.findOne({ _id: data.songId }, (err, song) => {
 			WSModule.runJob("EMIT_TO_ROOMS", {
-				rooms: ["import-album", "admin.songs", `edit-song.${data.songId}`],
+				rooms: ["import-album", "admin.songs", `edit-song.${data.songId}`, "edit-songs"],
 				args: ["event:admin.song.updated", { data: { song, oldStatus: data.oldStatus } }]
 			});
 		});
@@ -34,7 +34,7 @@ CacheModule.runJob("SUB", {
 	channel: "song.removed",
 	cb: async data => {
 		WSModule.runJob("EMIT_TO_ROOMS", {
-			rooms: ["import-album", "admin.songs", `edit-song.${data.songId}`],
+			rooms: ["import-album", "admin.songs", `edit-song.${data.songId}`, "edit-songs"],
 			args: ["event:admin.song.removed", { data }]
 		});
 	}

+ 1 - 0
frontend/src/components/SongItem.vue

@@ -5,6 +5,7 @@
 		v-if="song"
 	>
 		<div class="thumbnail-and-info">
+			<slot v-if="$slots.leftIcon" name="leftIcon" />
 			<song-thumbnail :song="song" v-if="thumbnail" />
 			<div class="song-info">
 				<h6 v-if="header">{{ header }}</h6>

+ 14 - 4
frontend/src/components/modals/EditSong/index.vue

@@ -10,11 +10,11 @@
 				<slot name="sidebar" />
 			</template>
 			<template #body>
-				<div v-if="!songId">
-					<h1>No song has been selected</h1>
+				<div v-if="!songId" class="notice-container">
+					<h4>No song has been selected</h4>
 				</div>
-				<div v-if="songId && !songDataLoaded">
-					<h1>Song hasn't loaded yet</h1>
+				<div v-if="songId && !songDataLoaded" class="notice-container">
+					<h4>Song hasn't loaded yet</h4>
 				</div>
 				<div class="left-section" v-show="songDataLoaded">
 					<div class="top-section">
@@ -1677,6 +1677,16 @@ export default {
 	display: flex;
 }
 
+.notice-container {
+	display: flex;
+	flex: 1;
+	justify-content: center;
+
+	h4 {
+		margin: auto;
+	}
+}
+
 .left-section {
 	flex-basis: unset !important;
 	height: 100%;

+ 115 - 54
frontend/src/components/modals/EditSongs.vue

@@ -20,43 +20,78 @@
 						v-for="{ status, flagged, song } in items"
 						:key="song._id"
 					>
-						<i
-							class="material-icons item-icon editing-icon"
-							v-if="currentSong._id === song._id"
-							>edit</i
-						>
-						<i
-							class="material-icons item-icon error-icon"
-							v-else-if="status === 'error'"
-							>error</i
-						>
-						<i
-							class="material-icons item-icon saving-icon"
-							v-else-if="status === 'saving'"
-							>pending<!--or we can use change_circle--></i
-						>
-						<i
-							class="material-icons item-icon flag-icon"
-							v-else-if="flagged"
-							>flag_circle</i
-						>
-						<i
-							class="material-icons item-icon done-icon"
-							v-else-if="status === 'done'"
-							>check_circle</i
-						>
-						<i
-							class="material-icons item-icon todo-icon"
-							v-else-if="status === 'todo'"
-							>cancel</i
-						>
 						<song-item
 							:song="song"
 							:thumbnail="false"
 							:duration="false"
-							:disabled-actions="['report']"
+							:disabled-actions="
+								song.removed ? ['all'] : ['report', 'edit']
+							"
+							:class="{
+								updated: song.updated,
+								removed: song.removed
+							}"
 						>
-							<template #actions>
+							<template #leftIcon>
+								<i
+									v-if="currentSong._id === song._id"
+									class="
+										material-icons
+										item-icon
+										editing-icon
+									"
+									content="Currently editing song"
+									v-tippy="{ theme: 'info' }"
+									>edit</i
+								>
+								<i
+									v-else-if="song.removed"
+									class="
+										material-icons
+										item-icon
+										removed-icon
+									"
+									content="Song removed"
+									v-tippy="{ theme: 'info' }"
+									>delete_forever</i
+								>
+								<i
+									v-else-if="status === 'error'"
+									class="material-icons item-icon error-icon"
+									content="Error saving song"
+									v-tippy="{ theme: 'info' }"
+									>error</i
+								>
+								<i
+									v-else-if="status === 'saving'"
+									class="material-icons item-icon saving-icon"
+									content="Currently saving song"
+									v-tippy="{ theme: 'info' }"
+									>pending</i
+								>
+								<i
+									v-else-if="flagged"
+									class="material-icons item-icon flag-icon"
+									content="Song flagged"
+									v-tippy="{ theme: 'info' }"
+									>flag_circle</i
+								>
+								<i
+									v-else-if="status === 'done'"
+									class="material-icons item-icon done-icon"
+									content="Song marked complete"
+									v-tippy="{ theme: 'info' }"
+									>check_circle</i
+								>
+								<i
+									v-else-if="status === 'todo'"
+									class="material-icons item-icon todo-icon"
+									content="Song marked todo"
+									v-tippy="{ theme: 'info' }"
+									>cancel</i
+								>
+							</template>
+							<template v-if="!song.removed" #actions>
 								<i
 									class="material-icons edit-icon"
 									content="Edit Song"
@@ -130,6 +165,8 @@ export default {
 		})
 	},
 	async mounted() {
+		this.socket.dispatch("apis.joinRoom", "edit-songs");
+
 		this.socket.dispatch("songs.getSongsFromSongIds", this.songIds, res => {
 			res.data.songs.forEach(song => {
 				this.items.push({
@@ -139,6 +176,27 @@ export default {
 				});
 			});
 		});
+
+		this.socket.on(`event:admin.song.updated`, res => {
+			const index = this.items
+				.map(item => item.song._id)
+				.indexOf(res.data.song._id);
+			this.items[index].song = {
+				...this.items[index].song,
+				...res.data.song,
+				updated: true
+			};
+		});
+
+		this.socket.on(`event:admin.song.removed`, res => {
+			const index = this.items
+				.map(item => item.song._id)
+				.indexOf(res.songId);
+			this.items[index].song.removed = true;
+		});
+	},
+	beforeUnmount() {
+		this.socket.dispatch("apis.leaveRoom", "edit-songs");
 	},
 	methods: {
 		pickSong(song) {
@@ -261,33 +319,36 @@ export default {
 			align-items: center;
 			column-gap: 8px;
 
-			.item-icon {
-				font-size: 32px;
-				line-height: 32px;
-			}
-
-			.error-icon {
-				color: var(--red);
-			}
+			/deep/ .song-item {
+				.item-icon {
+					margin-right: 10px;
+					cursor: pointer;
+				}
 
-			.saving-icon {
-				color: var(--primary-color);
-			}
+				.removed-icon,
+				.error-icon {
+					color: var(--red);
+				}
 
-			.todo-icon {
-				color: var(--primary-color);
-			}
+				.saving-icon,
+				.todo-icon,
+				.editing-icon {
+					color: var(--primary-color);
+				}
 
-			.done-icon {
-				color: var(--green);
-			}
+				.done-icon {
+					color: var(--green);
+				}
 
-			.flag-icon {
-				color: var(--orange);
-			}
+				.flag-icon {
+					color: var(--orange);
+				}
 
-			.editing-icon {
-				color: var(--primary-color);
+				&.removed {
+					filter: grayscale(100%);
+					cursor: not-allowed;
+					user-select: none;
+				}
 			}
 		}
 	}

+ 3 - 3
frontend/src/main.js

@@ -176,14 +176,14 @@ router.beforeEach((to, from, next) => {
 	if (to.meta.loginRequired || to.meta.adminRequired || to.meta.guestsOnly) {
 		const gotData = () => {
 			if (to.meta.loginRequired && !store.state.user.auth.loggedIn)
-				next({ path: "/login" });
+				next({ path: "/login", query: "" });
 			else if (
 				to.meta.adminRequired &&
 				store.state.user.auth.role !== "admin"
 			)
-				next({ path: "/" });
+				next({ path: "/", query: "" });
 			else if (to.meta.guestsOnly && store.state.user.auth.loggedIn)
-				next({ path: "/" });
+				next({ path: "/", query: "" });
 			else next();
 		};