Add ability to switch between all reports and grouped reports (with stubbed data)
This commit is contained in:
parent
f7777f6d15
commit
b87945c42f
4 changed files with 394 additions and 14 deletions
|
@ -3,8 +3,8 @@ import { changeState, changeStatusScope, deleteStatus, fetchReports, filterRepor
|
|||
const reports = {
|
||||
state: {
|
||||
fetchedReports: [],
|
||||
groupReports: true,
|
||||
idOfLastReport: '',
|
||||
page_limit: 5,
|
||||
stateFilter: '',
|
||||
loading: true
|
||||
},
|
||||
|
@ -20,6 +20,9 @@ const reports = {
|
|||
},
|
||||
SET_REPORTS_FILTER: (state, filter) => {
|
||||
state.stateFilter = filter
|
||||
},
|
||||
SET_REPORTS_GROUPING: (state) => {
|
||||
state.groupReports = !state.groupReports
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
|
@ -42,20 +45,18 @@ const reports = {
|
|||
},
|
||||
async FetchReports({ commit, getters, state }) {
|
||||
commit('SET_LOADING', true)
|
||||
|
||||
const response = state.stateFilter.length === 0
|
||||
const { data } = state.stateFilter.length === 0
|
||||
? await fetchReports(state.page_limit, state.idOfLastReport, getters.authHost, getters.token)
|
||||
: await filterReports(state.stateFilter, state.page_limit, state.idOfLastReport, getters.authHost, getters.token)
|
||||
|
||||
const reports = state.fetchedReports.concat(response.data.reports)
|
||||
const id = reports.length > 0 ? reports[reports.length - 1].id : state.idOfLastReport
|
||||
|
||||
commit('SET_REPORTS', reports)
|
||||
commit('SET_LAST_REPORT_ID', id)
|
||||
commit('SET_REPORTS', data.reports)
|
||||
commit('SET_LOADING', false)
|
||||
},
|
||||
SetFilter({ commit }, filter) {
|
||||
commit('SET_REPORTS_FILTER', filter)
|
||||
},
|
||||
ToggleReportsGrouping({ commit }) {
|
||||
commit('SET_REPORTS_GROUPING')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
120
src/views/reports/components/GroupedReport.vue
Normal file
120
src/views/reports/components/GroupedReport.vue
Normal file
|
@ -0,0 +1,120 @@
|
|||
<template>
|
||||
<el-card>
|
||||
<div class="header-container">
|
||||
<div>
|
||||
<h3 class="report-title">{{ $t('reports.reportsOn') }} {{ group.account.display_name }}</h3>
|
||||
</div>
|
||||
<div>
|
||||
<moderate-user-dropdown :account="group.account"/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="line"/>
|
||||
<span class="report-row-key">{{ $t('reports.account') }}:</span>
|
||||
<img
|
||||
:src="group.account.avatar"
|
||||
alt="avatar"
|
||||
class="avatar-img">
|
||||
<a :href="group.account.url" target="_blank">
|
||||
<span>{{ group.account.acct }}</span>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<div class="line"/>
|
||||
<span class="report-row-key">{{ $t('reports.actors') }}:</span>
|
||||
<span v-for="actor in group.actors" :key="actor.id">
|
||||
<a :href="actor.url" target="_blank">
|
||||
<span>{{ actor.acct }}, </span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="group.status">
|
||||
<div class="line"/>
|
||||
<span class="report-row-key">{{ $t('reports.reportedStatus') }}:</span>
|
||||
<statuses :statuses="group.status" class="reported-status"/>
|
||||
</div>
|
||||
<div v-if="group.reports">
|
||||
<div class="line"/>
|
||||
<el-collapse>
|
||||
<el-collapse-item :title="$t('reports.reports')">
|
||||
<report-card :reports="group.reports"/>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ModerateUserDropdown from './ModerateUserDropdown'
|
||||
import ReportCard from './ReportCard'
|
||||
import Statuses from './Statuses'
|
||||
|
||||
export default {
|
||||
name: 'Report',
|
||||
components: { ModerateUserDropdown, ReportCard, Statuses },
|
||||
props: {
|
||||
group: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeMultipleReportsState(reportState, groupOfReports) {
|
||||
// this.$store.dispatch('ChangeReportState', { reportState, reportId })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style rel='stylesheet/scss' lang='scss'>
|
||||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.avatar-img {
|
||||
vertical-align: bottom;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.el-card__body {
|
||||
padding: 17px;
|
||||
}
|
||||
.el-card__header {
|
||||
background-color: #FAFAFA;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
.el-icon-arrow-right {
|
||||
margin-right: 6px;
|
||||
}
|
||||
.header-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
height: 40px;
|
||||
}
|
||||
.line {
|
||||
width: 100%;
|
||||
height: 0;
|
||||
border: 0.5px solid #EBEEF5;
|
||||
margin: 15px 0 15px;
|
||||
}
|
||||
.report-title {
|
||||
margin: 0;
|
||||
}
|
||||
.report-row-key {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.reported-status {
|
||||
margin-top: 15px;
|
||||
}
|
||||
@media
|
||||
only screen and (max-width: 760px),
|
||||
(min-device-width: 768px) and (max-device-width: 1024px) {
|
||||
.header-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 80px;
|
||||
}
|
||||
}
|
||||
</style>
|
89
src/views/reports/components/ReportCard.vue
Normal file
89
src/views/reports/components/ReportCard.vue
Normal file
|
@ -0,0 +1,89 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-card v-for="report in reports" :key="report.id" class="report-card">
|
||||
<div slot="header">
|
||||
<div class="report-header">
|
||||
<div class="report-actor-container">
|
||||
<div class="report-actor">
|
||||
<img :src="report.actor.avatar" class="report-avatar-img">
|
||||
<h3 class="report-actor-name">{{ report.actor.display_name }}</h3>
|
||||
</div>
|
||||
<a :href="report.actor.url" target="_blank">
|
||||
@{{ report.actor.acct }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="report-body">
|
||||
<span class="report-content" v-html="report.content"/>
|
||||
{{ parseTimestamp(report.created_at) }}
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment'
|
||||
|
||||
export default {
|
||||
name: 'Statuses',
|
||||
props: {
|
||||
reports: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
parseTimestamp(timestamp) {
|
||||
return moment(timestamp).format('YYYY-MM-DD HH:mm')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style rel='stylesheet/scss' lang='scss'>
|
||||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.report-actor {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.report-actor-name {
|
||||
margin: 0;
|
||||
height: 22px;
|
||||
}
|
||||
.report-avatar-img {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.report-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.report-card {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.report-content {
|
||||
font-size: 15px;
|
||||
}
|
||||
.report-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
@media
|
||||
only screen and (max-width: 760px),
|
||||
(min-device-width: 768px) and (max-device-width: 1024px) {
|
||||
.el-card__header {
|
||||
padding: 10px 17px;
|
||||
}
|
||||
.report-actor-container {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.report-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -3,12 +3,15 @@
|
|||
<h1>{{ $t('reports.reports') }}</h1>
|
||||
<div class="filter-container">
|
||||
<reports-filter/>
|
||||
<el-checkbox v-model="groupReports" class="group-reports-checkbox" @change="toggleReportsGrouping">
|
||||
<el-checkbox v-model="groupReports" class="group-reports-checkbox">
|
||||
Group reports by statuses
|
||||
</el-checkbox>
|
||||
</div>
|
||||
<div class="block">
|
||||
<el-timeline class="timeline">
|
||||
<el-timeline v-if="groupReports" class="timeline">
|
||||
<grouped-report v-loading="loading" v-for="group in groups" :group="group" :key="group.id"/>
|
||||
</el-timeline>
|
||||
<el-timeline v-else class="timeline">
|
||||
<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">
|
||||
|
@ -29,14 +32,181 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import GroupedReport from './components/GroupedReport'
|
||||
import Report from './components/Report'
|
||||
import ReportsFilter from './components/ReportsFilter'
|
||||
|
||||
export default {
|
||||
components: { Report, ReportsFilter },
|
||||
components: { GroupedReport, Report, ReportsFilter },
|
||||
computed: {
|
||||
groupReports() {
|
||||
return this.$store.state.reports.groupReports
|
||||
groups() {
|
||||
return [{
|
||||
date: '19-07-2019',
|
||||
account: {
|
||||
'acct': 'user',
|
||||
'avatar': 'https://pleroma.example.org/images/avi.png',
|
||||
'avatar_static': 'https://pleroma.example.org/images/avi.png',
|
||||
'bot': false,
|
||||
'created_at': '2019-04-23T17:32:04.000Z',
|
||||
'display_name': 'User',
|
||||
'emojis': [],
|
||||
'fields': [],
|
||||
'followers_count': 1,
|
||||
'following_count': 1,
|
||||
'header': 'https://pleroma.example.org/images/banner.png',
|
||||
'header_static': 'https://pleroma.example.org/images/banner.png',
|
||||
'id': '9i6dAJqSGSKMzLG2Lo',
|
||||
'locked': false,
|
||||
'note': '',
|
||||
'pleroma': {
|
||||
'confirmation_pending': false,
|
||||
'hide_favorites': true,
|
||||
'hide_followers': false,
|
||||
'hide_follows': false,
|
||||
'is_admin': false,
|
||||
'is_moderator': false,
|
||||
'relationship': {},
|
||||
'tags': []
|
||||
},
|
||||
'source': {
|
||||
'note': '',
|
||||
'pleroma': {},
|
||||
'sensitive': false
|
||||
},
|
||||
'tags': ['force_unlisted'],
|
||||
'statuses_count': 3,
|
||||
'url': 'https://pleroma.example.org/users/user',
|
||||
'username': 'user'
|
||||
},
|
||||
actors: [
|
||||
{ 'acct': 'lain', 'url': 'https://pleroma.example.org/users/lain' },
|
||||
{ 'acct': 'linafilippova1', 'url': 'https://pleroma.example.org/users/linafilippova1' }
|
||||
],
|
||||
reports: [
|
||||
{
|
||||
'actor': {
|
||||
'acct': 'lain',
|
||||
'avatar': 'https://pleroma.example.org/images/avi.png',
|
||||
'display_name': 'Roger Braun',
|
||||
'url': 'https://pleroma.example.org/users/lain'
|
||||
},
|
||||
'content': 'Please delete it',
|
||||
'created_at': '2019-04-29T19:48:15.000Z',
|
||||
'id': '9iJGOv1j8hxuw19bcm',
|
||||
'state': 'open'
|
||||
},
|
||||
{ 'actor': {
|
||||
'acct': 'linafilippova1',
|
||||
'avatar': 'https://pleroma.example.org/images/avi.png',
|
||||
'display_name': 'Lina Filippova',
|
||||
'url': 'https://pleroma.example.org/users/linafilippova1'
|
||||
},
|
||||
'content': 'This is an assault',
|
||||
'created_at': '2019-03-01T19:48:15.000Z',
|
||||
'id': '9iJGOv1alksjdf3r',
|
||||
'state': 'resolve'
|
||||
}
|
||||
],
|
||||
status: [{
|
||||
'account': {
|
||||
'acct': 'user',
|
||||
'avatar': 'https://pleroma.example.org/images/avi.png',
|
||||
'avatar_static': 'https://pleroma.example.org/images/avi.png',
|
||||
'bot': false,
|
||||
'created_at': '2019-04-23T17:32:04.000Z',
|
||||
'display_name': 'User',
|
||||
'emojis': [],
|
||||
'fields': [],
|
||||
'followers_count': 1,
|
||||
'following_count': 1,
|
||||
'header': 'https://pleroma.example.org/images/banner.png',
|
||||
'header_static': 'https://pleroma.example.org/images/banner.png',
|
||||
'id': '9i6dAJqSGSKMzLG2Lo',
|
||||
'locked': false,
|
||||
'note': '',
|
||||
'pleroma': {
|
||||
'confirmation_pending': false,
|
||||
'hide_favorites': true,
|
||||
'hide_followers': false,
|
||||
'hide_follows': false,
|
||||
'is_admin': false,
|
||||
'is_moderator': false,
|
||||
'relationship': {},
|
||||
'tags': []
|
||||
},
|
||||
'source': {
|
||||
'note': '',
|
||||
'pleroma': {},
|
||||
'sensitive': false
|
||||
},
|
||||
'tags': ['force_unlisted'],
|
||||
'statuses_count': 3,
|
||||
'url': 'https://pleroma.example.org/users/user',
|
||||
'username': 'user'
|
||||
},
|
||||
'application': {
|
||||
'name': 'Web',
|
||||
'website': null
|
||||
},
|
||||
'bookmarked': false,
|
||||
'card': null,
|
||||
'content': '<span class=\"h-card\"><a data-user=\"9hEkA5JsvAdlSrocam\" class=\"u-url mention\" href=\"https://pleroma.example.org/users/lain\">@<span>lain</span></a></span> click on my link <a href=\"https://www.google.com/\">https://www.google.com/</a>',
|
||||
'created_at': '2019-04-23T19:15:47.000Z',
|
||||
'emojis': [],
|
||||
'favourited': false,
|
||||
'favourites_count': 0,
|
||||
'id': '9i6mQ9uVrrOmOime8m',
|
||||
'in_reply_to_account_id': null,
|
||||
'in_reply_to_id': null,
|
||||
'language': null,
|
||||
'media_attachments': [],
|
||||
'mentions': [
|
||||
{
|
||||
'acct': 'lain',
|
||||
'id': '9hEkA5JsvAdlSrocam',
|
||||
'url': 'https://pleroma.example.org/users/lain',
|
||||
'username': 'lain'
|
||||
},
|
||||
{
|
||||
'acct': 'user',
|
||||
'id': '9i6dAJqSGSKMzLG2Lo',
|
||||
'url': 'https://pleroma.example.org/users/user',
|
||||
'username': 'user'
|
||||
}
|
||||
],
|
||||
'muted': false,
|
||||
'pinned': false,
|
||||
'pleroma': {
|
||||
'content': {
|
||||
'text/plain': '@lain click on my link https://www.google.com/'
|
||||
},
|
||||
'conversation_id': 28,
|
||||
'in_reply_to_account_acct': null,
|
||||
'local': true,
|
||||
'spoiler_text': {
|
||||
'text/plain': ''
|
||||
}
|
||||
},
|
||||
'reblog': null,
|
||||
'reblogged': false,
|
||||
'reblogs_count': 0,
|
||||
'replies_count': 0,
|
||||
'sensitive': false,
|
||||
'spoiler_text': '',
|
||||
'tags': [],
|
||||
'uri': 'https://pleroma.example.org/objects/8717b90f-8e09-4b58-97b0-e3305472b396',
|
||||
'url': 'https://pleroma.example.org/notice/9i6mQ9uVrrOmOime8m',
|
||||
'visibility': 'direct'
|
||||
}]
|
||||
}]
|
||||
},
|
||||
groupReports: {
|
||||
get() {
|
||||
return this.$store.state.reports.groupReports
|
||||
},
|
||||
set() {
|
||||
this.toggleReportsGrouping()
|
||||
}
|
||||
},
|
||||
loading() {
|
||||
return this.$store.state.reports.loading
|
||||
|
@ -68,7 +238,7 @@ export default {
|
|||
this.$store.dispatch('FetchReports', { page })
|
||||
},
|
||||
toggleReportsGrouping() {
|
||||
|
||||
this.$store.dispatch('ToggleReportsGrouping')
|
||||
}
|
||||
// handleScroll(reports) {
|
||||
// const bottomOfWindow = document.documentElement.scrollHeight - document.documentElement.scrollTop === document.documentElement.clientHeight
|
||||
|
|
Loading…
Reference in a new issue