cubash-archive/frontend/src/components/routes/AdminModerationReports.vue

306 lines
8.6 KiB
Vue

<template>
<div class='admin_moderation'>
<moderation-header selected-tab='reports'></moderation-header>
<confirm-modal v-model='removePostObj.showConfirmModal' @confirm='removePost' text='Remove' color='red'>
Are you sure you want to remove this post?
</confirm-modal>
<confirm-modal v-model='removePostObj.showThreadDeleteModal' @confirm='deleteThread' text='Delete' color='red'>
Are you sure you want to delete the thread containing this post?
</confirm-modal>
<transition name='fade' mode='out-in'>
<loading-message v-if='!reports' key='loading'></loading-message>
<div
class='admin_moderation__reports'
v-else-if='filteredReports.length'
key='reports'
>
<div class='admin_moderation__report admin_moderation__report--header'>
<div class='admin_moderation__report__post admin_moderation__report--cell_border admin_moderation__report--cell_border-hidden'>
User and post reported
</div>
<div class='admin_moderation__report__reason admin_moderation__report--cell_border admin_moderation__report--cell_border-hidden'>Report reason</div>
<div class='admin_moderation__report__flagged_by admin_moderation__report--cell_border admin_moderation__report--cell_border-hidden'>
Reported by user
</div>
<div class='admin_moderation__report__actions'>
Actions
</div>
</div>
<div class='admin_moderation__report' :key='"report-" + $index' v-for='(report, $index) in filteredReports'>
<div class='admin_moderation__report__post admin_moderation__report--cell_border'>
<div class='admin_moderation__report__post__header'>
<avatar-icon class='admin_moderation__report__flagged_by__avatar' size='small' :user='report.Post.User'></avatar-icon>
<div>
<div class='admin_moderation__report__post__user'>{{report.PostUserUsername}}</div>
<div class='admin_moderation__report__flagged_by__date'>Posted {{report.createdAt| formatDate}}</div>
</div>
</div>
<div class='admin_moderation__report__post__content'>{{report.Post.content | stripTags | truncate(150)}}</div>
</div>
<div class='admin_moderation__report__reason admin_moderation__report--cell_border'>{{report.reason}}</div>
<div class='admin_moderation__report__flagged_by admin_moderation__report--cell_border'>
<avatar-icon class='admin_moderation__report__flagged_by__avatar' size='small' :user='report.FlaggedByUser'></avatar-icon>
<div class='admin_moderation__report__flagged_by__text_info'>
<div class='admin_moderation__report__flagged_by__user'>{{report.FlaggedByUserUsername}}</div>
<div class='admin_moderation__report__flagged_by__date'>{{report.createdAt| formatDate}}</div>
</div>
</div>
<div class='admin_moderation__report__actions'>
<button class='button button--red' @click='removePost(report, $index)'>Remove post</button>
<menu-button
@delete='deleteReport(report.id, $index)'
@ban='banUser(report, $index)'
@deleteThread='deleteThread(report, $index)'
:options='reportMenuOptions'
>
<button class='button'>More options&hellip;</button>
</menu-button>
</div>
</div>
</div>
<div class='overlay_message' v-else key='no reports'>
<font-awesome-icon :icon='["fa", "thumbs-up"]' />
No user reports
</div>
</transition>
</div>
</template>
<script>
import MenuButton from '../MenuButton'
import LoadingMessage from '../LoadingMessage'
import AvatarIcon from '../AvatarIcon'
import ConfirmModal from '../ConfirmModal'
import ModerationHeader from '../ModerationHeader'
import AjaxErrorHandler from '../../assets/js/errorHandler'
export default {
name: 'AdminDashboard',
components: {
MenuButton,
LoadingMessage,
AvatarIcon,
ConfirmModal,
ModerationHeader
},
data () {
return {
reportMenuOptions: [
{ value: "Delete report", event: 'delete' },
{ value: "Ban a user", event: 'ban' },
{ value: "Delete thread", event: 'deleteThread' }
],
reports: null,
removePostObj: {
showConfirmModal: false,
showThreadDeleteModal: false,
report: null,
index: null
}
}
},
computed: {
filteredReports () {
if (!this.reports) return null;
return this.reports
//Only show reports not already deleted
.filter(report => report.Post)
.map(report => {
let clone = Object.create(report);
//Provide username text if user deleted for post
//or flaggedByUser
if(!report.Post.User) {
clone.PostUserUsername = '[deleted]';
} else {
clone.PostUserUsername = report.Post.User.username;
}
if(!report.FlaggedByUser) {
clone.FlaggedByUserUsername = '[deleted]';
} else {
clone.FlaggedByUserUsername = report.FlaggedByUser.username;
}
return clone;
});
}
},
methods: {
deleteReport (id, index) {
return this.axios
.delete(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'users/report/' + id)
.then(() => {
this.reports.splice(index, 1)
})
.catch(AjaxErrorHandler(this.$store))
},
deleteThread (report, index) {
if(report) {
this.removePostObj.report = report
this.removePostObj.index = index
this.removePostObj.showThreadDeleteModal = true
} else {
let threadId = this.removePostObj.report.Post.Thread.id
this.axios
.delete(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/thread/' + threadId)
.then(() => {
//Get reports with id of deleted thread
//and remove them locally
this.reports = this.reports.filter(report => {
return report.Post.Thread.id !== threadId
})
})
.catch(AjaxErrorHandler(this.$store))
}
},
removePost (report, index) {
if(report) {
this.removePostObj.report = report
this.removePostObj.index = index
this.removePostObj.showConfirmModal = true
} else {
this.axios
.delete(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/post/' + this.removePostObj.report.Post.id)
.then(() => {
return this.axios.delete(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'users/report/' + this.removePostObj.report.id)
})
.then(() => {
this.reports.splice(this.removePostObj.index, 1)
})
.catch(AjaxErrorHandler(this.$store))
}
},
banUser (report) {
this.$router.push('bans')
setTimeout(() => {
this.$store.commit('moderation/setModal', true)
this.$store.commit('moderation/setUsername', report.Post.User.username)
}, 0)
}
},
mounted () {
this.$store.dispatch('setTitle', 'Moderation - Admin')
this.axios
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'users/report')
.then(res => {
this.reports = res.data
})
.catch(AjaxErrorHandler(this.$store))
}
}
</script>
<style lang='scss' scoped>
@import '../../assets/scss/variables.scss';
.admin_moderation {
padding: 2rem;
padding-top: 1rem;
@at-root #{&}__reports {
margin-top: 1rem;
border: thin solid $color__gray--darker;
border-radius: 0.25rem;
&> :first-child {
border-radius: 0.25rem 0.25rem 0 0;
}
&> :last-child {
border-radius: 0 0 0.25rem 0.25rem;
}
}
@at-root #{&}__report {
display: flex;
background-color: #fff;
border-bottom: thin solid $color__lightgray--darkest;
padding: 0.5rem;
@at-root #{&}--header {
font-weight: bold;
}
@at-root #{&}--cell_border {
padding-right: 0.5rem;
margin-right: 0.5rem;
border-right: thin solid $color__lightgray--darkest;
@at-root #{&}-hidden {
border-right-color: transparent;
}
}
@at-root #{&}__post {
width: 35%;
display: flex;
@at-root #{&}__header {
display: flex;
justify-content: space-between;
border-right: thin solid $color__lightgray--darker;
padding-right: 0.25rem;
}
@at-root #{&}__thread {
font-size: 1rem;
text-decoration: underline;
}
@at-root #{&}__content {
padding-left: 0.25rem;
}
}
@at-root #{&}__reason {
width: 15%;
}
@at-root #{&}__flagged_by {
width: 20%;
display: flex;
@at-root #{&}__text_info {
margin-left: 0.5rem;
display: flex;
flex-direction: column;
}
@at-root #{&}__date {
color: $color__darkgray--primary;
}
}
@at-root #{&}__actions {
width: 30%;
display: flex;
align-items: center;
.button--red {
margin-right: 0.5rem;
}
}
}
@at-root #{&}__header {
display: flex;
justify-content: space-between;
align-items: center;
}
}
</style>