aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/shared
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/shared')
-rw-r--r--client/src/app/shared/shared-abuse-list/abuse-details.component.html4
-rw-r--r--client/src/app/shared/shared-abuse-list/abuse-list-table.component.html40
-rw-r--r--client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts18
-rw-r--r--client/src/app/shared/shared-abuse-list/processed-abuse.model.ts4
-rw-r--r--client/src/app/shared/shared-abuse-list/shared-abuse-list.module.ts6
-rw-r--r--client/src/app/shared/shared-main/shared-main.module.ts13
-rw-r--r--client/src/app/shared/shared-main/video/embed.component.html3
-rw-r--r--client/src/app/shared/shared-main/video/embed.component.scss10
-rw-r--r--client/src/app/shared/shared-main/video/embed.component.ts35
-rw-r--r--client/src/app/shared/shared-main/video/index.ts1
-rw-r--r--client/src/app/shared/shared-main/video/video.service.ts85
-rw-r--r--client/src/app/shared/shared-moderation/moderation.scss77
-rw-r--r--client/src/app/shared/shared-moderation/report-modals/report.component.scss6
-rw-r--r--client/src/app/shared/shared-moderation/report-modals/video-report.component.html4
-rw-r--r--client/src/app/shared/shared-moderation/report-modals/video-report.component.ts21
-rw-r--r--client/src/app/shared/shared-tables/index.ts3
-rw-r--r--client/src/app/shared/shared-tables/shared-tables.module.ts25
-rw-r--r--client/src/app/shared/shared-tables/table-expander-icon.component.ts12
-rw-r--r--client/src/app/shared/shared-tables/video-cell.component.html19
-rw-r--r--client/src/app/shared/shared-tables/video-cell.component.scss74
-rw-r--r--client/src/app/shared/shared-tables/video-cell.component.ts15
21 files changed, 298 insertions, 177 deletions
diff --git a/client/src/app/shared/shared-abuse-list/abuse-details.component.html b/client/src/app/shared/shared-abuse-list/abuse-details.component.html
index 2f0bc5ae5..a1a4586f0 100644
--- a/client/src/app/shared/shared-abuse-list/abuse-details.component.html
+++ b/client/src/app/shared/shared-abuse-list/abuse-details.component.html
@@ -85,9 +85,9 @@
85 85
86 <!-- report right part (video/comment details) --> 86 <!-- report right part (video/comment details) -->
87 <div class="right"> 87 <div class="right">
88 <div *ngIf="abuse.video" class="screenratio"> 88 <div *ngIf="abuse.video">
89 <div *ngIf="abuse.video.deleted" i18n>The video was deleted</div> 89 <div *ngIf="abuse.video.deleted" i18n>The video was deleted</div>
90 <div *ngIf="!abuse.video.deleted" [innerHTML]="abuse.embedHtml"></div> 90 <my-embed *ngIf="!abuse.video.deleted" [video]="abuse.video"></my-embed>
91 </div> 91 </div>
92 92
93 <div *ngIf="abuse.comment" class="comment-html"> 93 <div *ngIf="abuse.comment" class="comment-html">
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 4bf83316b..d957eaeab 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
@@ -30,9 +30,7 @@
30 <ng-template pTemplate="body" let-expanded="expanded" let-abuse> 30 <ng-template pTemplate="body" let-expanded="expanded" let-abuse>
31 <tr> 31 <tr>
32 <td class="expand-cell c-hand" [pRowToggler]="abuse" i18n-ngbTooltip ngbTooltip="More information" placement="top-left" container="body"> 32 <td class="expand-cell c-hand" [pRowToggler]="abuse" i18n-ngbTooltip ngbTooltip="More information" placement="top-left" container="body">
33 <span class="expander"> 33 <my-table-expander-icon [expanded]="expanded"></my-table-expander-icon>
34 <i [ngClass]="expanded ? 'glyphicon glyphicon-menu-down' : 'glyphicon glyphicon-menu-right'"></i>
35 </span>
36 </td> 34 </td>
37 35
38 <td class="action-cell"> 36 <td class="action-cell">
@@ -61,28 +59,20 @@
61 <ng-container *ngIf="abuse.video"> 59 <ng-container *ngIf="abuse.video">
62 60
63 <td *ngIf="!abuse.video.deleted"> 61 <td *ngIf="!abuse.video.deleted">
64 <a [href]="getVideoUrl(abuse)" class="table-video-link" [title]="abuse.video.name" target="_blank" rel="noopener noreferrer"> 62 <my-video-cell [video]="abuse.video">
65 <div class="table-video"> 63 <span image>
66 <div class="table-video-image"> 64 <span
67 <img [src]="abuse.video.thumbnailPath"> 65 class="table-video-image-label" *ngIf="abuse.count > 1"
68 <span 66 i18n-title title="This video has been reported multiple times."
69 class="table-video-image-label" *ngIf="abuse.count > 1" 67 >
70 i18n-title title="This video has been reported multiple times." 68 {{ abuse.nth }}/{{ abuse.count }}
71 > 69 </span>
72 {{ abuse.nth }}/{{ abuse.count }} 70 </span>
73 </span> 71
74 </div> 72 <span name>
75 73 <span *ngIf="abuse.video.blacklisted" i18n-title title="The video was blocked" class="glyphicon glyphicon-ban-circle"></span>
76 <div class="table-video-text"> 74 </span>
77 <div> 75 </my-video-cell>
78 <span *ngIf="!abuse.video.blacklisted" class="glyphicon glyphicon-new-window"></span>
79 <span *ngIf="abuse.video.blacklisted" i18n-title title="The video was blocked" class="glyphicon glyphicon-ban-circle"></span>
80 {{ abuse.video.name }}
81 </div>
82 <div i18n>by {{ abuse.video.channel?.displayName }} on {{ abuse.video.channel?.host }} </div>
83 </div>
84 </div>
85 </a>
86 </td> 76 </td>
87 77
88 <td *ngIf="abuse.video.deleted" class="c-hand" [pRowToggler]="abuse"> 78 <td *ngIf="abuse.video.deleted" class="c-hand" [pRowToggler]="abuse">
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 297993e39..10f5861b9 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
@@ -1,8 +1,6 @@
1import * as debug from 'debug' 1import * as debug from 'debug'
2import truncate from 'lodash-es/truncate' 2import truncate from 'lodash-es/truncate'
3import { SortMeta } from 'primeng/api' 3import { SortMeta } from 'primeng/api'
4import { buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
5import { environment } from 'src/environments/environment'
6import { Component, Input, OnInit, ViewChild } from '@angular/core' 4import { Component, Input, OnInit, ViewChild } from '@angular/core'
7import { DomSanitizer } from '@angular/platform-browser' 5import { DomSanitizer } from '@angular/platform-browser'
8import { ActivatedRoute, Router } from '@angular/router' 6import { ActivatedRoute, Router } from '@angular/router'
@@ -10,7 +8,6 @@ import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable }
10import { Account, Actor, DropdownAction, Video, VideoService } from '@app/shared/shared-main' 8import { Account, Actor, DropdownAction, Video, VideoService } from '@app/shared/shared-main'
11import { AbuseService, BlocklistService, VideoBlockService } from '@app/shared/shared-moderation' 9import { AbuseService, BlocklistService, VideoBlockService } from '@app/shared/shared-moderation'
12import { VideoCommentService } from '@app/shared/shared-video-comment' 10import { VideoCommentService } from '@app/shared/shared-video-comment'
13import { buildVideoEmbedLink, decorateVideoLink } from '@shared/core-utils'
14import { AbuseState, AdminAbuse } from '@shared/models' 11import { AbuseState, AdminAbuse } from '@shared/models'
15import { AdvancedInputFilter } from '../shared-forms' 12import { AdvancedInputFilter } from '../shared-forms'
16import { AbuseMessageModalComponent } from './abuse-message-modal.component' 13import { AbuseMessageModalComponent } from './abuse-message-modal.component'
@@ -133,19 +130,6 @@ export class AbuseListTableComponent extends RestTable implements OnInit {
133 return '/a/' + abuse.flaggedAccount.nameWithHost 130 return '/a/' + abuse.flaggedAccount.nameWithHost
134 } 131 }
135 132
136 getVideoEmbed (abuse: AdminAbuse) {
137 return buildVideoOrPlaylistEmbed(
138 decorateVideoLink({
139 url: buildVideoEmbedLink(abuse.video, environment.originServerUrl),
140 title: false,
141 warningTitle: false,
142 startTime: abuse.video.startAt,
143 stopTime: abuse.video.endAt
144 }),
145 abuse.video.name
146 )
147 }
148
149 async removeAbuse (abuse: AdminAbuse) { 133 async removeAbuse (abuse: AdminAbuse) {
150 const res = await this.confirmService.confirm($localize`Do you really want to delete this abuse report?`, $localize`Delete`) 134 const res = await this.confirmService.confirm($localize`Do you really want to delete this abuse report?`, $localize`Delete`)
151 if (res === false) return 135 if (res === false) return
@@ -220,8 +204,6 @@ export class AbuseListTableComponent extends RestTable implements OnInit {
220 } 204 }
221 205
222 if (abuse.video) { 206 if (abuse.video) {
223 abuse.embedHtml = this.sanitizer.bypassSecurityTrustHtml(this.getVideoEmbed(abuse))
224
225 if (abuse.video.channel?.ownerAccount) { 207 if (abuse.video.channel?.ownerAccount) {
226 abuse.video.channel.ownerAccount = new Account(abuse.video.channel.ownerAccount) 208 abuse.video.channel.ownerAccount = new Account(abuse.video.channel.ownerAccount)
227 } 209 }
diff --git a/client/src/app/shared/shared-abuse-list/processed-abuse.model.ts b/client/src/app/shared/shared-abuse-list/processed-abuse.model.ts
index 194d52a33..b9a9bd889 100644
--- a/client/src/app/shared/shared-abuse-list/processed-abuse.model.ts
+++ b/client/src/app/shared/shared-abuse-list/processed-abuse.model.ts
@@ -1,13 +1,11 @@
1import { SafeHtml } from '@angular/platform-browser'
2import { AdminAbuse } from '@shared/models'
3import { Account } from '@app/shared/shared-main' 1import { Account } from '@app/shared/shared-main'
2import { AdminAbuse } from '@shared/models'
4 3
5// Don't use an abuse model because we need external services to compute some properties 4// Don't use an abuse model because we need external services to compute some properties
6// And this model is only used in this component 5// And this model is only used in this component
7export type ProcessedAbuse = AdminAbuse & { 6export type ProcessedAbuse = AdminAbuse & {
8 moderationCommentHtml?: string 7 moderationCommentHtml?: string
9 reasonHtml?: string 8 reasonHtml?: string
10 embedHtml?: SafeHtml
11 updatedAt?: Date 9 updatedAt?: Date
12 10
13 // override bare server-side definitions with rich client-side definitions 11 // override bare server-side definitions with rich client-side definitions
diff --git a/client/src/app/shared/shared-abuse-list/shared-abuse-list.module.ts b/client/src/app/shared/shared-abuse-list/shared-abuse-list.module.ts
index 8f3830a17..eeda27fa6 100644
--- a/client/src/app/shared/shared-abuse-list/shared-abuse-list.module.ts
+++ b/client/src/app/shared/shared-abuse-list/shared-abuse-list.module.ts
@@ -1,16 +1,17 @@
1 1
2import { TableModule } from 'primeng/table' 2import { TableModule } from 'primeng/table'
3import { NgModule } from '@angular/core' 3import { NgModule } from '@angular/core'
4import { SharedActorImageModule } from '../shared-actor-image/shared-actor-image.module'
4import { SharedFormModule } from '../shared-forms/shared-form.module' 5import { SharedFormModule } from '../shared-forms/shared-form.module'
5import { SharedGlobalIconModule } from '../shared-icons' 6import { SharedGlobalIconModule } from '../shared-icons'
6import { SharedMainModule } from '../shared-main/shared-main.module' 7import { SharedMainModule } from '../shared-main/shared-main.module'
7import { SharedModerationModule } from '../shared-moderation' 8import { SharedModerationModule } from '../shared-moderation'
9import { SharedTablesModule } from '../shared-tables'
8import { SharedVideoCommentModule } from '../shared-video-comment' 10import { SharedVideoCommentModule } from '../shared-video-comment'
9import { AbuseDetailsComponent } from './abuse-details.component' 11import { AbuseDetailsComponent } from './abuse-details.component'
10import { AbuseListTableComponent } from './abuse-list-table.component' 12import { AbuseListTableComponent } from './abuse-list-table.component'
11import { AbuseMessageModalComponent } from './abuse-message-modal.component' 13import { AbuseMessageModalComponent } from './abuse-message-modal.component'
12import { ModerationCommentModalComponent } from './moderation-comment-modal.component' 14import { ModerationCommentModalComponent } from './moderation-comment-modal.component'
13import { SharedActorImageModule } from '../shared-actor-image/shared-actor-image.module'
14 15
15@NgModule({ 16@NgModule({
16 imports: [ 17 imports: [
@@ -21,7 +22,8 @@ import { SharedActorImageModule } from '../shared-actor-image/shared-actor-image
21 SharedModerationModule, 22 SharedModerationModule,
22 SharedGlobalIconModule, 23 SharedGlobalIconModule,
23 SharedVideoCommentModule, 24 SharedVideoCommentModule,
24 SharedActorImageModule 25 SharedActorImageModule,
26 SharedTablesModule
25 ], 27 ],
26 28
27 declarations: [ 29 declarations: [
diff --git a/client/src/app/shared/shared-main/shared-main.module.ts b/client/src/app/shared/shared-main/shared-main.module.ts
index 93989780d..a90b59e41 100644
--- a/client/src/app/shared/shared-main/shared-main.module.ts
+++ b/client/src/app/shared/shared-main/shared-main.module.ts
@@ -43,13 +43,8 @@ import {
43} from './misc' 43} from './misc'
44import { PluginPlaceholderComponent } from './plugins' 44import { PluginPlaceholderComponent } from './plugins'
45import { ActorRedirectGuard } from './router' 45import { ActorRedirectGuard } from './router'
46import { 46import { UserHistoryService, UserNotificationsComponent, UserNotificationService, UserQuotaComponent } from './users'
47 UserHistoryService, 47import { EmbedComponent, RedundancyService, VideoImportService, VideoOwnershipService, VideoService } from './video'
48 UserNotificationsComponent,
49 UserNotificationService,
50 UserQuotaComponent
51} from './users'
52import { RedundancyService, VideoImportService, VideoOwnershipService, VideoService } from './video'
53import { VideoCaptionService } from './video-caption' 48import { VideoCaptionService } from './video-caption'
54import { VideoChannelService } from './video-channel' 49import { VideoChannelService } from './video-channel'
55 50
@@ -111,6 +106,8 @@ import { VideoChannelService } from './video-channel'
111 UserQuotaComponent, 106 UserQuotaComponent,
112 UserNotificationsComponent, 107 UserNotificationsComponent,
113 108
109 EmbedComponent,
110
114 PluginPlaceholderComponent 111 PluginPlaceholderComponent
115 ], 112 ],
116 113
@@ -167,6 +164,8 @@ import { VideoChannelService } from './video-channel'
167 UserQuotaComponent, 164 UserQuotaComponent,
168 UserNotificationsComponent, 165 UserNotificationsComponent,
169 166
167 EmbedComponent,
168
170 PluginPlaceholderComponent 169 PluginPlaceholderComponent
171 ], 170 ],
172 171
diff --git a/client/src/app/shared/shared-main/video/embed.component.html b/client/src/app/shared/shared-main/video/embed.component.html
new file mode 100644
index 000000000..3b088d058
--- /dev/null
+++ b/client/src/app/shared/shared-main/video/embed.component.html
@@ -0,0 +1,3 @@
1<div class="screenratio">
2 <div [innerHTML]="embedHTML"></div>
3</div>
diff --git a/client/src/app/shared/shared-main/video/embed.component.scss b/client/src/app/shared/shared-main/video/embed.component.scss
new file mode 100644
index 000000000..420ba6f23
--- /dev/null
+++ b/client/src/app/shared/shared-main/video/embed.component.scss
@@ -0,0 +1,10 @@
1@use '_mixins' as *;
2@use '_variables' as *;
3
4.screenratio {
5 @include block-ratio($selector: 'div, ::ng-deep iframe') {
6 width: 100% !important;
7 height: 100% !important;
8 left: 0;
9 };
10}
diff --git a/client/src/app/shared/shared-main/video/embed.component.ts b/client/src/app/shared/shared-main/video/embed.component.ts
new file mode 100644
index 000000000..4732efa44
--- /dev/null
+++ b/client/src/app/shared/shared-main/video/embed.component.ts
@@ -0,0 +1,35 @@
1import { buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
2import { environment } from 'src/environments/environment'
3import { Component, Input, OnInit } from '@angular/core'
4import { DomSanitizer, SafeHtml } from '@angular/platform-browser'
5import { buildVideoEmbedLink, decorateVideoLink } from '@shared/core-utils'
6import { Video } from '@shared/models'
7
8@Component({
9 selector: 'my-embed',
10 styleUrls: [ './embed.component.scss' ],
11 templateUrl: './embed.component.html'
12})
13export class EmbedComponent implements OnInit {
14 @Input() video: Pick<Video, 'name' | 'uuid'>
15
16 embedHTML: SafeHtml
17
18 constructor (private sanitizer: DomSanitizer) {
19
20 }
21
22 ngOnInit () {
23 const html = buildVideoOrPlaylistEmbed(
24 decorateVideoLink({
25 url: buildVideoEmbedLink(this.video, environment.originServerUrl),
26
27 title: false,
28 warningTitle: false
29 }),
30 this.video.name
31 )
32
33 this.embedHTML = this.sanitizer.bypassSecurityTrustHtml(html)
34 }
35}
diff --git a/client/src/app/shared/shared-main/video/index.ts b/client/src/app/shared/shared-main/video/index.ts
index 3053df4ef..e72c0c3d6 100644
--- a/client/src/app/shared/shared-main/video/index.ts
+++ b/client/src/app/shared/shared-main/video/index.ts
@@ -1,3 +1,4 @@
1export * from './embed.component'
1export * from './redundancy.service' 2export * from './redundancy.service'
2export * from './video-details.model' 3export * from './video-details.model'
3export * from './video-edit.model' 4export * from './video-edit.model'
diff --git a/client/src/app/shared/shared-main/video/video.service.ts b/client/src/app/shared/shared-main/video/video.service.ts
index 7935569e7..9e3aa1e6a 100644
--- a/client/src/app/shared/shared-main/video/video.service.ts
+++ b/client/src/app/shared/shared-main/video/video.service.ts
@@ -1,8 +1,9 @@
1import { Observable } from 'rxjs' 1import { SortMeta } from 'primeng/api'
2import { catchError, map, switchMap } from 'rxjs/operators' 2import { from, Observable } from 'rxjs'
3import { catchError, concatMap, map, switchMap, toArray } from 'rxjs/operators'
3import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http' 4import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http'
4import { Injectable } from '@angular/core' 5import { Injectable } from '@angular/core'
5import { ComponentPaginationLight, RestExtractor, RestService, ServerService, UserService } from '@app/core' 6import { ComponentPaginationLight, RestExtractor, RestPagination, RestService, ServerService, UserService } from '@app/core'
6import { objectToFormData } from '@app/helpers' 7import { objectToFormData } from '@app/helpers'
7import { 8import {
8 BooleanBothQuery, 9 BooleanBothQuery,
@@ -31,8 +32,8 @@ import { VideoEdit } from './video-edit.model'
31import { Video } from './video.model' 32import { Video } from './video.model'
32 33
33export type CommonVideoParams = { 34export type CommonVideoParams = {
34 videoPagination: ComponentPaginationLight 35 videoPagination?: ComponentPaginationLight
35 sort: VideoSortField 36 sort: VideoSortField | SortMeta
36 filter?: VideoFilter 37 filter?: VideoFilter
37 categoryOneOf?: number[] 38 categoryOneOf?: number[]
38 languageOneOf?: string[] 39 languageOneOf?: string[]
@@ -200,6 +201,31 @@ export class VideoService {
200 ) 201 )
201 } 202 }
202 203
204 getAdminVideos (
205 parameters: Omit<CommonVideoParams, 'filter'> & { pagination: RestPagination, search?: string }
206 ): Observable<ResultList<Video>> {
207 const { pagination, search } = parameters
208
209 let params = new HttpParams()
210 params = this.buildCommonVideosParams({ params, ...parameters })
211
212 params = params.set('start', pagination.start.toString())
213 .set('count', pagination.count.toString())
214
215 if (search) {
216 params = this.buildAdminParamsFromSearch(search, params)
217 }
218
219 if (!params.has('filter')) params = params.set('filter', 'all')
220
221 return this.authHttp
222 .get<ResultList<Video>>(VideoService.BASE_VIDEO_URL, { params })
223 .pipe(
224 switchMap(res => this.extractVideos(res)),
225 catchError(err => this.restExtractor.handleError(err))
226 )
227 }
228
203 getVideos (parameters: CommonVideoParams): Observable<ResultList<Video>> { 229 getVideos (parameters: CommonVideoParams): Observable<ResultList<Video>> {
204 let params = new HttpParams() 230 let params = new HttpParams()
205 params = this.buildCommonVideosParams({ params, ...parameters }) 231 params = this.buildCommonVideosParams({ params, ...parameters })
@@ -284,13 +310,15 @@ export class VideoService {
284 ) 310 )
285 } 311 }
286 312
287 removeVideo (id: number) { 313 removeVideo (idArg: number | number[]) {
288 return this.authHttp 314 const ids = Array.isArray(idArg) ? idArg : [ idArg ]
289 .delete(VideoService.BASE_VIDEO_URL + id) 315
290 .pipe( 316 return from(ids)
291 map(this.restExtractor.extractDataBool), 317 .pipe(
292 catchError(err => this.restExtractor.handleError(err)) 318 concatMap(id => this.authHttp.delete(VideoService.BASE_VIDEO_URL + id)),
293 ) 319 toArray(),
320 catchError(err => this.restExtractor.handleError(err))
321 )
294 } 322 }
295 323
296 loadCompleteDescription (descriptionPath: string) { 324 loadCompleteDescription (descriptionPath: string) {
@@ -393,9 +421,23 @@ export class VideoService {
393 } 421 }
394 422
395 private buildCommonVideosParams (options: CommonVideoParams & { params: HttpParams }) { 423 private buildCommonVideosParams (options: CommonVideoParams & { params: HttpParams }) {
396 const { params, videoPagination, sort, filter, categoryOneOf, languageOneOf, skipCount, nsfwPolicy, isLive, nsfw } = options 424 const {
425 params,
426 videoPagination,
427 sort,
428 filter,
429 categoryOneOf,
430 languageOneOf,
431 skipCount,
432 nsfwPolicy,
433 isLive,
434 nsfw
435 } = options
436
437 const pagination = videoPagination
438 ? this.restService.componentToRestPagination(videoPagination)
439 : undefined
397 440
398 const pagination = this.restService.componentToRestPagination(videoPagination)
399 let newParams = this.restService.addRestGetParams(params, pagination, sort) 441 let newParams = this.restService.addRestGetParams(params, pagination, sort)
400 442
401 if (filter) newParams = newParams.set('filter', filter) 443 if (filter) newParams = newParams.set('filter', filter)
@@ -409,4 +451,19 @@ export class VideoService {
409 451
410 return newParams 452 return newParams
411 } 453 }
454
455 private buildAdminParamsFromSearch (search: string, params: HttpParams) {
456 const filters = this.restService.parseQueryStringFilter(search, {
457 filter: {
458 prefix: 'local:',
459 handler: v => {
460 if (v === 'true') return 'all-local'
461
462 return 'all'
463 }
464 }
465 })
466
467 return this.restService.addObjectParams(params, filters)
468 }
412} 469}
diff --git a/client/src/app/shared/shared-moderation/moderation.scss b/client/src/app/shared/shared-moderation/moderation.scss
index 815e2791f..eaf5a8250 100644
--- a/client/src/app/shared/shared-moderation/moderation.scss
+++ b/client/src/app/shared/shared-moderation/moderation.scss
@@ -40,14 +40,6 @@
40 } 40 }
41} 41}
42 42
43.screenratio {
44 @include block-ratio($selector: 'div, ::ng-deep iframe') {
45 width: 100% !important;
46 height: 100% !important;
47 left: 0;
48 };
49}
50
51.chip { 43.chip {
52 @include chip; 44 @include chip;
53} 45}
@@ -58,13 +50,6 @@ my-action-dropdown.show {
58 } 50 }
59} 51}
60 52
61.table-video-link {
62 @include disable-outline;
63
64 position: relative;
65 top: 3px;
66}
67
68.table-comment-link, 53.table-comment-link,
69.table-account-link { 54.table-account-link {
70 @include disable-outline; 55 @include disable-outline;
@@ -81,68 +66,6 @@ my-action-dropdown.show {
81 flex-direction: column; 66 flex-direction: column;
82} 67}
83 68
84.table-video {
85 display: inline-flex;
86
87 .table-video-image {
88 $image-height: 45px;
89
90 @include miniature-thumbnail;
91 @include margin-right(0.5rem);
92
93 height: $image-height;
94 width: #{math.div(16, 9) * $image-height};
95 border-radius: 2px;
96 border: 0;
97 background: transparent;
98 display: inline-flex;
99 justify-content: center;
100 position: relative;
101
102 img {
103 height: 100%;
104 width: 100%;
105 border-radius: 2px;
106 }
107
108 span {
109 color: pvar(--inputPlaceholderColor);
110 }
111
112 .table-video-image-label {
113 @include static-thumbnail-overlay;
114 position: absolute;
115 border-radius: 3px;
116 font-size: 10px;
117 padding: 0 3px;
118 line-height: 1.3;
119 bottom: 2px;
120 right: 2px;
121 }
122 }
123
124 .table-video-text {
125 display: inline-flex;
126 flex-direction: column;
127 justify-content: center;
128 font-size: 90%;
129 color: pvar(--mainForegroundColor);
130 line-height: 1rem;
131
132 div .glyphicon {
133 @include margin-left(0.1rem);
134
135 font-size: 80%;
136 color: #808080;
137 }
138
139 div + div {
140 color: var(--greyForegroundColor);
141 font-size: 11px;
142 }
143 }
144}
145
146my-abuse-details { 69my-abuse-details {
147 width: 100%; 70 width: 100%;
148} 71}
diff --git a/client/src/app/shared/shared-moderation/report-modals/report.component.scss b/client/src/app/shared/shared-moderation/report-modals/report.component.scss
index 06e50ac2d..76ec0a6ed 100644
--- a/client/src/app/shared/shared-moderation/report-modals/report.component.scss
+++ b/client/src/app/shared/shared-moderation/report-modals/report.component.scss
@@ -19,9 +19,3 @@ textarea {
19 @include margin-left(10px); 19 @include margin-left(10px);
20 } 20 }
21} 21}
22
23.screenratio {
24 @include block-ratio($selector: 'div, ::ng-deep iframe') {
25 left: 0;
26 };
27}
diff --git a/client/src/app/shared/shared-moderation/report-modals/video-report.component.html b/client/src/app/shared/shared-moderation/report-modals/video-report.component.html
index 1aae64bff..afac108fc 100644
--- a/client/src/app/shared/shared-moderation/report-modals/video-report.component.html
+++ b/client/src/app/shared/shared-moderation/report-modals/video-report.component.html
@@ -35,9 +35,7 @@
35 <div class="col-7"> 35 <div class="col-7">
36 <div class="row justify-content-center"> 36 <div class="row justify-content-center">
37 <div class="col-12 col-lg-9 mb-2"> 37 <div class="col-12 col-lg-9 mb-2">
38 <div class="screenratio"> 38 <my-embed [video]="video"></my-embed>
39 <div [innerHTML]="embedHtml"></div>
40 </div>
41 </div> 39 </div>
42 </div> 40 </div>
43 41
diff --git a/client/src/app/shared/shared-moderation/report-modals/video-report.component.ts b/client/src/app/shared/shared-moderation/report-modals/video-report.component.ts
index 278d60ac6..38dd92910 100644
--- a/client/src/app/shared/shared-moderation/report-modals/video-report.component.ts
+++ b/client/src/app/shared/shared-moderation/report-modals/video-report.component.ts
@@ -1,13 +1,11 @@
1import { mapValues, pickBy } from 'lodash-es' 1import { mapValues, pickBy } from 'lodash-es'
2import { buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
3import { Component, Input, OnInit, ViewChild } from '@angular/core' 2import { Component, Input, OnInit, ViewChild } from '@angular/core'
4import { DomSanitizer, SafeHtml } from '@angular/platform-browser' 3import { DomSanitizer } from '@angular/platform-browser'
5import { Notifier } from '@app/core' 4import { Notifier } from '@app/core'
6import { ABUSE_REASON_VALIDATOR } from '@app/shared/form-validators/abuse-validators' 5import { ABUSE_REASON_VALIDATOR } from '@app/shared/form-validators/abuse-validators'
7import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' 6import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
8import { NgbModal } from '@ng-bootstrap/ng-bootstrap' 7import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
9import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' 8import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
10import { decorateVideoLink } from '@shared/core-utils'
11import { abusePredefinedReasonsMap } from '@shared/core-utils/abuse' 9import { abusePredefinedReasonsMap } from '@shared/core-utils/abuse'
12import { AbusePredefinedReasonsString } from '@shared/models' 10import { AbusePredefinedReasonsString } from '@shared/models'
13import { Video } from '../../shared-main' 11import { Video } from '../../shared-main'
@@ -25,7 +23,6 @@ export class VideoReportComponent extends FormReactive implements OnInit {
25 23
26 error: string = null 24 error: string = null
27 predefinedReasons: { id: AbusePredefinedReasonsString, label: string, description?: string, help?: string }[] = [] 25 predefinedReasons: { id: AbusePredefinedReasonsString, label: string, description?: string, help?: string }[] = []
28 embedHtml: SafeHtml
29 26
30 private openedModal: NgbModalRef 27 private openedModal: NgbModalRef
31 28
@@ -55,20 +52,6 @@ export class VideoReportComponent extends FormReactive implements OnInit {
55 return this.form.get('timestamp').value 52 return this.form.get('timestamp').value
56 } 53 }
57 54
58 getVideoEmbed () {
59 return this.sanitizer.bypassSecurityTrustHtml(
60 buildVideoOrPlaylistEmbed(
61 decorateVideoLink({
62 url: this.video.embedUrl,
63 title: false,
64 warningTitle: false
65 }),
66
67 this.video.name
68 )
69 )
70 }
71
72 ngOnInit () { 55 ngOnInit () {
73 this.buildForm({ 56 this.buildForm({
74 reason: ABUSE_REASON_VALIDATOR, 57 reason: ABUSE_REASON_VALIDATOR,
@@ -82,8 +65,6 @@ export class VideoReportComponent extends FormReactive implements OnInit {
82 }) 65 })
83 66
84 this.predefinedReasons = this.abuseService.getPrefefinedReasons('video') 67 this.predefinedReasons = this.abuseService.getPrefefinedReasons('video')
85
86 this.embedHtml = this.getVideoEmbed()
87 } 68 }
88 69
89 show () { 70 show () {
diff --git a/client/src/app/shared/shared-tables/index.ts b/client/src/app/shared/shared-tables/index.ts
new file mode 100644
index 000000000..e7b593257
--- /dev/null
+++ b/client/src/app/shared/shared-tables/index.ts
@@ -0,0 +1,3 @@
1export * from './table-expander-icon.component'
2export * from './video-cell.component'
3export * from './shared-tables.module'
diff --git a/client/src/app/shared/shared-tables/shared-tables.module.ts b/client/src/app/shared/shared-tables/shared-tables.module.ts
new file mode 100644
index 000000000..c528365a0
--- /dev/null
+++ b/client/src/app/shared/shared-tables/shared-tables.module.ts
@@ -0,0 +1,25 @@
1
2import { NgModule } from '@angular/core'
3import { SharedMainModule } from '../shared-main/shared-main.module'
4import { TableExpanderIconComponent } from './table-expander-icon.component'
5import { VideoCellComponent } from './video-cell.component'
6
7@NgModule({
8 imports: [
9 SharedMainModule
10 ],
11
12 declarations: [
13 VideoCellComponent,
14 TableExpanderIconComponent
15 ],
16
17 exports: [
18 VideoCellComponent,
19 TableExpanderIconComponent
20 ],
21
22 providers: [
23 ]
24})
25export class SharedTablesModule { }
diff --git a/client/src/app/shared/shared-tables/table-expander-icon.component.ts b/client/src/app/shared/shared-tables/table-expander-icon.component.ts
new file mode 100644
index 000000000..3756b475a
--- /dev/null
+++ b/client/src/app/shared/shared-tables/table-expander-icon.component.ts
@@ -0,0 +1,12 @@
1import { Component, Input } from '@angular/core'
2
3@Component({
4 selector: 'my-table-expander-icon',
5 template: `
6<span class="expander">
7 <i [ngClass]="expanded ? 'glyphicon glyphicon-menu-down' : 'glyphicon glyphicon-menu-right'"></i>
8</span>`
9})
10export class TableExpanderIconComponent {
11 @Input() expanded: boolean
12}
diff --git a/client/src/app/shared/shared-tables/video-cell.component.html b/client/src/app/shared/shared-tables/video-cell.component.html
new file mode 100644
index 000000000..fb7d852ab
--- /dev/null
+++ b/client/src/app/shared/shared-tables/video-cell.component.html
@@ -0,0 +1,19 @@
1<a [href]="getVideoUrl()" class="table-video-link" [title]="video.name" target="_blank" rel="noopener noreferrer">
2 <div class="table-video">
3 <div class="table-video-image">
4 <img [src]="video.thumbnailPath">
5
6 <ng-content select="[image]"></ng-content>
7 </div>
8
9 <div class="table-video-text">
10 <div>
11 <ng-content select="[name]"></ng-content>
12
13 {{ video.name }}
14 </div>
15
16 <div class="text-muted">by {{ video.channel?.displayName }} on {{ video.channel?.host }} </div>
17 </div>
18 </div>
19</a>
diff --git a/client/src/app/shared/shared-tables/video-cell.component.scss b/client/src/app/shared/shared-tables/video-cell.component.scss
new file mode 100644
index 000000000..7efb61502
--- /dev/null
+++ b/client/src/app/shared/shared-tables/video-cell.component.scss
@@ -0,0 +1,74 @@
1@use 'sass:math';
2@use '_mixins' as *;
3@use '_variables' as *;
4@use '_miniature' as *;
5
6.table-video-link {
7 @include disable-outline;
8
9 position: relative;
10 top: 3px;
11}
12
13.table-video {
14 display: inline-flex;
15
16 .table-video-image {
17 $image-height: 45px;
18
19 @include miniature-thumbnail;
20 @include margin-right(0.5rem);
21
22 height: $image-height;
23 width: #{math.div(16, 9) * $image-height};
24 border-radius: 2px;
25 border: 0;
26 background: transparent;
27 display: inline-flex;
28 justify-content: center;
29 position: relative;
30
31 img {
32 height: 100%;
33 width: 100%;
34 border-radius: 2px;
35 }
36
37 span {
38 color: pvar(--inputPlaceholderColor);
39 }
40
41 .table-video-image-label {
42 @include static-thumbnail-overlay;
43
44 position: absolute;
45 border-radius: 3px;
46 font-size: 10px;
47 padding: 0 3px;
48 line-height: 1.3;
49 bottom: 2px;
50 right: 2px;
51 }
52 }
53
54 .table-video-text {
55 display: inline-flex;
56 flex-direction: column;
57 justify-content: center;
58 font-size: 90%;
59 color: pvar(--mainForegroundColor);
60 line-height: 1rem;
61
62 div .glyphicon {
63 @include margin-left(0.1rem);
64
65 font-size: 80%;
66 color: #808080;
67 }
68
69 div + div {
70 color: var(--greyForegroundColor);
71 font-size: 11px;
72 }
73 }
74}
diff --git a/client/src/app/shared/shared-tables/video-cell.component.ts b/client/src/app/shared/shared-tables/video-cell.component.ts
new file mode 100644
index 000000000..62984180d
--- /dev/null
+++ b/client/src/app/shared/shared-tables/video-cell.component.ts
@@ -0,0 +1,15 @@
1import { Component, Input } from '@angular/core'
2import { Video } from '@app/shared/shared-main'
3
4@Component({
5 selector: 'my-video-cell',
6 styleUrls: [ 'video-cell.component.scss' ],
7 templateUrl: 'video-cell.component.html'
8})
9export class VideoCellComponent {
10 @Input() video: Video
11
12 getVideoUrl () {
13 return Video.buildWatchUrl(this.video)
14 }
15}