Procházet zdrojové kódy

feat: Added remove functions and events for YouTube API requests

Owen Diffey před 2 roky
rodič
revize
72f51730f4

+ 3 - 1
backend/logic/actions/apis.js

@@ -132,6 +132,7 @@ export default {
 			room.startsWith("edit-song.") ||
 			room.startsWith("view-report.") ||
 			room.startsWith("edit-user.") ||
+			room.startsWith("view-api-request.") ||
 			room === "import-album" ||
 			room === "edit-songs"
 		) {
@@ -194,7 +195,8 @@ export default {
 			page === "playlists" ||
 			page === "users" ||
 			page === "statistics" ||
-			page === "punishments"
+			page === "punishments" ||
+			page === "youtube"
 		) {
 			WSModule.runJob("SOCKET_LEAVE_ROOMS", { socketId: session.socketId }).then(() => {
 				WSModule.runJob("SOCKET_JOIN_ROOM", {

+ 61 - 4
backend/logic/actions/youtube.js

@@ -9,6 +9,23 @@ import moduleManager from "../../index";
 const DBModule = moduleManager.modules.db;
 const UtilsModule = moduleManager.modules.utils;
 const YouTubeModule = moduleManager.modules.youtube;
+const WSModule = moduleManager.modules.ws;
+const CacheModule = moduleManager.modules.cache;
+
+CacheModule.runJob("SUB", {
+	channel: "youtube.removeYoutubeApiRequest",
+	cb: requestId => {
+		WSModule.runJob("EMIT_TO_ROOM", {
+			room: `view-api-request.${requestId}`,
+			args: ["event:youtubeApiRequest.removed"]
+		});
+
+		WSModule.runJob("EMIT_TO_ROOM", {
+			room: "admin.youtube",
+			args: ["event:admin.youtubeApiRequest.removed", { data: { requestId } }]
+		});
+	}
+});
 
 export default {
 	/**
@@ -128,15 +145,55 @@ export default {
 	 *
 	 * @returns {{status: string, data: object}}
 	 */
-	 resetStoredApiRequests: isAdminRequired(function resetStoredApiRequests(session, cb) {
+	resetStoredApiRequests: isAdminRequired(function resetStoredApiRequests(session, cb) {
 		YouTubeModule.runJob("RESET_STORED_API_REQUESTS", {}, this)
-			.then(response => {
-				this.log("SUCCESS", "YOUTUBE_RESET_STORED_API_REQUESTS", `Resetting stored API requests was successful.`);
+			.then(() => {
+				this.log(
+					"SUCCESS",
+					"YOUTUBE_RESET_STORED_API_REQUESTS",
+					`Resetting stored API requests was successful.`
+				);
 				return cb({ status: "success", message: "Successfully reset stored YouTube API requests" });
 			})
 			.catch(async err => {
 				err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
-				this.log("ERROR", "YOUTUBE_RESET_STORED_API_REQUESTS", `Resetting stored API requests failed. "${err}"`);
+				this.log(
+					"ERROR",
+					"YOUTUBE_RESET_STORED_API_REQUESTS",
+					`Resetting stored API requests failed. "${err}"`
+				);
+				return cb({ status: "error", message: err });
+			});
+	}),
+
+	/**
+	 * Remove stored API requests
+	 *
+	 * @returns {{status: string, data: object}}
+	 */
+	removeStoredApiRequest: isAdminRequired(function removeStoredApiRequest(session, requestId, cb) {
+		YouTubeModule.runJob("REMOVE_STORED_API_REQUEST", { requestId }, this)
+			.then(() => {
+				this.log(
+					"SUCCESS",
+					"YOUTUBE_REMOVE_STORED_API_REQUEST",
+					`Removing stored API request "${requestId}" was successful.`
+				);
+
+				CacheModule.runJob("PUB", {
+					channel: "youtube.removeYoutubeApiRequest",
+					value: requestId
+				});
+
+				return cb({ status: "success", message: "Successfully removed stored YouTube API request" });
+			})
+			.catch(async err => {
+				err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
+				this.log(
+					"ERROR",
+					"YOUTUBE_REMOVE_STORED_API_REQUEST",
+					`Removing stored API request "${requestId}" failed. "${err}"`
+				);
 				return cb({ status: "error", message: err });
 			});
 	})

+ 11 - 0
backend/logic/youtube.js

@@ -967,6 +967,17 @@ class _YouTubeModule extends CoreClass {
 			});
 		});
 	}
+
+	REMOVE_STORED_API_REQUEST(payload) {
+		return new Promise((resolve, reject) => {
+			YouTubeModule.youtubeApiRequestModel.deleteOne({_id: payload.requestId}, err => {
+				if (err) reject(new Error("Couldn't remove stored YouTube API request."));
+				else {
+					resolve();
+				}
+			});
+		});
+	}
 }
 
 export default new _YouTubeModule();

+ 38 - 1
frontend/src/components/modals/ViewApiRequest.vue

@@ -33,6 +33,11 @@
 				<p><b>Quota cost:</b> {{ request.quotaCost }}</p>
 			</div>
 		</template>
+		<template #footer>
+			<quick-confirm v-if="removeAction" @confirm="remove()">
+				<a class="button is-danger"> Remove API request</a>
+			</quick-confirm>
+		</template>
 	</modal>
 </template>
 
@@ -61,7 +66,8 @@ export default {
 	computed: {
 		...mapModalState("modals/viewApiRequest/MODAL_UUID", {
 			requestId: state => state.requestId,
-			request: state => state.request
+			request: state => state.request,
+			removeAction: state => state.removeAction
 		}),
 		...mapGetters({
 			socket: "websockets/getSocket"
@@ -71,6 +77,12 @@ export default {
 		ws.onConnect(this.init);
 	},
 	beforeUnmount() {
+		this.socket.dispatch(
+			"apis.leaveRoom",
+			`view-api-request.${this.requestId}`,
+			() => {}
+		);
+
 		// Delete the VueX module that was created for this modal, after all other cleanup tasks are performed
 		this.$store.unregisterModule([
 			"modals",
@@ -89,6 +101,20 @@ export default {
 						const { apiRequest } = res.data;
 						this.viewApiRequest(apiRequest);
 						this.loaded = true;
+
+						this.socket.dispatch(
+							"apis.joinRoom",
+							`view-api-request.${this.requestId}`
+						);
+
+						this.socket.on(
+							"event:youtubeApiRequest.removed",
+							() => {
+								new Toast("This API request was removed.");
+								this.closeCurrentModal();
+							},
+							{ modalUuid: this.modalUuid }
+						);
 					} else {
 						new Toast("API request with that ID not found");
 						this.closeCurrentModal();
@@ -96,6 +122,17 @@ export default {
 				}
 			);
 		},
+		remove() {
+			if (this.removeAction)
+				this.socket.dispatch(this.removeAction, this.requestId, res => {
+					if (res.status === "success") {
+						new Toast("API request successfully removed.");
+						this.closeCurrentModal();
+					} else {
+						new Toast("API request with that ID not found.");
+					}
+				});
+		},
 		...mapModalActions("modals/viewApiRequest/MODAL_UUID", [
 			"viewApiRequest"
 		]),

+ 35 - 3
frontend/src/pages/Admin/YouTube.vue

@@ -55,6 +55,7 @@
 				:column-default="columnDefault"
 				:columns="columns"
 				:filters="filters"
+				:events="events"
 				data-action="youtube.getApiRequests"
 				name="admin-youtube-api-requests"
 				:max-width="1140"
@@ -67,7 +68,9 @@
 								openModal({
 									modal: 'viewApiRequest',
 									data: {
-										requestId: slotProps.item._id
+										requestId: slotProps.item._id,
+										removeAction:
+											'youtube.removeStoredApiRequest'
 									}
 								})
 							"
@@ -77,6 +80,18 @@
 						>
 							open_in_full
 						</button>
+						<quick-confirm
+							@confirm="removeApiRequest(slotProps.item._id)"
+							:disabled="slotProps.item.removed"
+						>
+							<button
+								class="button is-danger icon-with-button material-icons"
+								content="Remove API Request"
+								v-tippy
+							>
+								delete_forever
+							</button>
+						</quick-confirm>
 					</div>
 				</template>
 				<template #column-_id="slotProps">
@@ -107,6 +122,8 @@
 <script>
 import { mapActions, mapGetters } from "vuex";
 
+import Toast from "toasters";
+
 import AdvancedTable from "@/components/AdvancedTable.vue";
 import RunJobDropdown from "@/components/RunJobDropdown.vue";
 import LineChart from "@/components/LineChart.vue";
@@ -137,10 +154,11 @@ export default {
 					name: "options",
 					displayName: "Options",
 					properties: ["_id"],
+					sortable: false,
 					hidable: false,
 					resizable: false,
-					minWidth: 76,
-					defaultWidth: 76
+					minWidth: 85,
+					defaultWidth: 85
 				},
 				{
 					name: "quotaCost",
@@ -209,6 +227,13 @@ export default {
 					defaultFilterType: "contains"
 				}
 			],
+			events: {
+				adminRoom: "youtube",
+				removed: {
+					event: "admin.youtubeApiRequest.removed",
+					id: "requestId"
+				}
+			},
 			charts: {
 				quotaUsage: {
 					labels: [
@@ -285,6 +310,13 @@ export default {
 			const minute = `${date.getMinutes()}`.padStart(2, 0);
 			return `${year}-${month}-${day} ${hour}:${minute}`;
 		},
+		removeApiRequest(requestId) {
+			this.socket.dispatch(
+				"youtube.removeStoredApiRequest",
+				requestId,
+				res => new Toast(res.message)
+			);
+		},
 		...mapActions("modalVisibility", ["openModal"])
 	}
 };

+ 4 - 2
frontend/src/store/modules/modals/viewApiRequest.js

@@ -4,7 +4,8 @@ export default {
 	namespaced: true,
 	state: {
 		requestId: null,
-		request: {}
+		request: {},
+		removeAction: null
 	},
 	getters: {},
 	actions: {
@@ -13,8 +14,9 @@ export default {
 			commit("viewApiRequest", request)
 	},
 	mutations: {
-		init(state, { requestId }) {
+		init(state, { requestId, removeAction }) {
 			state.requestId = requestId;
+			state.removeAction = removeAction;
 		},
 		viewApiRequest(state, request) {
 			state.request = request;