Ver Fonte

refactor(Admin/YouTube): Integrated advanced table for api requests

Owen Diffey há 2 anos atrás
pai
commit
c929a5a0ab

+ 53 - 13
backend/logic/actions/youtube.js

@@ -1,10 +1,12 @@
 import mongoose from "mongoose";
+import async from "async";
 
 import { isAdminRequired } from "./hooks";
 
 // eslint-disable-next-line
 import moduleManager from "../../index";
 
+const DBModule = moduleManager.modules.db;
 const UtilsModule = moduleManager.modules.utils;
 const YouTubeModule = moduleManager.modules.youtube;
 
@@ -28,21 +30,59 @@ export default {
 	}),
 
 	/**
-	 * Returns api requests
+	 * Gets api requests, used in the admin youtube page by the AdvancedTable component
 	 *
-	 * @returns {{status: string, data: object}}
+	 * @param {object} session - the session object automatically added by the websocket
+	 * @param page - the page
+	 * @param pageSize - the size per page
+	 * @param properties - the properties to return for each news item
+	 * @param sort - the sort object
+	 * @param queries - the queries array
+	 * @param operator - the operator for queries
+	 * @param cb
 	 */
-	getApiRequests: isAdminRequired(function getApiRequests(session, fromDate, cb) {
-		YouTubeModule.runJob("GET_API_REQUESTS", { fromDate }, this)
-			.then(response => {
-				this.log("SUCCESS", "YOUTUBE_GET_API_REQUESTS", `Getting api requests was successful.`);
-				return cb({ status: "success", data: { apiRequests: response.apiRequests } });
-			})
-			.catch(async err => {
-				err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
-				this.log("ERROR", "YOUTUBE_GET_API_REQUESTS", `Getting api requests failed. "${err}"`);
-				return cb({ status: "error", message: err });
-			});
+	 getApiRequests: isAdminRequired(async function getApiRequests(session, page, pageSize, properties, sort, queries, operator, cb) {
+		async.waterfall(
+			[
+				next => {
+					DBModule.runJob(
+						"GET_DATA",
+						{
+							page,
+							pageSize,
+							properties,
+							sort,
+							queries,
+							operator,
+							modelName: "youtubeApiRequest",
+							blacklistedProperties: [],
+							specialProperties: {},
+							specialQueries: {}
+						},
+						this
+					)
+						.then(response => {
+							next(null, response);
+						})
+						.catch(err => {
+							next(err);
+						});
+				}
+			],
+			async (err, response) => {
+				if (err && err !== true) {
+					err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
+					this.log("ERROR", "YOUTUBE_GET_API_REQUESTS", `Failed to get YouTube api requests. "${err}"`);
+					return cb({ status: "error", message: err });
+				}
+				this.log("SUCCESS", "YOUTUBE_GET_API_REQUESTS", `Fetched YouTube api requests successfully.`);
+				return cb({
+					status: "success",
+					message: "Successfully fetched YouTube api requests.",
+					data: response
+				});
+			}
+		);
 	}),
 
 	/**

+ 1 - 1
frontend/src/pages/Admin/Songs/Import.vue

@@ -1,6 +1,6 @@
 <template>
 	<div>
-		<divage-metadata title="Admin | Songs | Import" />
+		<page-metadata title="Admin | Songs | Import" />
 		<div class="admin-tab import-tab">
 			<div class="card">
 				<h1>Import Songs</h1>

+ 151 - 49
frontend/src/pages/Admin/YouTube.vue

@@ -30,42 +30,55 @@
 		<div class="card">
 			<h4>API Requests</h4>
 			<hr class="section-horizontal-rule" />
-			<div class="card-content">
-				<p v-if="fromDate">As of {{ fromDate }}</p>
-				<table class="table">
-					<thead>
-						<tr>
-							<th>Date</th>
-							<th>Quota cost</th>
-							<th>URL</th>
-							<th>Request ID</th>
-						</tr>
-					</thead>
-					<tbody>
-						<tr
-							v-for="apiRequest in apiRequests"
-							:key="apiRequest._id"
+			<advanced-table
+				:column-default="columnDefault"
+				:columns="columns"
+				:filters="filters"
+				data-action="youtube.getApiRequests"
+				name="admin-youtube-api-requests"
+				:max-width="1140"
+			>
+				<template #column-options="slotProps">
+					<div class="row-options">
+						<button
+							class="button is-primary icon-with-button material-icons"
+							@click="
+								openModal({
+									modal: 'viewApiRequest',
+									data: {
+										requestId: slotProps.item._id
+									}
+								})
+							"
+							:disabled="slotProps.item.removed"
+							content="View API Request"
+							v-tippy
 						>
-							<td>
-								<router-link
-									:to="`?fromDate=${apiRequest.date}`"
-								>
-									{{ apiRequest.date }}
-								</router-link>
-							</td>
-							<td>{{ apiRequest.quotaCost }}</td>
-							<td>{{ apiRequest.url }}</td>
-							<td>
-								<router-link
-									:to="`?apiRequestId=${apiRequest._id}`"
-								>
-									{{ apiRequest._id }}
-								</router-link>
-							</td>
-						</tr>
-					</tbody>
-				</table>
-			</div>
+							open_in_full
+						</button>
+					</div>
+				</template>
+				<template #column-_id="slotProps">
+					<span :title="slotProps.item._id">{{
+						slotProps.item._id
+					}}</span>
+				</template>
+				<template #column-quotaCost="slotProps">
+					<span :title="slotProps.item.quotaCost">{{
+						slotProps.item.quotaCost
+					}}</span>
+				</template>
+				<template #column-timestamp="slotProps">
+					<span :title="new Date(slotProps.item.date)">{{
+						getDateFormatted(slotProps.item.date)
+					}}</span>
+				</template>
+				<template #column-url="slotProps">
+					<span :title="slotProps.item.url">{{
+						slotProps.item.url
+					}}</span>
+				</template>
+			</advanced-table>
 		</div>
 		<div class="card" v-if="currentApiRequest">
 			<h4>API Request</h4>
@@ -106,20 +119,108 @@
 import VueJsonPretty from "vue-json-pretty";
 import "vue-json-pretty/lib/styles.css";
 
-import { mapGetters } from "vuex";
+import { mapActions, mapGetters } from "vuex";
+
+import AdvancedTable from "@/components/AdvancedTable.vue";
 
 import ws from "@/ws";
 
 export default {
 	components: {
-		VueJsonPretty
+		VueJsonPretty,
+		AdvancedTable
 	},
 	data() {
 		return {
 			quotaStatus: {},
-			apiRequests: [],
 			currentApiRequest: null,
-			fromDate: null
+			fromDate: null,
+			columnDefault: {
+				sortable: true,
+				hidable: true,
+				defaultVisibility: "shown",
+				draggable: true,
+				resizable: true,
+				minWidth: 150,
+				maxWidth: 600
+			},
+			columns: [
+				{
+					name: "options",
+					displayName: "Options",
+					properties: ["_id"],
+					hidable: false,
+					resizable: false,
+					minWidth: 76,
+					defaultWidth: 76
+				},
+				{
+					name: "quotaCost",
+					displayName: "Quota Cost",
+					properties: ["quotaCost"],
+					sortProperty: ["quotaCost"],
+					minWidth: 150,
+					defaultWidth: 150
+				},
+				{
+					name: "timestamp",
+					displayName: "Timestamp",
+					properties: ["date"],
+					sortProperty: ["date"],
+					minWidth: 150,
+					defaultWidth: 150
+				},
+				{
+					name: "url",
+					displayName: "URL",
+					properties: ["url"],
+					sortProperty: ["url"]
+				},
+				{
+					name: "_id",
+					displayName: "Request ID",
+					properties: ["_id"],
+					sortProperty: ["_id"],
+					minWidth: 230,
+					defaultWidth: 230
+				}
+			],
+			filters: [
+				{
+					name: "_id",
+					displayName: "Request ID",
+					property: "_id",
+					filterTypes: ["exact"],
+					defaultFilterType: "exact"
+				},
+				{
+					name: "quotaCost",
+					displayName: "Quota Cost",
+					property: "quotaCost",
+					filterTypes: [
+						"numberLesserEqual",
+						"numberLesser",
+						"numberGreater",
+						"numberGreaterEqual",
+						"numberEquals"
+					],
+					defaultFilterType: "numberLesser"
+				},
+				{
+					name: "timestamp",
+					displayName: "Timestamp",
+					property: "date",
+					filterTypes: ["datetimeBefore", "datetimeAfter"],
+					defaultFilterType: "datetimeBefore"
+				},
+				{
+					name: "url",
+					displayName: "URL",
+					property: "url",
+					filterTypes: ["contains", "exact", "regex"],
+					defaultFilterType: "contains"
+				}
+			]
 		};
 	},
 	computed: mapGetters({
@@ -142,15 +243,6 @@ export default {
 				}
 			);
 
-			this.socket.dispatch(
-				"youtube.getApiRequests",
-				this.fromDate,
-				res => {
-					if (res.status === "success")
-						this.apiRequests = res.data.apiRequests;
-				}
-			);
-
 			if (this.$route.query.apiRequestId) {
 				this.socket.dispatch(
 					"youtube.getApiRequest",
@@ -164,7 +256,17 @@ export default {
 		},
 		round(number) {
 			return Math.round(number);
-		}
+		},
+		getDateFormatted(createdAt) {
+			const date = new Date(createdAt);
+			const year = date.getFullYear();
+			const month = `${date.getMonth() + 1}`.padStart(2, 0);
+			const day = `${date.getDate()}`.padStart(2, 0);
+			const hour = `${date.getHours()}`.padStart(2, 0);
+			const minute = `${date.getMinutes()}`.padStart(2, 0);
+			return `${year}-${month}-${day} ${hour}:${minute}`;
+		},
+		...mapActions("modalVisibility", ["openModal"])
 	}
 };
 </script>

+ 1 - 1
frontend/src/pages/Admin/index.vue

@@ -204,7 +204,7 @@
 									onShow: () => !sidebarActive
 								}"
 							>
-								<i class="material-icons">circle</i>
+								<i class="material-icons">smart_display</i>
 								<span>YouTube</span>
 							</router-link>
 						</div>

+ 1 - 0
frontend/src/store/modules/admin.js

@@ -69,6 +69,7 @@ export default {
 	namespaced: true,
 	state: {
 		childrenActive: {
+			songs: false,
 			users: false
 		}
 	},