aboutsummaryrefslogtreecommitdiffhomepage
path: root/client
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2020-07-28 09:57:16 +0200
committerChocobozzz <chocobozzz@cpy.re>2020-07-31 11:35:19 +0200
commitd573926e9b94fb19c8f51c53f71fc853182e1761 (patch)
tree907cc81c7275efe30aa90047c0763a7254bd1063 /client
parent594d3e48d8a887bbf48ce4cc594c1c36c9640fb1 (diff)
downloadPeerTube-d573926e9b94fb19c8f51c53f71fc853182e1761.tar.gz
PeerTube-d573926e9b94fb19c8f51c53f71fc853182e1761.tar.zst
PeerTube-d573926e9b94fb19c8f51c53f71fc853182e1761.zip
Add migrations for abuse messages
Diffstat (limited to 'client')
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts4
-rw-r--r--client/src/app/core/renderer/html-renderer.service.ts21
-rw-r--r--client/src/app/shared/shared-abuse-list/abuse-list-table.component.html7
-rw-r--r--client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts2
-rw-r--r--client/src/app/shared/shared-abuse-list/abuse-message-modal.component.html4
-rw-r--r--client/src/app/shared/shared-abuse-list/abuse-message-modal.component.scss1
-rw-r--r--client/src/app/shared/shared-abuse-list/abuse-message-modal.component.ts24
-rw-r--r--client/src/app/shared/shared-main/users/user-notification.model.ts28
-rw-r--r--client/src/app/shared/shared-main/users/user-notification.service.ts5
-rw-r--r--client/src/app/shared/shared-main/users/user-notifications.component.html26
-rw-r--r--client/src/app/shared/shared-main/users/user-notifications.component.ts6
11 files changed, 101 insertions, 27 deletions
diff --git a/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts
index 8562e564b..89a04c078 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts
+++ b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts
@@ -42,7 +42,9 @@ export class MyAccountNotificationPreferencesComponent implements OnInit {
42 newFollow: this.i18n('You or your channel(s) has a new follower'), 42 newFollow: this.i18n('You or your channel(s) has a new follower'),
43 commentMention: this.i18n('Someone mentioned you in video comments'), 43 commentMention: this.i18n('Someone mentioned you in video comments'),
44 newInstanceFollower: this.i18n('Your instance has a new follower'), 44 newInstanceFollower: this.i18n('Your instance has a new follower'),
45 autoInstanceFollowing: this.i18n('Your instance auto followed another instance') 45 autoInstanceFollowing: this.i18n('Your instance auto followed another instance'),
46 abuseNewMessage: this.i18n('An abuse received a new message'),
47 abuseStateChange: this.i18n('One of your abuse has been accepted or rejected by moderators')
46 } 48 }
47 this.notificationSettingKeys = Object.keys(this.labelNotifications) as (keyof UserNotificationSetting)[] 49 this.notificationSettingKeys = Object.keys(this.labelNotifications) as (keyof UserNotificationSetting)[]
48 50
diff --git a/client/src/app/core/renderer/html-renderer.service.ts b/client/src/app/core/renderer/html-renderer.service.ts
index f0527c759..302d92ed9 100644
--- a/client/src/app/core/renderer/html-renderer.service.ts
+++ b/client/src/app/core/renderer/html-renderer.service.ts
@@ -3,19 +3,29 @@ import { LinkifierService } from './linkifier.service'
3 3
4@Injectable() 4@Injectable()
5export class HtmlRendererService { 5export class HtmlRendererService {
6 private sanitizeHtml: typeof import ('sanitize-html')
6 7
7 constructor (private linkifier: LinkifierService) { 8 constructor (private linkifier: LinkifierService) {
8 9
9 } 10 }
10 11
12 async convertToBr (text: string) {
13 await this.loadSanitizeHtml()
14
15 const html = text.replace(/\r?\n/g, '<br />')
16
17 return this.sanitizeHtml(html, {
18 allowedTags: [ 'br' ]
19 })
20 }
21
11 async toSafeHtml (text: string) { 22 async toSafeHtml (text: string) {
12 // FIXME: import('..') returns a struct module, containing a "default" field corresponding to our sanitizeHtml function 23 await this.loadSanitizeHtml()
13 const sanitizeHtml: typeof import ('sanitize-html') = (await import('sanitize-html') as any).default
14 24
15 // Convert possible markdown to html 25 // Convert possible markdown to html
16 const html = this.linkifier.linkify(text) 26 const html = this.linkifier.linkify(text)
17 27
18 return sanitizeHtml(html, { 28 return this.sanitizeHtml(html, {
19 allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ], 29 allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ],
20 allowedSchemes: [ 'http', 'https' ], 30 allowedSchemes: [ 'http', 'https' ],
21 allowedAttributes: { 31 allowedAttributes: {
@@ -37,4 +47,9 @@ export class HtmlRendererService {
37 } 47 }
38 }) 48 })
39 } 49 }
50
51 private async loadSanitizeHtml () {
52 // FIXME: import('..') returns a struct module, containing a "default" field corresponding to our sanitizeHtml function
53 this.sanitizeHtml = (await import('sanitize-html') as any).default
54 }
40} 55}
diff --git a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.html b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.html
index 17b3742d6..d90b93fff 100644
--- a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.html
+++ b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.html
@@ -42,6 +42,7 @@
42 <th style="width: 150px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th> 42 <th style="width: 150px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
43 <th i18n pSortableColumn="state" style="width: 80px;">State <p-sortIcon field="state"></p-sortIcon></th> 43 <th i18n pSortableColumn="state" style="width: 80px;">State <p-sortIcon field="state"></p-sortIcon></th>
44 <th i18n style="width: 80px;">Messages</th> 44 <th i18n style="width: 80px;">Messages</th>
45 <th i18n *ngIf="isAdminView()" style="width: 100px;">Internal note</th>
45 <th style="width: 150px;"></th> 46 <th style="width: 150px;"></th>
46 </tr> 47 </tr>
47 </ng-template> 48 </ng-template>
@@ -144,13 +145,11 @@
144 145
145 </ng-container> 146 </ng-container>
146 147
147
148 <td class="c-hand" [pRowToggler]="abuse">{{ abuse.createdAt | date: 'short' }}</td> 148 <td class="c-hand" [pRowToggler]="abuse">{{ abuse.createdAt | date: 'short' }}</td>
149 149
150 <td class="c-hand abuse-states" [pRowToggler]="abuse"> 150 <td class="c-hand abuse-states" [pRowToggler]="abuse">
151 <span *ngIf="isAbuseAccepted(abuse)" [title]="abuse.state.label" class="glyphicon glyphicon-ok"></span> 151 <span *ngIf="isAbuseAccepted(abuse)" [title]="abuse.state.label" class="glyphicon glyphicon-ok"></span>
152 <span *ngIf="isAbuseRejected(abuse)" [title]="abuse.state.label" class="glyphicon glyphicon-remove"></span> 152 <span *ngIf="isAbuseRejected(abuse)" [title]="abuse.state.label" class="glyphicon glyphicon-remove"></span>
153 <span *ngIf="abuse.moderationComment" container="body" placement="left auto" [ngbTooltip]="abuse.moderationComment" class="glyphicon glyphicon-comment"></span>
154 </td> 153 </td>
155 154
156 <td class="c-hand abuse-messages" (click)="openAbuseMessagesModal(abuse)"> 155 <td class="c-hand abuse-messages" (click)="openAbuseMessagesModal(abuse)">
@@ -161,6 +160,10 @@
161 </ng-container> 160 </ng-container>
162 </td> 161 </td>
163 162
163 <td *ngIf="isAdminView()" class="internal-note" container="body" placement="left auto" [ngbTooltip]="abuse.moderationComment">
164 {{ abuse.moderationComment }}
165 </td>
166
164 <td class="action-cell"> 167 <td class="action-cell">
165 <my-action-dropdown 168 <my-action-dropdown
166 [ngClass]="{ 'show': expanded }" placement="bottom-right top-right left auto" container="body" 169 [ngClass]="{ 'show': expanded }" placement="bottom-right top-right left auto" container="body"
diff --git a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts
index 1d17c9ec9..21d2ea47d 100644
--- a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts
+++ b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts
@@ -278,7 +278,7 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
278 isDisplayed: abuse => this.isLocalAbuse(abuse) 278 isDisplayed: abuse => this.isLocalAbuse(abuse)
279 }, 279 },
280 { 280 {
281 label: this.i18n('Update note'), 281 label: this.i18n('Update internal note'),
282 handler: abuse => this.openModerationCommentModal(abuse), 282 handler: abuse => this.openModerationCommentModal(abuse),
283 isDisplayed: abuse => this.isAdminView() && !!abuse.moderationComment 283 isDisplayed: abuse => this.isAdminView() && !!abuse.moderationComment
284 }, 284 },
diff --git a/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.html b/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.html
index cb965b71d..17e9ce4cf 100644
--- a/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.html
+++ b/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.html
@@ -9,7 +9,7 @@
9 </div> 9 </div>
10 10
11 <div class="modal-body"> 11 <div class="modal-body">
12 <div class="messages" #messagesBlock> 12 <div class="messages">
13 <div 13 <div
14 *ngFor="let message of abuseMessages" 14 *ngFor="let message of abuseMessages"
15 class="message-block" [ngClass]="{ 'by-moderator': message.byModerator, 'by-me': isMessageByMe(message) }" 15 class="message-block" [ngClass]="{ 'by-moderator': message.byModerator, 'by-me': isMessageByMe(message) }"
@@ -18,7 +18,7 @@
18 <div class="author">{{ message.account.name }}</div> 18 <div class="author">{{ message.account.name }}</div>
19 19
20 <div class="bubble"> 20 <div class="bubble">
21 <div class="content">{{ message.message }}</div> 21 <div class="content" [innerHTML]="message.messageHtml"></div>
22 <div class="date">{{ message.createdAt | date }}</div> 22 <div class="date">{{ message.createdAt | date }}</div>
23 </div> 23 </div>
24 </div> 24 </div>
diff --git a/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.scss b/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.scss
index 4dd025fc4..4163722dd 100644
--- a/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.scss
+++ b/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.scss
@@ -20,6 +20,7 @@ textarea {
20 display: flex; 20 display: flex;
21 flex-direction: column; 21 flex-direction: column;
22 overflow-y: scroll; 22 overflow-y: scroll;
23 max-height: 50vh;
23} 24}
24 25
25.no-messages { 26.no-messages {
diff --git a/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.ts b/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.ts
index 03f5ad735..6686d91f4 100644
--- a/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.ts
+++ b/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.ts
@@ -1,5 +1,5 @@
1import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' 1import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
2import { AuthService, Notifier } from '@app/core' 2import { AuthService, Notifier, HtmlRendererService } from '@app/core'
3import { AbuseValidatorsService, FormReactive, FormValidatorService } from '@app/shared/shared-forms' 3import { AbuseValidatorsService, FormReactive, FormValidatorService } from '@app/shared/shared-forms'
4import { NgbModal } from '@ng-bootstrap/ng-bootstrap' 4import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
5import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' 5import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
@@ -14,13 +14,12 @@ import { AbuseService } from '../shared-moderation'
14}) 14})
15export class AbuseMessageModalComponent extends FormReactive implements OnInit { 15export class AbuseMessageModalComponent extends FormReactive implements OnInit {
16 @ViewChild('modal', { static: true }) modal: NgbModal 16 @ViewChild('modal', { static: true }) modal: NgbModal
17 @ViewChild('messagesBlock', { static: false }) messagesBlock: ElementRef
18 17
19 @Input() isAdminView: boolean 18 @Input() isAdminView: boolean
20 19
21 @Output() countMessagesUpdated = new EventEmitter<{ abuseId: number, countMessages: number }>() 20 @Output() countMessagesUpdated = new EventEmitter<{ abuseId: number, countMessages: number }>()
22 21
23 abuseMessages: AbuseMessage[] = [] 22 abuseMessages: (AbuseMessage & { messageHtml: string })[] = []
24 textareaMessage: string 23 textareaMessage: string
25 sendingMessage = false 24 sendingMessage = false
26 noResults = false 25 noResults = false
@@ -33,6 +32,7 @@ export class AbuseMessageModalComponent extends FormReactive implements OnInit {
33 private abuseValidatorsService: AbuseValidatorsService, 32 private abuseValidatorsService: AbuseValidatorsService,
34 private modalService: NgbModal, 33 private modalService: NgbModal,
35 private i18n: I18n, 34 private i18n: I18n,
35 private htmlRenderer: HtmlRendererService,
36 private auth: AuthService, 36 private auth: AuthService,
37 private notifier: Notifier, 37 private notifier: Notifier,
38 private abuseService: AbuseService 38 private abuseService: AbuseService
@@ -108,15 +108,21 @@ export class AbuseMessageModalComponent extends FormReactive implements OnInit {
108 private loadMessages () { 108 private loadMessages () {
109 this.abuseService.listAbuseMessages(this.abuse) 109 this.abuseService.listAbuseMessages(this.abuse)
110 .subscribe( 110 .subscribe(
111 res => { 111 async res => {
112 this.abuseMessages = res.data 112 this.abuseMessages = []
113
114 for (const m of res.data) {
115 this.abuseMessages.push(Object.assign(m, {
116 messageHtml: await this.htmlRenderer.convertToBr(m.message)
117 }))
118 }
119
113 this.noResults = this.abuseMessages.length === 0 120 this.noResults = this.abuseMessages.length === 0
114 121
115 setTimeout(() => { 122 setTimeout(() => {
116 if (!this.messagesBlock) return 123 // Don't use ViewChild: it is not supported inside a ng-template
117 124 const messagesBlock = document.querySelector('.messages')
118 const element = this.messagesBlock.nativeElement as HTMLElement 125 messagesBlock.scroll(0, messagesBlock.scrollHeight)
119 element.scrollIntoView({ block: 'end', inline: 'nearest' })
120 }) 126 })
121 }, 127 },
122 128
diff --git a/client/src/app/shared/shared-main/users/user-notification.model.ts b/client/src/app/shared/shared-main/users/user-notification.model.ts
index 61b48a806..a068daaac 100644
--- a/client/src/app/shared/shared-main/users/user-notification.model.ts
+++ b/client/src/app/shared/shared-main/users/user-notification.model.ts
@@ -1,5 +1,14 @@
1import {
2 AbuseState,
3 ActorInfo,
4 FollowState,
5 UserNotification as UserNotificationServer,
6 UserNotificationType,
7 VideoInfo,
8 UserRight
9} from '@shared/models'
1import { Actor } from '../account/actor.model' 10import { Actor } from '../account/actor.model'
2import { ActorInfo, Avatar, FollowState, UserNotification as UserNotificationServer, UserNotificationType, VideoInfo } from '@shared/models' 11import { AuthUser } from '@app/core'
3 12
4export class UserNotification implements UserNotificationServer { 13export class UserNotification implements UserNotificationServer {
5 id: number 14 id: number
@@ -27,6 +36,7 @@ export class UserNotification implements UserNotificationServer {
27 36
28 abuse?: { 37 abuse?: {
29 id: number 38 id: number
39 state: AbuseState
30 40
31 video?: VideoInfo 41 video?: VideoInfo
32 42
@@ -69,13 +79,14 @@ export class UserNotification implements UserNotificationServer {
69 videoUrl?: string 79 videoUrl?: string
70 commentUrl?: any[] 80 commentUrl?: any[]
71 abuseUrl?: string 81 abuseUrl?: string
82 abuseQueryParams?: { [id: string]: string } = {}
72 videoAutoBlacklistUrl?: string 83 videoAutoBlacklistUrl?: string
73 accountUrl?: string 84 accountUrl?: string
74 videoImportIdentifier?: string 85 videoImportIdentifier?: string
75 videoImportUrl?: string 86 videoImportUrl?: string
76 instanceFollowUrl?: string 87 instanceFollowUrl?: string
77 88
78 constructor (hash: UserNotificationServer) { 89 constructor (hash: UserNotificationServer, user: AuthUser) {
79 this.id = hash.id 90 this.id = hash.id
80 this.type = hash.type 91 this.type = hash.type
81 this.read = hash.read 92 this.read = hash.read
@@ -122,12 +133,25 @@ export class UserNotification implements UserNotificationServer {
122 133
123 case UserNotificationType.NEW_ABUSE_FOR_MODERATORS: 134 case UserNotificationType.NEW_ABUSE_FOR_MODERATORS:
124 this.abuseUrl = '/admin/moderation/abuses/list' 135 this.abuseUrl = '/admin/moderation/abuses/list'
136 this.abuseQueryParams.search = '#' + this.abuse.id
125 137
126 if (this.abuse.video) this.videoUrl = this.buildVideoUrl(this.abuse.video) 138 if (this.abuse.video) this.videoUrl = this.buildVideoUrl(this.abuse.video)
127 else if (this.abuse.comment) this.commentUrl = this.buildCommentUrl(this.abuse.comment) 139 else if (this.abuse.comment) this.commentUrl = this.buildCommentUrl(this.abuse.comment)
128 else if (this.abuse.account) this.accountUrl = this.buildAccountUrl(this.abuse.account) 140 else if (this.abuse.account) this.accountUrl = this.buildAccountUrl(this.abuse.account)
129 break 141 break
130 142
143 case UserNotificationType.ABUSE_STATE_CHANGE:
144 this.abuseUrl = '/my-account/abuses'
145 this.abuseQueryParams.search = '#' + this.abuse.id
146 break
147
148 case UserNotificationType.ABUSE_NEW_MESSAGE:
149 this.abuseUrl = user.hasRight(UserRight.MANAGE_ABUSES)
150 ? '/admin/moderation/abuses/list'
151 : '/my-account/abuses'
152 this.abuseQueryParams.search = '#' + this.abuse.id
153 break
154
131 case UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS: 155 case UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS:
132 this.videoAutoBlacklistUrl = '/admin/moderation/video-auto-blacklist/list' 156 this.videoAutoBlacklistUrl = '/admin/moderation/video-auto-blacklist/list'
133 // Backward compatibility where we did not assign videoBlacklist to this type of notification before 157 // Backward compatibility where we did not assign videoBlacklist to this type of notification before
diff --git a/client/src/app/shared/shared-main/users/user-notification.service.ts b/client/src/app/shared/shared-main/users/user-notification.service.ts
index ecc66ecdb..7b9dc34be 100644
--- a/client/src/app/shared/shared-main/users/user-notification.service.ts
+++ b/client/src/app/shared/shared-main/users/user-notification.service.ts
@@ -1,7 +1,7 @@
1import { catchError, map, tap } from 'rxjs/operators' 1import { catchError, map, tap } from 'rxjs/operators'
2import { HttpClient, HttpParams } from '@angular/common/http' 2import { HttpClient, HttpParams } from '@angular/common/http'
3import { Injectable } from '@angular/core' 3import { Injectable } from '@angular/core'
4import { ComponentPaginationLight, RestExtractor, RestService, User, UserNotificationSocket } from '@app/core' 4import { ComponentPaginationLight, RestExtractor, RestService, User, UserNotificationSocket, AuthService } from '@app/core'
5import { ResultList, UserNotification as UserNotificationServer, UserNotificationSetting } from '@shared/models' 5import { ResultList, UserNotification as UserNotificationServer, UserNotificationSetting } from '@shared/models'
6import { environment } from '../../../../environments/environment' 6import { environment } from '../../../../environments/environment'
7import { UserNotification } from './user-notification.model' 7import { UserNotification } from './user-notification.model'
@@ -14,6 +14,7 @@ export class UserNotificationService {
14 14
15 constructor ( 15 constructor (
16 private authHttp: HttpClient, 16 private authHttp: HttpClient,
17 private auth: AuthService,
17 private restExtractor: RestExtractor, 18 private restExtractor: RestExtractor,
18 private restService: RestService, 19 private restService: RestService,
19 private userNotificationSocket: UserNotificationSocket 20 private userNotificationSocket: UserNotificationSocket
@@ -84,6 +85,6 @@ export class UserNotificationService {
84 } 85 }
85 86
86 private formatNotification (notification: UserNotificationServer) { 87 private formatNotification (notification: UserNotificationServer) {
87 return new UserNotification(notification) 88 return new UserNotification(notification, this.auth.getUser())
88 } 89 }
89} 90}
diff --git a/client/src/app/shared/shared-main/users/user-notifications.component.html b/client/src/app/shared/shared-main/users/user-notifications.component.html
index 8127ae979..a56a0859b 100644
--- a/client/src/app/shared/shared-main/users/user-notifications.component.html
+++ b/client/src/app/shared/shared-main/users/user-notifications.component.html
@@ -46,20 +46,38 @@
46 <my-global-icon iconName="flag" aria-hidden="true"></my-global-icon> 46 <my-global-icon iconName="flag" aria-hidden="true"></my-global-icon>
47 47
48 <div class="message" *ngIf="notification.videoUrl" i18n> 48 <div class="message" *ngIf="notification.videoUrl" i18n>
49 <a (click)="markAsRead(notification)" [routerLink]="notification.abuseUrl">A new video abuse</a> has been created on video <a (click)="markAsRead(notification)" [routerLink]="notification.videoUrl">{{ notification.abuse.video.name }}</a> 49 <a (click)="markAsRead(notification)" [routerLink]="notification.abuseUrl" [queryParams]="notification.abuseQueryParams">A new video abuse</a> has been created on video <a (click)="markAsRead(notification)" [routerLink]="notification.videoUrl">{{ notification.abuse.video.name }}</a>
50 </div> 50 </div>
51 51
52 <div class="message" *ngIf="notification.commentUrl" i18n> 52 <div class="message" *ngIf="notification.commentUrl" i18n>
53 <a (click)="markAsRead(notification)" [routerLink]="notification.abuseUrl">A new comment abuse</a> has been created on video <a (click)="markAsRead(notification)" [routerLink]="notification.commentUrl">{{ notification.abuse.comment.video.name }}</a> 53 <a (click)="markAsRead(notification)" [routerLink]="notification.abuseUrl" [queryParams]="notification.abuseQueryParams">A new comment abuse</a> has been created on video <a (click)="markAsRead(notification)" [routerLink]="notification.commentUrl">{{ notification.abuse.comment.video.name }}</a>
54 </div> 54 </div>
55 55
56 <div class="message" *ngIf="notification.accountUrl" i18n> 56 <div class="message" *ngIf="notification.accountUrl" i18n>
57 <a (click)="markAsRead(notification)" [routerLink]="notification.abuseUrl">A new account abuse</a> has been created on account <a (click)="markAsRead(notification)" [routerLink]="notification.accountUrl">{{ notification.abuse.account.displayName }}</a> 57 <a (click)="markAsRead(notification)" [routerLink]="notification.abuseUrl" [queryParams]="notification.abuseQueryParams">A new account abuse</a> has been created on account <a (click)="markAsRead(notification)" [routerLink]="notification.accountUrl">{{ notification.abuse.account.displayName }}</a>
58 </div> 58 </div>
59 59
60 <!-- Deleted entity associated to the abuse --> 60 <!-- Deleted entity associated to the abuse -->
61 <div class="message" *ngIf="!notification.videoUrl && !notification.commentUrl && !notification.accountUrl" i18n> 61 <div class="message" *ngIf="!notification.videoUrl && !notification.commentUrl && !notification.accountUrl" i18n>
62 <a (click)="markAsRead(notification)" [routerLink]="notification.abuseUrl">A new abuse</a> has been created 62 <a (click)="markAsRead(notification)" [routerLink]="notification.abuseUrl" [queryParams]="notification.abuseQueryParams">A new abuse</a> has been created
63 </div>
64 </ng-container>
65
66 <ng-container *ngSwitchCase="UserNotificationType.ABUSE_STATE_CHANGE">
67 <my-global-icon iconName="flag" aria-hidden="true"></my-global-icon>
68
69 <div class="message" i18n>
70 <a (click)="markAsRead(notification)" [routerLink]="notification.abuseUrl" [queryParams]="notification.abuseQueryParams">Your abuse {{ notification.abuse.id }}</a> has been
71 <ng-container *ngIf="isAccepted(notification)">accepted</ng-container>
72 <ng-container *ngIf="!isAccepted(notification)">rejected</ng-container>
73 </div>
74 </ng-container>
75
76 <ng-container *ngSwitchCase="UserNotificationType.ABUSE_NEW_MESSAGE">
77 <my-global-icon iconName="flag" aria-hidden="true"></my-global-icon>
78
79 <div class="message" i18n>
80 <a (click)="markAsRead(notification)" [routerLink]="notification.abuseUrl" [queryParams]="notification.abuseQueryParams">Abuse {{ notification.abuse.id }}</a> has a new message
63 </div> 81 </div>
64 </ng-container> 82 </ng-container>
65 83
diff --git a/client/src/app/shared/shared-main/users/user-notifications.component.ts b/client/src/app/shared/shared-main/users/user-notifications.component.ts
index 7518dbdd0..387c49d94 100644
--- a/client/src/app/shared/shared-main/users/user-notifications.component.ts
+++ b/client/src/app/shared/shared-main/users/user-notifications.component.ts
@@ -1,7 +1,7 @@
1import { Subject } from 'rxjs' 1import { Subject } from 'rxjs'
2import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core' 2import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
3import { ComponentPagination, hasMoreItems, Notifier } from '@app/core' 3import { ComponentPagination, hasMoreItems, Notifier } from '@app/core'
4import { UserNotificationType } from '@shared/models' 4import { UserNotificationType, AbuseState } from '@shared/models'
5import { UserNotification } from './user-notification.model' 5import { UserNotification } from './user-notification.model'
6import { UserNotificationService } from './user-notification.service' 6import { UserNotificationService } from './user-notification.service'
7 7
@@ -116,4 +116,8 @@ export class UserNotificationsComponent implements OnInit {
116 this.sortField = column 116 this.sortField = column
117 this.loadNotifications(true) 117 this.loadNotifications(true)
118 } 118 }
119
120 isAccepted (notification: UserNotification) {
121 return notification.abuse.state === AbuseState.ACCEPTED
122 }
119} 123}