1
0
Fork 0

Increase rows per page, add reporter muting for abuse list

This commit is contained in:
Rigel Kent 2020-04-16 17:18:55 +02:00 committed by Rigel Kent
parent 68d19a0ace
commit 9b4241e33b
9 changed files with 78 additions and 14 deletions

View file

@ -8,7 +8,7 @@
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>
<th i18n>Account</th> <th i18n>Account</th>
<th style="width: 200px;" i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th> <th style="width: 190px;" i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th>
<th style="width: 100px;"></th> <!-- column for action buttons --> <th style="width: 100px;"></th> <!-- column for action buttons -->
</tr> </tr>
</ng-template> </ng-template>

View file

@ -16,7 +16,7 @@
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>
<th i18n>Instance</th> <th i18n>Instance</th>
<th style="width: 200px;" i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th> <th style="width: 190px;" i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th>
<th style="width: 100px;"></th> <!-- column for action buttons --> <th style="width: 100px;"></th> <!-- column for action buttons -->
</tr> </tr>
</ng-template> </ng-template>

View file

@ -29,6 +29,10 @@
} }
} }
.glyphicon-trash {
font-size: 80%;
}
.screenratio { .screenratio {
position: relative; position: relative;
width: 100%; width: 100%;

View file

@ -1,15 +1,15 @@
<p-table <p-table
[value]="videoAbuses" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [value]="videoAbuses" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id" [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id" [resizableColumns]="true"
[showCurrentPageReport]="true" i18n-currentPageReportTemplate [showCurrentPageReport]="true" i18n-currentPageReportTemplate
currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} reports" currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} reports"
> >
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <!-- header --> <tr> <!-- header -->
<th style="width: 40px;"></th> <th style="width: 40px;"></th>
<th i18n>Reporter</th> <th style="width: 20%;" pResizableColumn i18n>Reporter</th>
<th style="width: 200px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
<th i18n>Video</th> <th i18n>Video</th>
<th style="width:190px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
<th i18n pSortableColumn="state" style="width: 80px;">State <p-sortIcon field="state"></p-sortIcon></th> <th i18n pSortableColumn="state" style="width: 80px;">State <p-sortIcon field="state"></p-sortIcon></th>
<th style="width: 120px;"></th> <th style="width: 120px;"></th>
</tr> </tr>
@ -40,14 +40,15 @@
</a> </a>
</td> </td>
<td>{{ videoAbuse.createdAt }}</td>
<td> <td>
<span *ngIf="videoAbuse.video.deleted" i18n-title title="Video was deleted" class="glyphicon glyphicon-trash"></span>
<a [href]="getVideoUrl(videoAbuse)" i18n-title title="Open video in a new tab" target="_blank" rel="noopener noreferrer"> <a [href]="getVideoUrl(videoAbuse)" i18n-title title="Open video in a new tab" target="_blank" rel="noopener noreferrer">
{{ videoAbuse.video.name }} {{ videoAbuse.video.name }}
</a> </a>
</td> </td>
<td>{{ videoAbuse.createdAt }}</td>
<td class="c-hand video-abuse-states" [pRowToggler]="videoAbuse"> <td class="c-hand video-abuse-states" [pRowToggler]="videoAbuse">
<span *ngIf="isVideoAbuseAccepted(videoAbuse)" [title]="videoAbuse.state.label" class="glyphicon glyphicon-ok"></span> <span *ngIf="isVideoAbuseAccepted(videoAbuse)" [title]="videoAbuse.state.label" class="glyphicon glyphicon-ok"></span>
<span *ngIf="isVideoAbuseRejected(videoAbuse)" [title]="videoAbuse.state.label" class="glyphicon glyphicon-remove"></span> <span *ngIf="isVideoAbuseRejected(videoAbuse)" [title]="videoAbuse.state.label" class="glyphicon glyphicon-remove"></span>
@ -55,7 +56,7 @@
</td> </td>
<td class="action-cell"> <td class="action-cell">
<my-action-dropdown placement="bottom-right auto" i18n-label label="Actions" [actions]="videoAbuseActions" [entry]="videoAbuse"></my-action-dropdown> <my-action-dropdown placement="bottom-right auto" container="body" i18n-label label="Actions" [actions]="videoAbuseActions" [entry]="videoAbuse"></my-action-dropdown>
</td> </td>
</tr> </tr>
</ng-template> </ng-template>

View file

@ -15,6 +15,7 @@ import { buildVideoLink, buildVideoEmbed } from 'src/assets/player/utils'
import { getAbsoluteAPIUrl } from '@app/shared/misc/utils' import { getAbsoluteAPIUrl } from '@app/shared/misc/utils'
import { DomSanitizer } from '@angular/platform-browser' import { DomSanitizer } from '@angular/platform-browser'
import { BlocklistService } from '@app/shared/blocklist' import { BlocklistService } from '@app/shared/blocklist'
import { VideoService } from '@app/shared/video/video.service'
@Component({ @Component({
selector: 'my-video-abuse-list', selector: 'my-video-abuse-list',
@ -26,7 +27,8 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
videoAbuses: (VideoAbuse & { moderationCommentHtml?: string, reasonHtml?: string })[] = [] videoAbuses: (VideoAbuse & { moderationCommentHtml?: string, reasonHtml?: string })[] = []
totalRecords = 0 totalRecords = 0
rowsPerPage = 10 rowsPerPageOptions = [ 20, 50, 100 ]
rowsPerPage = this.rowsPerPageOptions[0]
sort: SortMeta = { field: 'createdAt', order: 1 } sort: SortMeta = { field: 'createdAt', order: 1 }
pagination: RestPagination = { count: this.rowsPerPage, start: 0 } pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
@ -36,6 +38,7 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
private notifier: Notifier, private notifier: Notifier,
private videoAbuseService: VideoAbuseService, private videoAbuseService: VideoAbuseService,
private blocklistService: BlocklistService, private blocklistService: BlocklistService,
private videoService: VideoService,
private videoBlacklistService: VideoBlacklistService, private videoBlacklistService: VideoBlacklistService,
private confirmService: ConfirmService, private confirmService: ConfirmService,
private i18n: I18n, private i18n: I18n,
@ -78,10 +81,12 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
[ [
{ {
label: this.i18n('Actions for the video'), label: this.i18n('Actions for the video'),
isHeader: true isHeader: true,
isDisplayed: videoAbuse => !videoAbuse.video.deleted
}, },
{ {
label: this.i18n('Blacklist video'), label: this.i18n('Blacklist video'),
isDisplayed: videoAbuse => !videoAbuse.video.deleted,
handler: videoAbuse => { handler: videoAbuse => {
this.videoBlacklistService.blacklistVideo(videoAbuse.video.id, undefined, true) this.videoBlacklistService.blacklistVideo(videoAbuse.video.id, undefined, true)
.subscribe( .subscribe(
@ -91,6 +96,48 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
this.updateVideoAbuseState(videoAbuse, VideoAbuseState.ACCEPTED) this.updateVideoAbuseState(videoAbuse, VideoAbuseState.ACCEPTED)
}, },
err => this.notifier.error(err.message)
)
}
},
{
label: this.i18n('Delete video'),
isDisplayed: videoAbuse => !videoAbuse.video.deleted,
handler: async videoAbuse => {
const res = await this.confirmService.confirm(this.i18n('Do you really want to delete this video?'), this.i18n('Delete'))
if (res === false) return
this.videoService.removeVideo(videoAbuse.video.id)
.subscribe(
() => {
this.notifier.success(this.i18n('Video deleted.'))
this.updateVideoAbuseState(videoAbuse, VideoAbuseState.ACCEPTED)
},
err => this.notifier.error(err.message)
)
}
}
],
[
{
label: this.i18n('Actions for the reporter'),
isHeader: true
},
{
label: this.i18n('Mute reporter'),
handler: async videoAbuse => {
const account = videoAbuse.reporterAccount as Account
this.blocklistService.blockAccountByInstance(account)
.subscribe(
() => {
this.notifier.success(this.i18n('Account {{nameWithHost}} muted by the instance.', { nameWithHost: account.nameWithHost }))
account.mutedByInstance = true
},
err => this.notifier.error(err.message) err => this.notifier.error(err.message)
) )
} }
@ -180,7 +227,8 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
Object.assign(abuse, { Object.assign(abuse, {
reasonHtml: await this.toHtml(abuse.reason), 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)) embedHtml: this.sanitizer.bypassSecurityTrustHtml(this.getVideoEmbed(abuse)),
reporterAccount: new Account(abuse.reporterAccount)
}) })
} }

View file

@ -10,7 +10,7 @@
<th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th> <th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th>
<th style="width: 120px;" i18n>Sensitive</th> <th style="width: 120px;" i18n>Sensitive</th>
<th style="width: 120px;" i18n>Unfederated</th> <th style="width: 120px;" i18n>Unfederated</th>
<th style="width: 200px;" i18n pSortableColumn="createdAt">Date <p-sortIcon field="createdAt"></p-sortIcon></th> <th style="width: 190px;" i18n pSortableColumn="createdAt">Date <p-sortIcon field="createdAt"></p-sortIcon></th>
<th style="width: 120px;"></th> <th style="width: 120px;"></th>
</tr> </tr>
</ng-template> </ng-template>

View file

@ -1,4 +1,4 @@
<div class="dropdown-root" ngbDropdown [placement]="placement" container="body" *ngIf="areActionsDisplayed(actions, entry)"> <div class="dropdown-root" ngbDropdown [placement]="placement" [container]="container" *ngIf="areActionsDisplayed(actions, entry)">
<div <div
class="action-button" [ngClass]="{ small: buttonSize === 'small', grey: theme === 'grey', orange: theme === 'orange', 'button-styled': buttonStyled }" class="action-button" [ngClass]="{ small: buttonSize === 'small', grey: theme === 'grey', orange: theme === 'orange', 'button-styled': buttonStyled }"
ngbDropdownToggle role="button" ngbDropdownToggle role="button"

View file

@ -27,6 +27,7 @@ export class ActionDropdownComponent<T> {
@Input() entry: T @Input() entry: T
@Input() placement = 'bottom-left auto' @Input() placement = 'bottom-left auto'
@Input() container: null | 'body'
@Input() buttonSize: DropdownButtonSize = 'normal' @Input() buttonSize: DropdownButtonSize = 'normal'
@Input() buttonDirection: DropdownDirection = 'horizontal' @Input() buttonDirection: DropdownDirection = 'horizontal'

View file

@ -191,12 +191,22 @@ p-table {
.ui-dropdown { .ui-dropdown {
position: absolute; position: absolute;
top: 3px;
left: 0; left: 0;
&.ui-state-focus {
box-shadow: #{$focus-box-shadow-form} var(--mainColorLightest);
}
.ui-dropdown-label {
color: var(--inputPlaceholderColor);
}
} }
.ui-paginator-current { .ui-paginator-current {
position: absolute; position: absolute;
right: 0; right: 0;
color: var(--inputPlaceholderColor);
} }
.ui-paginator-first, .ui-paginator-first,