From d6af81469ba9390ce8ce80161a7de3526ae0253d Mon Sep 17 00:00:00 2001 From: Rigel Kent <sendmemail@rigelk.eu> Date: Mon, 13 Apr 2020 19:57:57 +0200 Subject: [PATCH] Rich reporter field and video embed in moderation abuse list --- .../moderation/moderation.component.scss | 29 +++++++--- .../video-abuse-list.component.html | 39 ++++++++++---- .../video-abuse-list.component.ts | 33 ++++++++++-- .../video-blacklist-list.component.html | 6 +-- .../users/user-list/user-list.component.html | 19 +++++-- .../users/user-list/user-list.component.scss | 4 ++ .../users/user-list/user-list.component.ts | 5 ++ .../my-account-video-channels.component.ts | 2 +- client/src/sass/include/_mixins.scss | 54 +++++++++++++++++++ 9 files changed, 163 insertions(+), 28 deletions(-) diff --git a/client/src/app/+admin/moderation/moderation.component.scss b/client/src/app/+admin/moderation/moderation.component.scss index 13b019c5b..89e9b47d3 100644 --- a/client/src/app/+admin/moderation/moderation.component.scss +++ b/client/src/app/+admin/moderation/moderation.component.scss @@ -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; } diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html index cf7b61d2a..155d10dda 100644 --- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html +++ b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html @@ -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> diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts index 2d991aae9..b135792a7 100644 --- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts +++ b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts @@ -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)) }) } diff --git a/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html b/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html index a39e7639e..320172e37 100644 --- a/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html +++ b/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html @@ -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> diff --git a/client/src/app/+admin/users/user-list/user-list.component.html b/client/src/app/+admin/users/user-list/user-list.component.html index 15bdb6398..e9ff61283 100644 --- a/client/src/app/+admin/users/user-list/user-list.component.html +++ b/client/src/app/+admin/users/user-list/user-list.component.html @@ -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> diff --git a/client/src/app/+admin/users/user-list/user-list.component.scss b/client/src/app/+admin/users/user-list/user-list.component.scss index 40f08027f..99b22aaea 100644 --- a/client/src/app/+admin/users/user-list/user-list.component.scss +++ b/client/src/app/+admin/users/user-list/user-list.component.scss @@ -29,3 +29,7 @@ p-tableCheckbox { position: relative; top: -2.5px; } + +.chip { + @include chip; +} diff --git a/client/src/app/+admin/users/user-list/user-list.component.ts b/client/src/app/+admin/users/user-list/user-list.component.ts index 0de123e93..667a0e1fd 100644 --- a/client/src/app/+admin/users/user-list/user-list.component.ts +++ b/client/src/app/+admin/users/user-list/user-list.component.ts @@ -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 }) diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts index 153fc0127..75d6d8acd 100644 --- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts +++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts @@ -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) } }] }, diff --git a/client/src/sass/include/_mixins.scss b/client/src/sass/include/_mixins.scss index 975072637..3c420f547 100644 --- a/client/src/sass/include/_mixins.scss +++ b/client/src/sass/include/_mixins.scss @@ -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; + } + } +} -- 2.25.1