| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 | <template>	<div>		<metadata title="Admin | Reports" />		<div class="container">			<table class="table is-striped">				<thead>					<tr>						<td>Song ID</td>						<td>Author</td>						<td>Time of report</td>						<td>Description</td>						<td>Options</td>					</tr>				</thead>				<tbody>					<tr v-for="(report, index) in reports" :key="index">						<td>							<span>								{{ report.song.songId }}								<br />								{{ report.song._id }}							</span>						</td>						<td>							<user-id-to-username								:userId="report.createdBy"								:link="true"							/>						</td>						<td>							<span :title="report.createdAt">{{								formatDistance(									new Date(report.createdAt),									new Date(),									{ addSuffix: true }								)							}}</span>						</td>						<td>							<span>{{ report.description }}</span>						</td>						<td>							<a								class="button is-warning"								href="#"								@click="view(report)"								>View</a							>							<a								class="button is-primary"								href="#"								@click="resolve(report._id)"								>Resolve</a							>						</td>					</tr>				</tbody>			</table>		</div>		<issues-modal v-if="modals.viewReport" />	</div></template><script>import { mapState, mapActions } from "vuex";import { formatDistance } from "date-fns";import Toast from "toasters";import io from "../../io";import IssuesModal from "../Modals/IssuesModal.vue";import UserIdToUsername from "../UserIdToUsername.vue";export default {	components: { IssuesModal, UserIdToUsername },	data() {		return {			reports: []		};	},	mounted() {		io.getSocket(socket => {			this.socket = socket;			if (this.socket.connected) this.init();			this.socket.emit("reports.index", res => {				this.reports = res.data;			});			this.socket.on("event:admin.report.resolved", reportId => {				this.reports = this.reports.filter(report => {					return report._id !== reportId;				});			});			this.socket.on("event:admin.report.created", report => {				this.reports.push(report);			});			io.onConnect(() => {				this.init();			});		});		if (this.$route.query.id) {			this.socket.emit("reports.findOne", this.$route.query.id, res => {				if (res.status === "success") this.view(res.data);				else					new Toast({						content: "Report with that ID not found",						timeout: 3000					});			});		}	},	computed: {		...mapState("modals", {			modals: state => state.modals.admin		})	},	methods: {		formatDistance,		init() {			this.socket.emit("apis.joinAdminRoom", "reports", () => {});		},		view(report) {			this.viewReport(report);			this.openModal({ sector: "admin", modal: "viewReport" });		},		resolve(reportId) {			return this.resolveReport(reportId)				.then(res => {					if (res.status === "success" && this.modals.viewReport)						this.closeModal({							sector: "admin",							modal: "viewReport"						});				})				.catch(					err => new Toast({ content: err.message, timeout: 5000 })				);		},		...mapActions("modals", ["openModal", "closeModal"]),		...mapActions("admin/reports", ["viewReport", "resolveReport"])	}};</script><style lang="scss" scoped>@import "styles/global.scss";.night-mode {	.table {		color: #ddd;		background-color: #222;		thead tr {			background: $night-mode-secondary;			td {				color: #fff;			}		}		tbody tr:hover {			background-color: #111 !important;		}		tbody tr:nth-child(even) {			background-color: #444;		}		strong {			color: #ddd;		}	}}.tag:not(:last-child) {	margin-right: 5px;}td {	word-wrap: break-word;	max-width: 10vw;	vertical-align: middle;}</style>
 |