Rich reporter field and video embed in moderation abuse list
This commit is contained in:
parent
2bc9bd08cd
commit
d6af81469b
9 changed files with 163 additions and 28 deletions
|
@ -8,18 +8,35 @@
|
|||
|
||||
.moderation-expanded-label {
|
||||
font-weight: $font-semibold;
|
||||
min-width: 200px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.moderation-expanded-text {
|
||||
display: inline-block;
|
||||
word-wrap: break-word;
|
||||
|
||||
::ng-deep p:last-child {
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.moderation-expanded {
|
||||
word-wrap: break-word;
|
||||
overflow: visible !important;
|
||||
text-overflow: unset !important;
|
||||
white-space: unset !important;
|
||||
.screenratio {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
padding-bottom: 56%;
|
||||
|
||||
::ng-deep iframe {
|
||||
position: absolute;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.chip {
|
||||
@include chip;
|
||||
}
|
||||
|
|
|
@ -24,8 +24,19 @@
|
|||
</td>
|
||||
|
||||
<td>
|
||||
<a [href]="videoAbuse.reporterAccount.url" i18n-title title="Go to the account" target="_blank" rel="noopener noreferrer">
|
||||
{{ createByString(videoAbuse.reporterAccount) }}
|
||||
<a [href]="videoAbuse.reporterAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
|
||||
<div class="chip two-lines">
|
||||
<img
|
||||
class="avatar"
|
||||
[src]="videoAbuse.reporterAccount.avatar.path"
|
||||
(error)="switchToDefaultAvatar($event)"
|
||||
alt="Avatar"
|
||||
>
|
||||
<div>
|
||||
{{ videoAbuse.reporterAccount.displayName }}
|
||||
<span class="text-muted">{{ createByString(videoAbuse.reporterAccount) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
|
@ -50,14 +61,22 @@
|
|||
|
||||
<ng-template pTemplate="rowexpansion" let-videoAbuse>
|
||||
<tr>
|
||||
<td class="moderation-expanded" colspan="6">
|
||||
<div>
|
||||
<span i18n class="moderation-expanded-label">Reason:</span>
|
||||
<span class="moderation-expanded-text" [innerHTML]="videoAbuse.reasonHtml"></span>
|
||||
</div>
|
||||
<div *ngIf="videoAbuse.moderationComment">
|
||||
<span i18n class="moderation-expanded-label">Moderation comment:</span>
|
||||
<span class="moderation-expanded-text" [innerHTML]="videoAbuse.moderationCommentHtml"></span>
|
||||
<td class="expand-cell" colspan="6">
|
||||
<div class="d-flex">
|
||||
<div class="col-8">
|
||||
<div class="d-flex">
|
||||
<span class="col-3 moderation-expanded-label" i18n>Reason:</span>
|
||||
<span class="col-9 moderation-expanded-text" [innerHTML]="videoAbuse.reasonHtml"></span>
|
||||
</div>
|
||||
<div class="mt-3 d-flex" *ngIf="videoAbuse.moderationComment">
|
||||
<span class="col-3 moderation-expanded-label" i18n>Note:</span>
|
||||
<span class="col-9 moderation-expanded-text" [innerHTML]="videoAbuse.moderationCommentHtml"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
<div class="screenratio" [innerHTML]="videoAbuse.embedHtml"></div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -10,6 +10,10 @@ import { ConfirmService } from '../../../core/index'
|
|||
import { ModerationCommentModalComponent } from './moderation-comment-modal.component'
|
||||
import { Video } from '../../../shared/video/video.model'
|
||||
import { MarkdownService } from '@app/shared/renderer'
|
||||
import { Actor } from '@app/shared/actor/actor.model'
|
||||
import { buildVideoLink, buildVideoEmbed } from 'src/assets/player/utils'
|
||||
import { getAbsoluteAPIUrl } from '@app/shared/misc/utils'
|
||||
import { DomSanitizer } from '@angular/platform-browser'
|
||||
|
||||
@Component({
|
||||
selector: 'my-video-abuse-list',
|
||||
|
@ -32,7 +36,8 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
|
|||
private videoAbuseService: VideoAbuseService,
|
||||
private confirmService: ConfirmService,
|
||||
private i18n: I18n,
|
||||
private markdownRenderer: MarkdownService
|
||||
private markdownRenderer: MarkdownService,
|
||||
private sanitizer: DomSanitizer
|
||||
) {
|
||||
super()
|
||||
|
||||
|
@ -42,8 +47,14 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
|
|||
handler: videoAbuse => this.removeVideoAbuse(videoAbuse)
|
||||
},
|
||||
{
|
||||
label: this.i18n('Update moderation comment'),
|
||||
handler: videoAbuse => this.openModerationCommentModal(videoAbuse)
|
||||
label: this.i18n('Add note'),
|
||||
handler: videoAbuse => this.openModerationCommentModal(videoAbuse),
|
||||
isDisplayed: videoAbuse => !videoAbuse.moderationComment
|
||||
},
|
||||
{
|
||||
label: this.i18n('Update note'),
|
||||
handler: videoAbuse => this.openModerationCommentModal(videoAbuse),
|
||||
isDisplayed: videoAbuse => !!videoAbuse.moderationComment
|
||||
},
|
||||
{
|
||||
label: this.i18n('Mark as accepted'),
|
||||
|
@ -90,6 +101,19 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
|
|||
return Video.buildClientUrl(videoAbuse.video.uuid)
|
||||
}
|
||||
|
||||
getVideoEmbed (videoAbuse: VideoAbuse) {
|
||||
const absoluteAPIUrl = 'http://localhost:9000' || getAbsoluteAPIUrl()
|
||||
const embedUrl = buildVideoLink({
|
||||
baseUrl: absoluteAPIUrl + '/videos/embed/' + videoAbuse.video.uuid,
|
||||
warningTitle: false
|
||||
})
|
||||
return buildVideoEmbed(embedUrl)
|
||||
}
|
||||
|
||||
switchToDefaultAvatar ($event: Event) {
|
||||
($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL()
|
||||
}
|
||||
|
||||
async removeVideoAbuse (videoAbuse: VideoAbuse) {
|
||||
const res = await this.confirmService.confirm(this.i18n('Do you really want to delete this abuse report?'), this.i18n('Delete'))
|
||||
if (res === false) return
|
||||
|
@ -125,7 +149,8 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
|
|||
for (const abuse of this.videoAbuses) {
|
||||
Object.assign(abuse, {
|
||||
reasonHtml: await this.toHtml(abuse.reason),
|
||||
moderationCommentHtml: await this.toHtml(abuse.moderationComment)
|
||||
moderationCommentHtml: await this.toHtml(abuse.moderationComment),
|
||||
embedHtml: this.sanitizer.bypassSecurityTrustHtml(this.getVideoEmbed(abuse))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -42,9 +42,9 @@
|
|||
|
||||
<ng-template pTemplate="rowexpansion" let-videoBlacklist>
|
||||
<tr>
|
||||
<td class="moderation-expanded" colspan="6">
|
||||
<span i18n class="moderation-expanded-label">Blacklist reason:</span>
|
||||
<span class="moderation-expanded-text" [innerHTML]="videoBlacklist.reasonHtml"></span>
|
||||
<td class="expand-cell" colspan="6">
|
||||
<span class="col-2 moderation-expanded-label" i18n>Blacklist reason:</span>
|
||||
<span class="col-9 moderation-expanded-text" [innerHTML]="videoBlacklist.reasonHtml"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
|
|
|
@ -51,19 +51,30 @@
|
|||
<ng-template pTemplate="body" let-expanded="expanded" let-user>
|
||||
|
||||
<tr [pSelectableRow]="user" [ngClass]="{ banned: user.blocked }">
|
||||
<td class="expand-cell">
|
||||
<td>
|
||||
<p-tableCheckbox [value]="user"></p-tableCheckbox>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<td class="expand-cell">
|
||||
<span *ngIf="user.blockedReason" class="expander" [pRowToggler]="user">
|
||||
<i [ngClass]="expanded ? 'glyphicon glyphicon-menu-down' : 'glyphicon glyphicon-menu-right'"></i>
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<a i18n-title title="Go to the account page" target="_blank" rel="noopener noreferrer" [routerLink]="[ '/accounts/' + user.username ]">
|
||||
{{ user.username }}
|
||||
<a i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer" [routerLink]="[ '/accounts/' + user.username ]">
|
||||
<div class="chip two-lines">
|
||||
<img
|
||||
class="avatar"
|
||||
[src]="user?.account?.avatar?.path"
|
||||
(error)="switchToDefaultAvatar($event)"
|
||||
alt="Avatar"
|
||||
>
|
||||
<div>
|
||||
{{ user.account.displayName }}
|
||||
<span class="text-muted">{{ user.username }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<span i18n *ngIf="user.blocked" class="banned-info">(banned)</span>
|
||||
</a>
|
||||
</td>
|
||||
|
|
|
@ -29,3 +29,7 @@ p-tableCheckbox {
|
|||
position: relative;
|
||||
top: -2.5px;
|
||||
}
|
||||
|
||||
.chip {
|
||||
@include chip;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import { I18n } from '@ngx-translate/i18n-polyfill'
|
|||
import { ServerConfig, User } from '../../../../../../shared'
|
||||
import { UserBanModalComponent } from '@app/shared/moderation'
|
||||
import { DropdownAction } from '@app/shared/buttons/action-dropdown.component'
|
||||
import { Actor } from '@app/shared/actor/actor.model'
|
||||
|
||||
@Component({
|
||||
selector: 'my-user-list',
|
||||
|
@ -105,6 +106,10 @@ export class UserListComponent extends RestTable implements OnInit {
|
|||
this.loadData()
|
||||
}
|
||||
|
||||
switchToDefaultAvatar ($event: Event) {
|
||||
($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL()
|
||||
}
|
||||
|
||||
async unbanUsers (users: User[]) {
|
||||
const message = this.i18n('Do you really want to unban {{num}} users?', { num: users.length })
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ export class MyAccountVideoChannelsComponent implements OnInit {
|
|||
display: false,
|
||||
ticks: {
|
||||
min: Math.max(0, this.videoChannelsMinimumDailyViews - (3 * this.videoChannelsMaximumDailyViews / 100)),
|
||||
max: this.videoChannelsMaximumDailyViews
|
||||
max: Math.max(1, this.videoChannelsMaximumDailyViews)
|
||||
}
|
||||
}]
|
||||
},
|
||||
|
|
|
@ -796,3 +796,57 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin chip {
|
||||
$avatar-height: 1.2rem;
|
||||
|
||||
align-items: center;
|
||||
border-radius: 5rem;
|
||||
display: inline-flex;
|
||||
font-size: 90%;
|
||||
color: var(--mainForegroundColor);
|
||||
height: $avatar-height;
|
||||
line-height: .8rem;
|
||||
margin: .1rem;
|
||||
max-width: 320px;
|
||||
overflow: hidden;
|
||||
padding: .2rem .4rem;
|
||||
text-decoration: none;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
|
||||
.avatar {
|
||||
margin-left: -.4rem;
|
||||
margin-right: .2rem;
|
||||
height: $avatar-height;
|
||||
width: $avatar-height;
|
||||
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
line-height: 1.25;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&.two-lines {
|
||||
$avatar-height: 1.8rem;
|
||||
|
||||
height: $avatar-height;
|
||||
|
||||
.avatar {
|
||||
height: $avatar-height;
|
||||
width: $avatar-height;
|
||||
}
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 80%;
|
||||
height: $avatar-height;
|
||||
margin-left: .1rem;
|
||||
margin-right: .1rem;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue