aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src
diff options
context:
space:
mode:
authorRigel Kent <sendmemail@rigelk.eu>2020-04-13 19:57:57 +0200
committerRigel Kent <sendmemail@rigelk.eu>2020-04-13 19:57:57 +0200
commitd6af81469ba9390ce8ce80161a7de3526ae0253d (patch)
tree739e91d6bc779b5cce5af3db68813a48dd780784 /client/src
parent2bc9bd08cd121bdffbf56a0241c4decfb77bfdd5 (diff)
downloadPeerTube-d6af81469ba9390ce8ce80161a7de3526ae0253d.tar.gz
PeerTube-d6af81469ba9390ce8ce80161a7de3526ae0253d.tar.zst
PeerTube-d6af81469ba9390ce8ce80161a7de3526ae0253d.zip
Rich reporter field and video embed in moderation abuse list
Diffstat (limited to 'client/src')
-rw-r--r--client/src/app/+admin/moderation/moderation.component.scss29
-rw-r--r--client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html39
-rw-r--r--client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.ts33
-rw-r--r--client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.html6
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.html19
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.scss4
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.ts5
-rw-r--r--client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts2
-rw-r--r--client/src/sass/include/_mixins.scss54
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 @@
8 8
9.moderation-expanded-label { 9.moderation-expanded-label {
10 font-weight: $font-semibold; 10 font-weight: $font-semibold;
11 min-width: 200px;
12 display: inline-block; 11 display: inline-block;
13 vertical-align: top; 12 vertical-align: top;
13 text-align: right;
14} 14}
15 15
16.moderation-expanded-text { 16.moderation-expanded-text {
17 display: inline-block; 17 display: inline-block;
18 word-wrap: break-word;
19
20 ::ng-deep p:last-child {
21 margin-bottom: 0px !important;
22 }
18} 23}
19 24
20.moderation-expanded { 25.screenratio {
21 word-wrap: break-word; 26 position: relative;
22 overflow: visible !important; 27 width: 100%;
23 text-overflow: unset !important; 28 height: 0;
24 white-space: unset !important; 29 padding-bottom: 56%;
30
31 ::ng-deep iframe {
32 position: absolute;
33 width: 100% !important;
34 height: 100% !important;
35 left: 0;
36 top: 0;
37 }
38}
39
40.chip {
41 @include chip;
25} 42}
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 @@
24 </td> 24 </td>
25 25
26 <td> 26 <td>
27 <a [href]="videoAbuse.reporterAccount.url" i18n-title title="Go to the account" target="_blank" rel="noopener noreferrer"> 27 <a [href]="videoAbuse.reporterAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
28 {{ createByString(videoAbuse.reporterAccount) }} 28 <div class="chip two-lines">
29 <img
30 class="avatar"
31 [src]="videoAbuse.reporterAccount.avatar.path"
32 (error)="switchToDefaultAvatar($event)"
33 alt="Avatar"
34 >
35 <div>
36 {{ videoAbuse.reporterAccount.displayName }}
37 <span class="text-muted">{{ createByString(videoAbuse.reporterAccount) }}</span>
38 </div>
39 </div>
29 </a> 40 </a>
30 </td> 41 </td>
31 42
@@ -50,14 +61,22 @@
50 61
51 <ng-template pTemplate="rowexpansion" let-videoAbuse> 62 <ng-template pTemplate="rowexpansion" let-videoAbuse>
52 <tr> 63 <tr>
53 <td class="moderation-expanded" colspan="6"> 64 <td class="expand-cell" colspan="6">
54 <div> 65 <div class="d-flex">
55 <span i18n class="moderation-expanded-label">Reason:</span> 66 <div class="col-8">
56 <span class="moderation-expanded-text" [innerHTML]="videoAbuse.reasonHtml"></span> 67 <div class="d-flex">
57 </div> 68 <span class="col-3 moderation-expanded-label" i18n>Reason:</span>
58 <div *ngIf="videoAbuse.moderationComment"> 69 <span class="col-9 moderation-expanded-text" [innerHTML]="videoAbuse.reasonHtml"></span>
59 <span i18n class="moderation-expanded-label">Moderation comment:</span> 70 </div>
60 <span class="moderation-expanded-text" [innerHTML]="videoAbuse.moderationCommentHtml"></span> 71 <div class="mt-3 d-flex" *ngIf="videoAbuse.moderationComment">
72 <span class="col-3 moderation-expanded-label" i18n>Note:</span>
73 <span class="col-9 moderation-expanded-text" [innerHTML]="videoAbuse.moderationCommentHtml"></span>
74 </div>
75 </div>
76
77 <div class="col-4">
78 <div class="screenratio" [innerHTML]="videoAbuse.embedHtml"></div>
79 </div>
61 </div> 80 </div>
62 </td> 81 </td>
63 </tr> 82 </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'
10import { ModerationCommentModalComponent } from './moderation-comment-modal.component' 10import { ModerationCommentModalComponent } from './moderation-comment-modal.component'
11import { Video } from '../../../shared/video/video.model' 11import { Video } from '../../../shared/video/video.model'
12import { MarkdownService } from '@app/shared/renderer' 12import { MarkdownService } from '@app/shared/renderer'
13import { Actor } from '@app/shared/actor/actor.model'
14import { buildVideoLink, buildVideoEmbed } from 'src/assets/player/utils'
15import { getAbsoluteAPIUrl } from '@app/shared/misc/utils'
16import { DomSanitizer } from '@angular/platform-browser'
13 17
14@Component({ 18@Component({
15 selector: 'my-video-abuse-list', 19 selector: 'my-video-abuse-list',
@@ -32,7 +36,8 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
32 private videoAbuseService: VideoAbuseService, 36 private videoAbuseService: VideoAbuseService,
33 private confirmService: ConfirmService, 37 private confirmService: ConfirmService,
34 private i18n: I18n, 38 private i18n: I18n,
35 private markdownRenderer: MarkdownService 39 private markdownRenderer: MarkdownService,
40 private sanitizer: DomSanitizer
36 ) { 41 ) {
37 super() 42 super()
38 43
@@ -42,8 +47,14 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
42 handler: videoAbuse => this.removeVideoAbuse(videoAbuse) 47 handler: videoAbuse => this.removeVideoAbuse(videoAbuse)
43 }, 48 },
44 { 49 {
45 label: this.i18n('Update moderation comment'), 50 label: this.i18n('Add note'),
46 handler: videoAbuse => this.openModerationCommentModal(videoAbuse) 51 handler: videoAbuse => this.openModerationCommentModal(videoAbuse),
52 isDisplayed: videoAbuse => !videoAbuse.moderationComment
53 },
54 {
55 label: this.i18n('Update note'),
56 handler: videoAbuse => this.openModerationCommentModal(videoAbuse),
57 isDisplayed: videoAbuse => !!videoAbuse.moderationComment
47 }, 58 },
48 { 59 {
49 label: this.i18n('Mark as accepted'), 60 label: this.i18n('Mark as accepted'),
@@ -90,6 +101,19 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
90 return Video.buildClientUrl(videoAbuse.video.uuid) 101 return Video.buildClientUrl(videoAbuse.video.uuid)
91 } 102 }
92 103
104 getVideoEmbed (videoAbuse: VideoAbuse) {
105 const absoluteAPIUrl = 'http://localhost:9000' || getAbsoluteAPIUrl()
106 const embedUrl = buildVideoLink({
107 baseUrl: absoluteAPIUrl + '/videos/embed/' + videoAbuse.video.uuid,
108 warningTitle: false
109 })
110 return buildVideoEmbed(embedUrl)
111 }
112
113 switchToDefaultAvatar ($event: Event) {
114 ($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL()
115 }
116
93 async removeVideoAbuse (videoAbuse: VideoAbuse) { 117 async removeVideoAbuse (videoAbuse: VideoAbuse) {
94 const res = await this.confirmService.confirm(this.i18n('Do you really want to delete this abuse report?'), this.i18n('Delete')) 118 const res = await this.confirmService.confirm(this.i18n('Do you really want to delete this abuse report?'), this.i18n('Delete'))
95 if (res === false) return 119 if (res === false) return
@@ -125,7 +149,8 @@ export class VideoAbuseListComponent extends RestTable implements OnInit {
125 for (const abuse of this.videoAbuses) { 149 for (const abuse of this.videoAbuses) {
126 Object.assign(abuse, { 150 Object.assign(abuse, {
127 reasonHtml: await this.toHtml(abuse.reason), 151 reasonHtml: await this.toHtml(abuse.reason),
128 moderationCommentHtml: await this.toHtml(abuse.moderationComment) 152 moderationCommentHtml: await this.toHtml(abuse.moderationComment),
153 embedHtml: this.sanitizer.bypassSecurityTrustHtml(this.getVideoEmbed(abuse))
129 }) 154 })
130 } 155 }
131 156
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 @@
42 42
43 <ng-template pTemplate="rowexpansion" let-videoBlacklist> 43 <ng-template pTemplate="rowexpansion" let-videoBlacklist>
44 <tr> 44 <tr>
45 <td class="moderation-expanded" colspan="6"> 45 <td class="expand-cell" colspan="6">
46 <span i18n class="moderation-expanded-label">Blacklist reason:</span> 46 <span class="col-2 moderation-expanded-label" i18n>Blacklist reason:</span>
47 <span class="moderation-expanded-text" [innerHTML]="videoBlacklist.reasonHtml"></span> 47 <span class="col-9 moderation-expanded-text" [innerHTML]="videoBlacklist.reasonHtml"></span>
48 </td> 48 </td>
49 </tr> 49 </tr>
50 </ng-template> 50 </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 @@
51 <ng-template pTemplate="body" let-expanded="expanded" let-user> 51 <ng-template pTemplate="body" let-expanded="expanded" let-user>
52 52
53 <tr [pSelectableRow]="user" [ngClass]="{ banned: user.blocked }"> 53 <tr [pSelectableRow]="user" [ngClass]="{ banned: user.blocked }">
54 <td class="expand-cell"> 54 <td>
55 <p-tableCheckbox [value]="user"></p-tableCheckbox> 55 <p-tableCheckbox [value]="user"></p-tableCheckbox>
56 </td> 56 </td>
57 57
58 <td> 58 <td class="expand-cell">
59 <span *ngIf="user.blockedReason" class="expander" [pRowToggler]="user"> 59 <span *ngIf="user.blockedReason" class="expander" [pRowToggler]="user">
60 <i [ngClass]="expanded ? 'glyphicon glyphicon-menu-down' : 'glyphicon glyphicon-menu-right'"></i> 60 <i [ngClass]="expanded ? 'glyphicon glyphicon-menu-down' : 'glyphicon glyphicon-menu-right'"></i>
61 </span> 61 </span>
62 </td> 62 </td>
63 63
64 <td> 64 <td>
65 <a i18n-title title="Go to the account page" target="_blank" rel="noopener noreferrer" [routerLink]="[ '/accounts/' + user.username ]"> 65 <a i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer" [routerLink]="[ '/accounts/' + user.username ]">
66 {{ user.username }} 66 <div class="chip two-lines">
67 <img
68 class="avatar"
69 [src]="user?.account?.avatar?.path"
70 (error)="switchToDefaultAvatar($event)"
71 alt="Avatar"
72 >
73 <div>
74 {{ user.account.displayName }}
75 <span class="text-muted">{{ user.username }}</span>
76 </div>
77 </div>
67 <span i18n *ngIf="user.blocked" class="banned-info">(banned)</span> 78 <span i18n *ngIf="user.blocked" class="banned-info">(banned)</span>
68 </a> 79 </a>
69 </td> 80 </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 {
29 position: relative; 29 position: relative;
30 top: -2.5px; 30 top: -2.5px;
31} 31}
32
33.chip {
34 @include chip;
35}
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'
7import { ServerConfig, User } from '../../../../../../shared' 7import { ServerConfig, User } from '../../../../../../shared'
8import { UserBanModalComponent } from '@app/shared/moderation' 8import { UserBanModalComponent } from '@app/shared/moderation'
9import { DropdownAction } from '@app/shared/buttons/action-dropdown.component' 9import { DropdownAction } from '@app/shared/buttons/action-dropdown.component'
10import { Actor } from '@app/shared/actor/actor.model'
10 11
11@Component({ 12@Component({
12 selector: 'my-user-list', 13 selector: 'my-user-list',
@@ -105,6 +106,10 @@ export class UserListComponent extends RestTable implements OnInit {
105 this.loadData() 106 this.loadData()
106 } 107 }
107 108
109 switchToDefaultAvatar ($event: Event) {
110 ($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL()
111 }
112
108 async unbanUsers (users: User[]) { 113 async unbanUsers (users: User[]) {
109 const message = this.i18n('Do you really want to unban {{num}} users?', { num: users.length }) 114 const message = this.i18n('Do you really want to unban {{num}} users?', { num: users.length })
110 115
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 {
56 display: false, 56 display: false,
57 ticks: { 57 ticks: {
58 min: Math.max(0, this.videoChannelsMinimumDailyViews - (3 * this.videoChannelsMaximumDailyViews / 100)), 58 min: Math.max(0, this.videoChannelsMinimumDailyViews - (3 * this.videoChannelsMaximumDailyViews / 100)),
59 max: this.videoChannelsMaximumDailyViews 59 max: Math.max(1, this.videoChannelsMaximumDailyViews)
60 } 60 }
61 }] 61 }]
62 }, 62 },
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 @@
796 } 796 }
797 } 797 }
798} 798}
799
800@mixin chip {
801 $avatar-height: 1.2rem;
802
803 align-items: center;
804 border-radius: 5rem;
805 display: inline-flex;
806 font-size: 90%;
807 color: var(--mainForegroundColor);
808 height: $avatar-height;
809 line-height: .8rem;
810 margin: .1rem;
811 max-width: 320px;
812 overflow: hidden;
813 padding: .2rem .4rem;
814 text-decoration: none;
815 text-overflow: ellipsis;
816 vertical-align: middle;
817 white-space: nowrap;
818
819 .avatar {
820 margin-left: -.4rem;
821 margin-right: .2rem;
822 height: $avatar-height;
823 width: $avatar-height;
824
825 border-radius: 50%;
826 display: inline-block;
827 line-height: 1.25;
828 position: relative;
829 vertical-align: middle;
830 }
831
832 &.two-lines {
833 $avatar-height: 1.8rem;
834
835 height: $avatar-height;
836
837 .avatar {
838 height: $avatar-height;
839 width: $avatar-height;
840 }
841
842 div {
843 display: flex;
844 flex-direction: column;
845 font-size: 80%;
846 height: $avatar-height;
847 margin-left: .1rem;
848 margin-right: .1rem;
849 justify-content: center;
850 }
851 }
852}