Extract dropdown for moderating users into separate component and rename timeline item to report
This commit is contained in:
parent
47e60b11a7
commit
c9e9b62955
4 changed files with 153 additions and 93 deletions
86
src/views/reports/components/ModerateUserDropdown.vue
Normal file
86
src/views/reports/components/ModerateUserDropdown.vue
Normal file
|
@ -0,0 +1,86 @@
|
|||
<template>
|
||||
<el-dropdown trigger="click">
|
||||
<el-button plain size="small" icon="el-icon-files">{{ $t('reports.moderateUser') }}
|
||||
<i class="el-icon-arrow-down el-icon--right"/>
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item
|
||||
v-if="showDeactivatedButton(report.account)"
|
||||
@click.native="handleDeactivation(report.account)">
|
||||
{{ report.account.deactivated ? $t('users.activateAccount') : $t('users.deactivateAccount') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="showDeactivatedButton(report.account.id)"
|
||||
@click.native="handleDeletion(report.account.id)">
|
||||
{{ $t('users.deleteAccount') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:divided="true"
|
||||
:class="{ 'active-tag': report.account.tags.includes('force_nsfw') }"
|
||||
@click.native="toggleTag(report.account, 'force_nsfw')">
|
||||
{{ $t('users.forceNsfw') }}
|
||||
<i v-if="report.account.tags.includes('force_nsfw')" class="el-icon-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:class="{ 'active-tag': report.account.tags.includes('strip_media') }"
|
||||
@click.native="toggleTag(report.account, 'strip_media')">
|
||||
{{ $t('users.stripMedia') }}
|
||||
<i v-if="report.account.tags.includes('strip_media')" class="el-icon-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:class="{ 'active-tag': report.account.tags.includes('force_unlisted') }"
|
||||
@click.native="toggleTag(report.account, 'force_unlisted')">
|
||||
{{ $t('users.forceUnlisted') }}
|
||||
<i v-if="report.account.tags.includes('force_unlisted')" class="el-icon-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:class="{ 'active-tag': report.account.tags.includes('sandbox') }"
|
||||
@click.native="toggleTag(report.account, 'sandbox')">
|
||||
{{ $t('users.sandbox') }}
|
||||
<i v-if="report.account.tags.includes('sandbox')" class="el-icon-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="report.account.local"
|
||||
:class="{ 'active-tag': report.account.tags.includes('disable_remote_subscription') }"
|
||||
@click.native="toggleTag(report.account, 'disable_remote_subscription')">
|
||||
{{ $t('users.disableRemoteSubscription') }}
|
||||
<i v-if="report.account.tags.includes('disable_remote_subscription')" class="el-icon-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="report.account.local"
|
||||
:class="{ 'active-tag': report.account.tags.includes('disable_any_subscription') }"
|
||||
@click.native="toggleTag(report.account, 'disable_any_subscription')">
|
||||
{{ $t('users.disableAnySubscription') }}
|
||||
<i v-if="report.account.tags.includes('disable_any_subscription')" class="el-icon-check"/>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ModerateUserDropdown',
|
||||
props: {
|
||||
report: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleDeactivation({ nickname }) {
|
||||
this.$store.dispatch('ToggleUserActivation', nickname)
|
||||
},
|
||||
handleDeletion(user) {
|
||||
this.$store.dispatch('DeleteUser', user)
|
||||
},
|
||||
showDeactivatedButton(id) {
|
||||
return this.$store.state.user.id !== id
|
||||
},
|
||||
toggleTag(user, tag) {
|
||||
user.tags.includes(tag)
|
||||
? this.$store.dispatch('RemoveTag', { users: [user], tag })
|
||||
: this.$store.dispatch('AddTag', { users: [user], tag })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -16,60 +16,7 @@
|
|||
<el-dropdown-item v-if="report.state !== 'closed'" @click.native="changeReportState('closed', report.id)">{{ $t('reports.close') }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-dropdown trigger="click">
|
||||
<el-button plain size="small" icon="el-icon-files">{{ $t('reports.moderateUser') }}<i class="el-icon-arrow-down el-icon--right"/></el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item
|
||||
v-if="showDeactivatedButton(report.account)"
|
||||
@click.native="handleDeactivation(report.account)">
|
||||
{{ report.account.deactivated ? $t('users.activateAccount') : $t('users.deactivateAccount') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="showDeactivatedButton(report.account.id)"
|
||||
@click.native="handleDeletion(report.account.id)">
|
||||
{{ $t('users.deleteAccount') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:divided="true"
|
||||
:class="{ 'active-tag': report.account.tags.includes('force_nsfw') }"
|
||||
@click.native="toggleTag(report.account, 'force_nsfw')">
|
||||
{{ $t('users.forceNsfw') }}
|
||||
<i v-if="report.account.tags.includes('force_nsfw')" class="el-icon-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:class="{ 'active-tag': report.account.tags.includes('strip_media') }"
|
||||
@click.native="toggleTag(report.account, 'strip_media')">
|
||||
{{ $t('users.stripMedia') }}
|
||||
<i v-if="report.account.tags.includes('strip_media')" class="el-icon-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:class="{ 'active-tag': report.account.tags.includes('force_unlisted') }"
|
||||
@click.native="toggleTag(report.account, 'force_unlisted')">
|
||||
{{ $t('users.forceUnlisted') }}
|
||||
<i v-if="report.account.tags.includes('force_unlisted')" class="el-icon-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:class="{ 'active-tag': report.account.tags.includes('sandbox') }"
|
||||
@click.native="toggleTag(report.account, 'sandbox')">
|
||||
{{ $t('users.sandbox') }}
|
||||
<i v-if="report.account.tags.includes('sandbox')" class="el-icon-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="report.account.local"
|
||||
:class="{ 'active-tag': report.account.tags.includes('disable_remote_subscription') }"
|
||||
@click.native="toggleTag(report.account, 'disable_remote_subscription')">
|
||||
{{ $t('users.disableRemoteSubscription') }}
|
||||
<i v-if="report.account.tags.includes('disable_remote_subscription')" class="el-icon-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="report.account.local"
|
||||
:class="{ 'active-tag': report.account.tags.includes('disable_any_subscription') }"
|
||||
@click.native="toggleTag(report.account, 'disable_any_subscription')">
|
||||
{{ $t('users.disableAnySubscription') }}
|
||||
<i v-if="report.account.tags.includes('disable_any_subscription')" class="el-icon-check"/>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<moderate-user-dropdown :report="report"/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -112,10 +59,11 @@
|
|||
<script>
|
||||
import moment from 'moment'
|
||||
import Statuses from './Statuses'
|
||||
import ModerateUserDropdown from './ModerateUserDropdown'
|
||||
|
||||
export default {
|
||||
name: 'TimelineItem',
|
||||
components: { Statuses },
|
||||
name: 'Report',
|
||||
components: { Statuses, ModerateUserDropdown },
|
||||
props: {
|
||||
report: {
|
||||
type: Object,
|
||||
|
@ -141,20 +89,6 @@ export default {
|
|||
},
|
||||
parseTimestamp(timestamp) {
|
||||
return moment(timestamp).format('L HH:mm')
|
||||
},
|
||||
showDeactivatedButton(id) {
|
||||
return this.$store.state.user.id !== id
|
||||
},
|
||||
handleDeactivation({ nickname }) {
|
||||
this.$store.dispatch('ToggleUserActivation', nickname)
|
||||
},
|
||||
handleDeletion(user) {
|
||||
this.$store.dispatch('DeleteUser', user)
|
||||
},
|
||||
toggleTag(user, tag) {
|
||||
user.tags.includes(tag)
|
||||
? this.$store.dispatch('RemoveTag', { users: [user], tag })
|
||||
: this.$store.dispatch('AddTag', { users: [user], tag })
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,30 +3,55 @@
|
|||
<h1>{{ $t('reports.reports') }}</h1>
|
||||
<div class="filter-container">
|
||||
<reports-filter/>
|
||||
<el-checkbox v-model="groupReports" class="group-reports-checkbox" @change="toggleReportsGrouping">
|
||||
Group reports by statuses
|
||||
</el-checkbox>
|
||||
</div>
|
||||
<div class="block">
|
||||
<el-timeline class="timeline">
|
||||
<timeline-item v-loading="loading" v-for="report in reports" :report="report" :key="report.id"/>
|
||||
<report v-loading="loading" v-for="report in reports" :report="report" :key="report.id"/>
|
||||
</el-timeline>
|
||||
<div v-if="reports.length === 0" class="no-reports-message">
|
||||
<p>There are no reports to display</p>
|
||||
</div>
|
||||
<div v-if="!loading" class="reports-pagination">
|
||||
<el-pagination
|
||||
:total="totalReportsCount"
|
||||
:current-page="currentPage"
|
||||
:page-size="pageSize"
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
@current-change="handlePageChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TimelineItem from './components/TimelineItem'
|
||||
import Report from './components/Report'
|
||||
import ReportsFilter from './components/ReportsFilter'
|
||||
|
||||
export default {
|
||||
components: { TimelineItem, ReportsFilter },
|
||||
components: { Report, ReportsFilter },
|
||||
computed: {
|
||||
groupReports() {
|
||||
return this.$store.state.reports.groupReports
|
||||
},
|
||||
loading() {
|
||||
return this.$store.state.users.loading
|
||||
return this.$store.state.reports.loading
|
||||
},
|
||||
pageSize() {
|
||||
return this.$store.state.reports.pageSize
|
||||
},
|
||||
reports() {
|
||||
return this.$store.state.reports.fetchedReports
|
||||
},
|
||||
totalReportsCount() {
|
||||
return this.$store.state.reports.totalReportsCount
|
||||
},
|
||||
currentPage() {
|
||||
return this.$store.state.reports.currentPage
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -35,16 +60,22 @@ export default {
|
|||
created() {
|
||||
window.addEventListener('scroll', this.handleScroll)
|
||||
},
|
||||
destroyed() {
|
||||
window.removeEventListener('scroll', this.handleScroll)
|
||||
},
|
||||
// destroyed() {
|
||||
// window.removeEventListener('scroll', this.handleScroll)
|
||||
// },
|
||||
methods: {
|
||||
handleScroll(reports) {
|
||||
const bottomOfWindow = document.documentElement.scrollHeight - document.documentElement.scrollTop === document.documentElement.clientHeight
|
||||
if (bottomOfWindow) {
|
||||
this.$store.dispatch('FetchReports')
|
||||
}
|
||||
handlePageChange(page) {
|
||||
this.$store.dispatch('FetchReports', { page })
|
||||
},
|
||||
toggleReportsGrouping() {
|
||||
|
||||
}
|
||||
// handleScroll(reports) {
|
||||
// const bottomOfWindow = document.documentElement.scrollHeight - document.documentElement.scrollTop === document.documentElement.clientHeight
|
||||
// if (bottomOfWindow) {
|
||||
// this.$store.dispatch('FetchReports')
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -56,9 +87,14 @@ export default {
|
|||
padding: 0px;
|
||||
}
|
||||
.filter-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 22px 15px 22px 15px;
|
||||
padding-bottom: 0
|
||||
}
|
||||
.group-reports-checkbox {
|
||||
margin-top: 10px;
|
||||
}
|
||||
h1 {
|
||||
margin: 22px 0 0 15px;
|
||||
}
|
||||
|
@ -78,9 +114,13 @@ only screen and (max-width: 760px),
|
|||
.filter-container {
|
||||
margin: 0 10px
|
||||
}
|
||||
.timeline {
|
||||
margin: 20px 20px 20px 18px
|
||||
}
|
||||
}
|
||||
#app > div > div.main-container > section > div > div.block > ul {
|
||||
margin: 45px 45px 5px 19px;
|
||||
}
|
||||
.reports-pagination {
|
||||
margin: 25px 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Vuex from 'vuex'
|
||||
import { mount, createLocalVue, config } from '@vue/test-utils'
|
||||
import Element from 'element-ui'
|
||||
import TimelineItem from '@/views/reports/components/TimelineItem'
|
||||
import Report from '@/views/reports/components/Report'
|
||||
import storeConfig from './store.conf'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import flushPromises from 'flush-promises'
|
||||
|
@ -25,7 +25,7 @@ describe('Report in a timeline', () => {
|
|||
|
||||
it('changes report state from open to resolved', async (done) => {
|
||||
const report = store.state.reports.fetchedReports[0]
|
||||
const wrapper = mount(TimelineItem, {
|
||||
const wrapper = mount(Report, {
|
||||
store,
|
||||
localVue,
|
||||
propsData: {
|
||||
|
@ -43,7 +43,7 @@ describe('Report in a timeline', () => {
|
|||
|
||||
it('changes report state from open to closed', async (done) => {
|
||||
const report = store.state.reports.fetchedReports[3]
|
||||
const wrapper = mount(TimelineItem, {
|
||||
const wrapper = mount(Report, {
|
||||
store,
|
||||
localVue,
|
||||
propsData: {
|
||||
|
@ -61,7 +61,7 @@ describe('Report in a timeline', () => {
|
|||
|
||||
it('shows statuses', () => {
|
||||
const report = store.state.reports.fetchedReports[4]
|
||||
const wrapper = mount(TimelineItem, {
|
||||
const wrapper = mount(Report, {
|
||||
store,
|
||||
localVue,
|
||||
propsData: {
|
||||
|
@ -75,7 +75,7 @@ describe('Report in a timeline', () => {
|
|||
|
||||
it('adds sensitive flag to a status', async (done) => {
|
||||
const report = store.state.reports.fetchedReports[4]
|
||||
const wrapper = mount(TimelineItem, {
|
||||
const wrapper = mount(Report, {
|
||||
store,
|
||||
localVue,
|
||||
propsData: {
|
||||
|
@ -93,7 +93,7 @@ describe('Report in a timeline', () => {
|
|||
|
||||
it('removes sensitive flag to a status', async (done) => {
|
||||
const report = store.state.reports.fetchedReports[4]
|
||||
const wrapper = mount(TimelineItem, {
|
||||
const wrapper = mount(Report, {
|
||||
store,
|
||||
localVue,
|
||||
propsData: {
|
||||
|
@ -111,7 +111,7 @@ describe('Report in a timeline', () => {
|
|||
|
||||
it('changes status visibility from public to unlisted', async (done) => {
|
||||
const report = store.state.reports.fetchedReports[4]
|
||||
const wrapper = mount(TimelineItem, {
|
||||
const wrapper = mount(Report, {
|
||||
store,
|
||||
localVue,
|
||||
propsData: {
|
||||
|
@ -129,7 +129,7 @@ describe('Report in a timeline', () => {
|
|||
|
||||
it('changes status visibility from unlisted to private', async (done) => {
|
||||
const report = store.state.reports.fetchedReports[4]
|
||||
const wrapper = mount(TimelineItem, {
|
||||
const wrapper = mount(Report, {
|
||||
store,
|
||||
localVue,
|
||||
propsData: {
|
||||
|
|
Loading…
Reference in a new issue