forked from AkkomaGang/admin-fe
Merge branch 'feature/add-links' into 'develop'
Add links to user's profile page and to user's account in Pleroma See merge request pleroma/admin-fe!136
This commit is contained in:
commit
d8299972b5
9 changed files with 185 additions and 68 deletions
|
@ -9,6 +9,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
### Added
|
||||
|
||||
- Create `/statuses/:id` route that shows single status
|
||||
- Add link to the user's account in Pleroma on the user's profile page
|
||||
- On Reports page add links to reported account and the author of the report
|
||||
- In Notes add link to the note author's profile page
|
||||
- In Moderation log add link to the actor's profile page
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -5,7 +5,11 @@
|
|||
<div class="status-account-container">
|
||||
<div class="status-account">
|
||||
<el-checkbox v-if="showCheckbox" class="status-checkbox" @change="handleStatusSelection(account)"/>
|
||||
<router-link v-if="propertyExists(account, 'id')" :to="{ name: 'UsersShow', params: { id: account.id }}" @click.native.stop>
|
||||
<router-link
|
||||
v-if="propertyExists(account, 'id')"
|
||||
:to="{ name: 'UsersShow', params: { id: account.id }}"
|
||||
class="router-link"
|
||||
@click.native.stop>
|
||||
<div class="status-card-header">
|
||||
<img v-if="propertyExists(account, 'avatar')" :src="account.avatar" class="status-avatar-img">
|
||||
<span v-if="propertyExists(account, 'nickname')" class="status-account-name">{{ account.nickname }}</span>
|
||||
|
@ -100,7 +104,7 @@
|
|||
<div class="status-footer">
|
||||
<span class="status-created-at">{{ parseTimestamp(status.created_at) }}</span>
|
||||
<a v-if="status.url" :href="status.url" target="_blank" class="account" @click.stop>
|
||||
Open status in instance
|
||||
{{ $t('statuses.openStatusInInstance') }}
|
||||
<i class="el-icon-top-right"/>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -264,6 +268,9 @@ export default {
|
|||
width: 100%;
|
||||
}
|
||||
}
|
||||
.router-link {
|
||||
text-decoration: none;
|
||||
}
|
||||
.show-more-button {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
|
|
@ -254,7 +254,8 @@ export default {
|
|||
direct: 'Direct',
|
||||
private: 'Private',
|
||||
public: 'Public',
|
||||
unlisted: 'Unlisted'
|
||||
unlisted: 'Unlisted',
|
||||
openStatusInInstance: 'Open status in instance'
|
||||
},
|
||||
userProfile: {
|
||||
tags: 'Tags',
|
||||
|
@ -270,6 +271,7 @@ export default {
|
|||
status: 'Status',
|
||||
deactivated: 'Deactivated',
|
||||
noStatuses: 'No statuses to show',
|
||||
openAccountInInstance: 'Open account in instance',
|
||||
securitySettings: {
|
||||
email: 'Email',
|
||||
password: 'Password',
|
||||
|
|
46
src/views/moderation_log/LogEntryMessage.vue
Normal file
46
src/views/moderation_log/LogEntryMessage.vue
Normal file
|
@ -0,0 +1,46 @@
|
|||
<template>
|
||||
<span>
|
||||
<router-link
|
||||
v-if="propertyExists(actor, 'id')"
|
||||
:to="{ name: 'UsersShow', params: { id: actor.id }}"
|
||||
class="router-link">
|
||||
<span v-if="propertyExists(actor, 'nickname')" style="font-weight: 600">
|
||||
@{{ actor.nickname }}
|
||||
</span>
|
||||
</router-link>
|
||||
<span>{{ logEntryMessage }}</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'LogEntryMessage',
|
||||
props: {
|
||||
actor: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
message: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
logEntryMessage() {
|
||||
return this.message.split(this.actor.nickname)[1]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
propertyExists(account, property) {
|
||||
return account[property]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style rel='stylesheet/scss' lang='scss'>
|
||||
.router-link {
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
|
@ -43,7 +43,8 @@
|
|||
v-for="(logEntry, index) in log"
|
||||
:key="index"
|
||||
:timestamp="normalizeTimestamp(logEntry.time)">
|
||||
{{ logEntry.message }}
|
||||
<log-entry-message v-if="propertyExists(logEntry.data.actor, 'nickname')" :actor="logEntry.data.actor" :message="logEntry.message"/>
|
||||
<span v-else>{{ logEntry.message }}</span>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
<div class="pagination">
|
||||
|
@ -64,9 +65,10 @@ import moment from 'moment'
|
|||
import _ from 'lodash'
|
||||
import debounce from 'lodash.debounce'
|
||||
import RebootButton from '@/components/RebootButton'
|
||||
import LogEntryMessage from './LogEntryMessage'
|
||||
|
||||
export default {
|
||||
components: { RebootButton },
|
||||
components: { RebootButton, LogEntryMessage },
|
||||
data() {
|
||||
return {
|
||||
dateRange: '',
|
||||
|
@ -114,9 +116,6 @@ export default {
|
|||
this.$store.dispatch('FetchAdmins')
|
||||
},
|
||||
methods: {
|
||||
normalizeTimestamp(timestamp) {
|
||||
return moment(timestamp * 1000).format('YYYY-MM-DD HH:mm')
|
||||
},
|
||||
fetchLogWithFilters() {
|
||||
const filters = _.omitBy({
|
||||
start_date: this.dateRange ? this.dateRange[0].toISOString() : null,
|
||||
|
@ -127,6 +126,12 @@ export default {
|
|||
}, val => val === '' || val === null)
|
||||
|
||||
this.$store.dispatch('FetchModerationLog', filters)
|
||||
},
|
||||
normalizeTimestamp(timestamp) {
|
||||
return moment(timestamp * 1000).format('YYYY-MM-DD HH:mm')
|
||||
},
|
||||
propertyExists(account, property) {
|
||||
return account[property]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,23 @@
|
|||
<el-card class="note-card">
|
||||
<div slot="header">
|
||||
<div class="note-header">
|
||||
<div class="note-actor">
|
||||
<img v-if="propertyExists(note.user, 'avatar')" :src="note.user.avatar" class="note-avatar-img">
|
||||
<span v-if="propertyExists(note.user, 'nickname')" class="note-actor-name">{{ note.user.nickname }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<el-button size="mini" @click.native="handleNoteDeletion(note.id, report.id)">
|
||||
{{ $t('reports.deleteNote') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<router-link
|
||||
v-if="propertyExists(note.user, 'id')"
|
||||
:to="{ name: 'UsersShow', params: { id: note.user.id }}"
|
||||
class="router-link">
|
||||
<div class="note-actor">
|
||||
<img
|
||||
v-if="propertyExists(note.user, 'avatar')"
|
||||
:src="note.user.avatar"
|
||||
alt="avatar"
|
||||
class="note-avatar-img">
|
||||
<span v-if="propertyExists(note.user, 'nickname')" class="note-actor-name">{{ note.user.nickname }}</span>
|
||||
<span v-else class="note-actor-name deactivated">({{ $t('users.invalidNickname') }})</span>
|
||||
</div>
|
||||
</router-link>
|
||||
<el-button size="mini" @click.native="handleNoteDeletion(note.id, report.id)">
|
||||
{{ $t('reports.deleteNote') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="note-body">
|
||||
|
@ -68,6 +76,9 @@ export default {
|
|||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.deactivated {
|
||||
color: gray;
|
||||
}
|
||||
.el-icon-arrow-right {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
@ -108,6 +119,9 @@ export default {
|
|||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.router-link {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@media only screen and (max-width:480px) {
|
||||
.el-card__header {
|
||||
|
|
|
@ -27,23 +27,28 @@
|
|||
<moderate-user-dropdown v-if="propertyExists(report.account, 'nickname')" :account="report.account"/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<el-divider class="divider"/>
|
||||
<el-divider class="divider"/>
|
||||
<div class="report-account-container">
|
||||
<span class="report-row-key">{{ $t('reports.account') }}:</span>
|
||||
<img
|
||||
v-if="propertyExists(report.account, 'avatar')"
|
||||
:src="report.account.avatar"
|
||||
alt="avatar"
|
||||
class="avatar-img">
|
||||
<a v-if="propertyExists(report.account, 'url', 'nickname')" :href="report.account.url" target="_blank" class="account">
|
||||
<span class="report-account-name">{{ report.account.nickname }}</span>
|
||||
</a>
|
||||
<span v-else>
|
||||
<span v-if="propertyExists(report.account, 'nickname')" class="report-account-name">
|
||||
{{ report.account.nickname }}
|
||||
</span>
|
||||
<div class="report-account">
|
||||
<router-link
|
||||
v-if="propertyExists(report.account, 'id')"
|
||||
:to="{ name: 'UsersShow', params: { id: report.account.id }}"
|
||||
class="router-link">
|
||||
<img
|
||||
v-if="propertyExists(report.account, 'avatar')"
|
||||
:src="report.account.avatar"
|
||||
alt="avatar"
|
||||
class="avatar-img">
|
||||
<span v-if="propertyExists(report.account, 'nickname')" class="report-account-name">{{ report.account.nickname }}</span>
|
||||
<span v-else class="report-account-name deactivated">({{ $t('users.invalidNickname') }})</span>
|
||||
</router-link>
|
||||
<span v-else class="report-account-name deactivated">({{ $t('users.invalidNickname') }})</span>
|
||||
</span>
|
||||
<a v-if="propertyExists(report.account, 'url')" :href="report.account.url" target="_blank" class="account">
|
||||
{{ $t('userProfile.openAccountInInstance') }}
|
||||
<i class="el-icon-top-right"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="report.content && report.content.length > 0">
|
||||
<el-divider class="divider"/>
|
||||
|
@ -51,25 +56,30 @@
|
|||
<span>{{ report.content }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div :style="showStatuses(report.statuses) ? '' : 'margin-bottom:15px'">
|
||||
<el-divider class="divider"/>
|
||||
<el-divider class="divider"/>
|
||||
<div :style="showStatuses(report.statuses) ? '' : 'margin-bottom:15px'" class="report-account-container">
|
||||
<span class="report-row-key">{{ $t('reports.actor') }}:</span>
|
||||
<img
|
||||
v-if="propertyExists(report.actor, 'avatar')"
|
||||
:src="report.actor.avatar"
|
||||
alt="avatar"
|
||||
class="avatar-img">
|
||||
<a v-if="propertyExists(report.actor, 'url', 'nickname')" :href="report.actor.url" target="_blank" class="account">
|
||||
<span class="report-account-name">{{ report.actor.nickname }}</span>
|
||||
</a>
|
||||
<span v-else>
|
||||
<span v-if="propertyExists(report.actor, 'nickname')" class="report-account-name">
|
||||
{{ report.actor.nickname }}
|
||||
</span>
|
||||
<div class="report-account">
|
||||
<router-link
|
||||
v-if="propertyExists(report.actor, 'id')"
|
||||
:to="{ name: 'UsersShow', params: { id: report.actor.id }}"
|
||||
class="router-link">
|
||||
<img
|
||||
v-if="propertyExists(report.actor, 'avatar')"
|
||||
:src="report.actor.avatar"
|
||||
alt="avatar"
|
||||
class="avatar-img">
|
||||
<span v-if="propertyExists(report.actor, 'nickname')" class="report-account-name">{{ report.actor.nickname }}</span>
|
||||
<span v-else class="report-account-name deactivated">({{ $t('users.invalidNickname') }})</span>
|
||||
</router-link>
|
||||
<span v-else class="report-account-name deactivated">({{ $t('users.invalidNickname') }})</span>
|
||||
</span>
|
||||
<a v-if="propertyExists(report.actor, 'url')" :href="report.actor.url" target="_blank" class="account">
|
||||
{{ $t('userProfile.openAccountInInstance') }}
|
||||
<i class="el-icon-top-right"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showStatuses(report.statuses)" class="statuses">
|
||||
<div v-if="showStatuses(report.statuses)" class="reported-statuses">
|
||||
<el-collapse>
|
||||
<el-collapse-item :title="getStatusesTitle(report.statuses)">
|
||||
<div v-for="status in report.statuses" :key="status.id">
|
||||
|
@ -192,14 +202,22 @@ export default {
|
|||
</script>
|
||||
|
||||
<style rel='stylesheet/scss' lang='scss'>
|
||||
h4 {
|
||||
margin: 0;
|
||||
height: 17px;
|
||||
}
|
||||
.account {
|
||||
line-height: 26px;
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
.account:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.avatar-img {
|
||||
vertical-align: bottom;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.divider {
|
||||
margin: 15px 0;
|
||||
|
@ -231,18 +249,6 @@ export default {
|
|||
padding: 10px 5px 10px 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
h4 {
|
||||
margin: 0;
|
||||
height: 17px;
|
||||
}
|
||||
.report {
|
||||
.report-header-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
.id {
|
||||
color: gray;
|
||||
margin-top: 6px;
|
||||
|
@ -269,6 +275,24 @@ export default {
|
|||
font-style: italic;
|
||||
color: gray;
|
||||
}
|
||||
.report {
|
||||
.report-header-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
.report-account {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
flex-grow: 2;
|
||||
}
|
||||
.report-account-container {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
.report-account-name {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
|
@ -276,9 +300,7 @@ export default {
|
|||
.report-row-key {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.report-row-key {
|
||||
font-size: 14px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
.report-title {
|
||||
margin: 0;
|
||||
|
@ -298,7 +320,10 @@ export default {
|
|||
margin: 30px 45px 45px 19px;
|
||||
padding: 0px;
|
||||
}
|
||||
.statuses {
|
||||
.router-link {
|
||||
text-decoration: none;
|
||||
}
|
||||
.reported-statuses {
|
||||
margin-top: 15px;
|
||||
}
|
||||
.submit-button {
|
||||
|
|
|
@ -2,15 +2,18 @@
|
|||
<div v-if="!loading" class="status-show-container">
|
||||
<header v-if="isDesktop || isTablet" class="user-page-header">
|
||||
<div class="avatar-name-container">
|
||||
<router-link v-if="propertyExists(user, 'id')" :to="{ name: 'UsersShow', params: { id: user.id }}">
|
||||
<router-link
|
||||
v-if="propertyExists(user, 'id')"
|
||||
:to="{ name: 'UsersShow', params: { id: user.id }}"
|
||||
class="router-link">
|
||||
<div class="avatar-name-header">
|
||||
<el-avatar v-if="propertyExists(user, 'avatar')" :src="user.avatar" size="large" />
|
||||
<h1 v-if="propertyExists(user, 'nickname')">{{ user.nickname }}</h1>
|
||||
<h1 v-else class="invalid">({{ $t('users.invalidNickname') }})</h1>
|
||||
</div>
|
||||
</router-link>
|
||||
<a v-if="propertyExists(user, 'url')" :href="user.url" target="_blank" class="account">
|
||||
<i class="el-icon-top-right" title="Open user in instance"/>
|
||||
<a v-if="propertyExists(user, 'url')" :href="user.url" target="_blank">
|
||||
<i :title="$t('userProfile.openAccountInInstance')" class="el-icon-top-right"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="left-header-container">
|
||||
|
@ -173,6 +176,9 @@ export default {
|
|||
.reset-password-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.router-link {
|
||||
text-decoration: none;
|
||||
}
|
||||
.status-container {
|
||||
margin: 0 15px 0 20px;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
<el-avatar v-if="propertyExists(user, 'avatar')" :src="user.avatar" size="large" />
|
||||
<h1 v-if="propertyExists(user, 'nickname')">{{ user.nickname }}</h1>
|
||||
<h1 v-else class="invalid">({{ $t('users.invalidNickname') }})</h1>
|
||||
<a v-if="propertyExists(user, 'url')" :href="user.url" target="_blank">
|
||||
<i :title="$t('userProfile.openAccountInInstance')" class="el-icon-top-right"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="left-header-container">
|
||||
<moderation-dropdown
|
||||
|
@ -207,6 +210,11 @@ table {
|
|||
.avatar-name-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.el-icon-top-right {
|
||||
font-size: 2em;
|
||||
line-height: 36px;
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
.invalid {
|
||||
color: gray;
|
||||
|
|
Loading…
Reference in a new issue