Browse Source

refactor(Reports): added ReportInfoItem component and re-used 'universal item' css

Signed-off-by: Jonathan <theflametrooper@gmail.com>
Jonathan 3 years ago
parent
commit
909944f607

+ 33 - 21
backend/logic/actions/reports.js

@@ -135,17 +135,23 @@ export default {
 					userModel
 						.findById(report.createdBy)
 						.select({ avatar: -1, name: -1, username: -1 })
-						.exec((err, { avatar, name, username }) =>
-							next(err, {
-								...report._doc,
-								createdBy: {
-									avatar,
-									name,
-									username,
-									_id: report.createdBy
-								}
-							})
-						)
+						.exec((err, user) => {
+							if (!user)
+								next(err, {
+									...report._doc,
+									createdBy: { _id: report.createdBy }
+								});
+							else
+								next(err, {
+									...report._doc,
+									createdBy: {
+										avatar: user.avatar,
+										name: user.name,
+										username: user.username,
+										_id: report.createdBy
+									}
+								});
+						})
 			],
 			async (err, report) => {
 				if (err) {
@@ -185,16 +191,22 @@ export default {
 							userModel
 								.findById(report.createdBy)
 								.select({ avatar: -1, name: -1, username: -1 })
-								.exec((err, { avatar, name, username }) => {
-									reports.push({
-										...report._doc,
-										createdBy: {
-											avatar,
-											name,
-											username,
-											_id: report.createdBy
-										}
-									});
+								.exec((err, user) => {
+									if (!user)
+										next(err, {
+											...report._doc,
+											createdBy: { _id: report.createdBy }
+										});
+									else
+										next(err, {
+											...report._doc,
+											createdBy: {
+												avatar: user.avatar,
+												name: user.name,
+												username: user.username,
+												_id: report.createdBy
+											}
+										});
 
 									return cb(err);
 								});

+ 87 - 0
frontend/src/components/ReportInfoItem.vue

@@ -0,0 +1,87 @@
+<template>
+	<div class="universal-item report-info-item">
+		<div class="item-icon">
+			<profile-picture
+				:avatar="createdBy.avatar"
+				:name="createdBy.name ? createdBy.name : createdBy.username"
+				v-if="createdBy.avatar"
+			/>
+			<i class="material-icons" v-else>person_remove</i>
+		</div>
+
+		<div class="item-title-description">
+			<p class="item-title">
+				Reported by
+				<router-link
+					v-if="createdBy.username"
+					:to="{
+						path: `/u/${createdBy.username}`
+					}"
+					:title="createdBy._id"
+				>
+					{{ createdBy.username }}
+				</router-link>
+				<span v-else :title="createdBy._id">Deleted User</span>
+			</p>
+			<p class="item-description">
+				{{
+					formatDistance(new Date(createdAt), new Date(), {
+						addSuffix: true
+					})
+				}}
+			</p>
+		</div>
+
+		<div class="universal-item-actions">
+			<slot name="actions" />
+		</div>
+	</div>
+</template>
+
+<script>
+import { formatDistance } from "date-fns";
+import ProfilePicture from "@/components/ProfilePicture.vue";
+
+export default {
+	components: { ProfilePicture },
+	props: {
+		createdBy: { type: Object, default: () => {} },
+		createdAt: { type: String, default: "" }
+	},
+	methods: {
+		formatDistance
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.report-info-item {
+	.item-icon {
+		min-width: 45px;
+		max-width: 45px;
+		height: 45px;
+		margin-right: 10px;
+
+		.profile-picture,
+		i {
+			width: 45px;
+			height: 45px;
+		}
+
+		i {
+			font-size: 30px;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+		}
+	}
+
+	.item-title {
+		font-size: 14px;
+	}
+
+	.item-description {
+		font-size: 12px;
+	}
+}
+</style>

+ 23 - 117
frontend/src/components/modals/EditSong/Tabs/Reports.vue

@@ -26,24 +26,16 @@
 					v-for="(issues, category) in sortedByCategory"
 					:key="category"
 				>
-					<div class="report-item-header">
-						<div class="report-item-info">
-							<div class="report-item-icon">
-								<i
-									class="material-icons"
-									:content="category"
-									v-tippy="{ theme: 'info' }"
-								>
-									{{ icons[category] }}
-								</i>
-							</div>
+					<div class="report-item-header universal-item">
+						<i
+							class="material-icons"
+							:content="category"
+							v-tippy="{ theme: 'info' }"
+						>
+							{{ icons[category] }}
+						</i>
 
-							<div class="report-item-summary">
-								<p class="report-item-summary-title">
-									{{ category }} Issues
-								</p>
-							</div>
-						</div>
+						<p>{{ category }} Issues</p>
 					</div>
 					<div class="report-sub-items">
 						<div
@@ -117,52 +109,11 @@
 					v-for="report in reports"
 					:key="report._id"
 				>
-					<div class="report-item-header">
-						<div class="report-item-info">
-							<div class="report-item-icon">
-								<profile-picture
-									v-if="report.createdBy.avatar"
-									:avatar="report.createdBy.avatar"
-									:name="
-										report.createdBy.name
-											? report.createdBy.name
-											: report.createdBy.username
-									"
-								/>
-							</div>
-
-							<div class="report-item-summary">
-								<p class="report-item-summary-title">
-									Reported by
-									<router-link
-										v-if="report.createdBy.username"
-										:to="{
-											path: `/u/${report.createdBy.username}`
-										}"
-										:title="report.createdBy._id"
-										@click="closeModal('editSong')"
-									>
-										{{ report.createdBy.username }}
-									</router-link>
-									<span v-else>{{
-										report.createdBy._id
-									}}</span>
-								</p>
-								<p class="report-item-summary-description">
-									{{
-										formatDistance(
-											parseISO(report.createdAt),
-											new Date(),
-											{
-												addSuffix: true
-											}
-										)
-									}}
-								</p>
-							</div>
-						</div>
-
-						<div class="report-item-actions universal-item-actions">
+					<report-info-item
+						:created-at="report.createdAt"
+						:created-by="report.createdBy"
+					>
+						<template #actions>
 							<i
 								class="material-icons resolve-icon"
 								content="Resolve all"
@@ -171,8 +122,9 @@
 							>
 								done_all
 							</i>
-						</div>
-					</div>
+						</template>
+					</report-info-item>
+
 					<div class="report-sub-items">
 						<div
 							class="report-sub-item report-sub-item-unresolved"
@@ -236,14 +188,12 @@
 </template>
 
 <script>
-import ProfilePicture from "@/components/ProfilePicture.vue";
-
+import ReportInfoItem from "@/components/ReportInfoItem.vue";
 import { mapState, mapGetters, mapActions } from "vuex";
-import { formatDistance, parseISO } from "date-fns";
 import Toast from "toasters";
 
 export default {
-	components: { ProfilePicture },
+	components: { ReportInfoItem },
 	data() {
 		return {
 			tab: "sort-by-report",
@@ -336,8 +286,6 @@ export default {
 				}
 			);
 		},
-		formatDistance,
-		parseISO,
 		...mapActions("modals/editSong", ["resolveReport"]),
 		...mapActions("modalVisibility", ["closeModal"])
 	}
@@ -408,53 +356,11 @@ export default {
 		}
 
 		.report-item-header {
-			display: flex;
-			align-items: center;
-			justify-content: space-between;
-			margin-bottom: 8px;
-			background-color: var(--light-grey);
-			padding: 5px;
-			border-radius: 5px;
-
-			.report-item-info {
-				display: flex;
-				align-items: center;
-
-				.report-item-icon {
-					display: flex;
-					align-items: center;
-
-					.profile-picture,
-					i {
-						margin-right: 10px;
-						width: 45px;
-						height: 45px;
-					}
-
-					i {
-						font-size: 30px;
-						display: flex;
-						align-items: center;
-						justify-content: center;
-					}
-				}
-
-				.report-item-summary {
-					.report-item-summary-title {
-						font-size: 14px;
-						text-transform: capitalize;
-					}
-
-					.report-item-summary-description {
-						text-transform: capitalize;
-						font-size: 12px;
-					}
-				}
-			}
+			justify-content: center;
+			text-transform: capitalize;
 
-			.report-item-actions {
-				height: 24px;
-				margin-right: 4px;
+			i {
+				margin-right: 5px;
 			}
 		}
 

+ 19 - 113
frontend/src/components/modals/ViewReport.vue

@@ -1,60 +1,11 @@
 <template>
-	<modal title="View Report">
+	<modal class="view-report-modal" title="View Report">
 		<template #body v-if="report && report._id">
 			<div class="report-item">
-				<div class="report-item-header">
-					<div class="report-item-info">
-						<div class="report-item-icon">
-							<profile-picture
-								v-if="report.createdBy.avatar"
-								:avatar="report.createdBy.avatar"
-								:name="
-									report.createdBy.name
-										? report.createdBy.name
-										: report.createdBy.username
-								"
-							/>
-						</div>
-
-						<div class="report-item-summary">
-							<p class="report-item-summary-title">
-								Reported by
-								<router-link
-									v-if="report.createdBy.username"
-									:to="{
-										path: `/u/${report.createdBy.username}`
-									}"
-									:title="report.createdBy._id"
-								>
-									{{ report.createdBy.username }}
-								</router-link>
-								<span v-else>{{ report.createdBy._id }}</span>
-							</p>
-							<p class="report-item-summary-description">
-								{{
-									formatDistance(
-										new Date(report.createdAt),
-										new Date(),
-										{
-											addSuffix: true
-										}
-									)
-								}}
-								/ YouTube:
-								<a
-									:href="
-										'https://www.youtube.com/watch?v=' +
-											`${report.song.youtubeId}`
-									"
-									target="_blank"
-								>
-									{{ report.song.youtubeId }}</a
-								>
-								/ Song ID: {{ report.song._id }}
-							</p>
-						</div>
-					</div>
-				</div>
+				<report-info-item
+					:created-at="report.createdAt"
+					:created-by="report.createdBy"
+				/>
 				<div class="report-sub-items">
 					<div
 						class="report-sub-item report-sub-item-unresolved"
@@ -139,14 +90,13 @@
 
 <script>
 import { mapActions, mapGetters } from "vuex";
-import { formatDistance } from "date-fns";
 import Toast from "toasters";
 
-import ProfilePicture from "@/components/ProfilePicture.vue";
-import Modal from "../Modal.vue";
+import Modal from "@/components/Modal.vue";
+import ReportInfoItem from "@/components/ReportInfoItem.vue";
 
 export default {
-	components: { Modal, ProfilePicture },
+	components: { Modal, ReportInfoItem },
 	props: {
 		reportId: { type: String, default: "" },
 		sector: { type: String, default: "admin" }
@@ -210,7 +160,6 @@ export default {
 		this.socket.dispatch("apis.leaveRoom", `view-report.${this.reportId}`);
 	},
 	methods: {
-		formatDistance,
 		resolve(reportId) {
 			return this.resolveReport(reportId)
 				.then(res => {
@@ -239,6 +188,17 @@ export default {
 };
 </script>
 
+<style lang="scss">
+.view-report-modal .modal-card {
+	width: auto;
+
+	.modal-card-body {
+		display: flex;
+		justify-content: center;
+	}
+}
+</style>
+
 <style lang="scss" scoped>
 .night-mode {
 	.report-item {
@@ -260,60 +220,6 @@ export default {
 		margin-bottom: 16px;
 	}
 
-	.report-item-header {
-		display: flex;
-		align-items: center;
-		justify-content: space-between;
-		margin-bottom: 8px;
-		background-color: var(--light-grey);
-		// padding: 5px;
-		padding: 10px;
-		border-radius: 5px;
-
-		.report-item-info {
-			display: flex;
-			align-items: center;
-
-			.report-item-icon {
-				display: flex;
-				align-items: center;
-
-				.profile-picture,
-				i {
-					margin-right: 10px;
-					width: 45px;
-					height: 45px;
-				}
-
-				i {
-					font-size: 30px;
-					display: flex;
-					align-items: center;
-					justify-content: center;
-				}
-			}
-
-			.report-item-summary {
-				.report-item-summary-title {
-					// font-size: 14px;
-					font-size: 16px;
-					text-transform: capitalize;
-				}
-
-				.report-item-summary-description {
-					text-transform: capitalize;
-					// font-size: 12px;
-					font-size: 14px;
-				}
-			}
-		}
-
-		.report-item-actions {
-			height: 24px;
-			margin-right: 4px;
-		}
-	}
-
 	.report-sub-items {
 		.report-sub-item {
 			border: 0.5px solid var(--black);

+ 6 - 96
frontend/src/pages/Admin/tabs/Reports.vue

@@ -14,52 +14,10 @@
 				<tbody>
 					<tr v-for="report in reports" :key="report._id">
 						<td>
-							<div class="report-item-header">
-								<div class="report-item-info">
-									<div class="report-item-icon">
-										<profile-picture
-											v-if="report.createdBy.avatar"
-											:avatar="report.createdBy.avatar"
-											:name="
-												report.createdBy.name
-													? report.createdBy.name
-													: report.createdBy.username
-											"
-										/>
-									</div>
-
-									<div class="report-item-summary">
-										<p class="report-item-summary-title">
-											Reported by
-											<router-link
-												v-if="report.createdBy.username"
-												:to="{
-													path: `/u/${report.createdBy.username}`
-												}"
-												:title="report.createdBy._id"
-											>
-												{{ report.createdBy.username }}
-											</router-link>
-											<span v-else>{{
-												report.createdBy._id
-											}}</span>
-										</p>
-										<p
-											class="report-item-summary-description"
-										>
-											{{
-												formatDistance(
-													new Date(report.createdAt),
-													new Date(),
-													{
-														addSuffix: true
-													}
-												)
-											}}
-										</p>
-									</div>
-								</div>
-							</div>
+							<report-info-item
+								:created-at="report.createdAt"
+								:created-by="report.createdBy"
+							/>
 						</td>
 						<td>
 							<span>
@@ -131,12 +89,11 @@
 </template>
 
 <script>
+import ReportInfoItem from "@/components/ReportInfoItem.vue";
 import { mapState, mapActions, mapGetters } from "vuex";
-import { formatDistance } from "date-fns";
 import { defineAsyncComponent } from "vue";
 
 import Toast from "toasters";
-import ProfilePicture from "@/components/ProfilePicture.vue";
 import ws from "@/ws";
 
 export default {
@@ -147,7 +104,7 @@ export default {
 		EditSong: defineAsyncComponent(() =>
 			import("@/components/modals/EditSong/index.vue")
 		),
-		ProfilePicture
+		ReportInfoItem
 	},
 	data() {
 		return {
@@ -193,7 +150,6 @@ export default {
 		// }
 	},
 	methods: {
-		formatDistance,
 		init() {
 			this.socket.dispatch("apis.joinAdminRoom", "reports", () => {});
 		},
@@ -275,50 +231,4 @@ td {
 li {
 	list-style: inside;
 }
-
-.report-item-header {
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	margin-bottom: 8px;
-	background-color: var(--light-grey);
-	padding: 5px;
-	border-radius: 5px;
-
-	.report-item-info {
-		display: flex;
-		align-items: center;
-
-		.report-item-icon {
-			display: flex;
-			align-items: center;
-
-			.profile-picture,
-			i {
-				margin-right: 10px;
-				width: 45px;
-				height: 45px;
-			}
-
-			i {
-				font-size: 30px;
-				display: flex;
-				align-items: center;
-				justify-content: center;
-			}
-		}
-
-		.report-item-summary {
-			.report-item-summary-title {
-				font-size: 14px;
-				text-transform: capitalize;
-			}
-
-			.report-item-summary-description {
-				text-transform: capitalize;
-				font-size: 12px;
-			}
-		}
-	}
-}
 </style>