1 import { SortMeta } from 'primeng/api'
2 import { finalize } from 'rxjs/operators'
3 import { Component, OnInit, ViewChild } from '@angular/core'
4 import { ActivatedRoute, Router } from '@angular/router'
5 import { AuthService, ConfirmService, Notifier, RestPagination, RestTable } from '@app/core'
6 import { prepareIcu } from '@app/helpers'
7 import { AdvancedInputFilter } from '@app/shared/shared-forms'
8 import { DropdownAction, Video, VideoService } from '@app/shared/shared-main'
9 import { VideoBlockComponent, VideoBlockService } from '@app/shared/shared-moderation'
10 import { VideoActionsDisplayType } from '@app/shared/shared-video-miniature'
11 import { UserRight, VideoPrivacy, VideoState, VideoStreamingPlaylistType } from '@shared/models'
12 import { VideoAdminService } from './video-admin.service'
15 selector: 'my-video-list',
16 templateUrl: './video-list.component.html',
17 styleUrls: [ './video-list.component.scss' ]
19 export class VideoListComponent extends RestTable implements OnInit {
20 @ViewChild('videoBlockModal') videoBlockModal: VideoBlockComponent
25 sort: SortMeta = { field: 'publishedAt', order: -1 }
26 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
28 bulkVideoActions: DropdownAction<Video[]>[][] = []
30 selectedVideos: Video[] = []
32 inputFilters: AdvancedInputFilter[]
34 videoActionsOptions: VideoActionsDisplayType = {
53 protected route: ActivatedRoute,
54 protected router: Router,
55 private confirmService: ConfirmService,
56 private auth: AuthService,
57 private notifier: Notifier,
58 private videoService: VideoService,
59 private videoAdminService: VideoAdminService,
60 private videoBlockService: VideoBlockService
66 return this.auth.getUser()
72 this.inputFilters = this.videoAdminService.buildAdminInputFilter()
74 this.bulkVideoActions = [
77 label: $localize`Delete`,
78 handler: videos => this.removeVideos(videos),
79 isDisplayed: () => this.authUser.hasRight(UserRight.REMOVE_ANY_VIDEO),
83 label: $localize`Block`,
84 handler: videos => this.videoBlockModal.show(videos),
85 isDisplayed: videos => this.authUser.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) && videos.every(v => !v.blacklisted),
89 label: $localize`Unblock`,
90 handler: videos => this.unblockVideos(videos),
91 isDisplayed: videos => this.authUser.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) && videos.every(v => v.blacklisted),
97 label: $localize`Run HLS transcoding`,
98 handler: videos => this.runTranscoding(videos, 'hls'),
99 isDisplayed: videos => videos.every(v => v.canRunTranscoding(this.authUser)),
103 label: $localize`Run WebTorrent transcoding`,
104 handler: videos => this.runTranscoding(videos, 'webtorrent'),
105 isDisplayed: videos => videos.every(v => v.canRunTranscoding(this.authUser)),
109 label: $localize`Delete HLS files`,
110 handler: videos => this.removeVideoFiles(videos, 'hls'),
111 isDisplayed: videos => videos.every(v => v.canRemoveFiles(this.authUser)),
115 label: $localize`Delete WebTorrent files`,
116 handler: videos => this.removeVideoFiles(videos, 'webtorrent'),
117 isDisplayed: videos => videos.every(v => v.canRemoveFiles(this.authUser)),
125 return 'VideoListComponent'
128 isInSelectionMode () {
129 return this.selectedVideos.length !== 0
132 getPrivacyBadgeClass (video: Video) {
133 if (video.privacy.id === VideoPrivacy.PUBLIC) return 'badge-green'
135 return 'badge-yellow'
138 isUnpublished (video: Video) {
139 return video.state.id !== VideoState.LIVE_ENDED && video.state.id !== VideoState.PUBLISHED
142 isAccountBlocked (video: Video) {
143 return video.blockedOwner
146 isServerBlocked (video: Video) {
147 return video.blockedServer
150 isVideoBlocked (video: Video) {
151 return video.blacklisted
154 isImport (video: Video) {
155 return video.state.id === VideoState.TO_IMPORT
158 isHLS (video: Video) {
159 const p = video.streamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS)
162 return p.files.length !== 0
165 isWebTorrent (video: Video) {
166 return video.files.length !== 0
169 getFilesSize (video: Video) {
170 let files = video.files
172 if (this.isHLS(video)) {
173 files = files.concat(video.streamingPlaylists[0].files)
176 return files.reduce((p, f) => p += f.size, 0)
180 this.selectedVideos = []
184 this.videoAdminService.getAdminVideos({
185 pagination: this.pagination,
188 }).pipe(finalize(() => this.loading = false))
190 next: resultList => {
191 this.videos = resultList.data
192 this.totalRecords = resultList.total
195 error: err => this.notifier.error(err.message)
199 private async removeVideos (videos: Video[]) {
200 const message = prepareIcu($localize`Are you sure you want to delete {count, plural, =1 {this video} other {these {count} videos}}?`)(
201 { count: videos.length },
202 $localize`Are you sure you want to delete these ${videos.length} videos?`
205 const res = await this.confirmService.confirm(message, $localize`Delete`)
206 if (res === false) return
208 this.videoService.removeVideo(videos.map(v => v.id))
211 this.notifier.success(
212 prepareIcu($localize`Deleted {count, plural, =1 {1 video} other {{count} videos}}.`)(
213 { count: videos.length },
214 $localize`Deleted ${videos.length} videos.`
221 error: err => this.notifier.error(err.message)
225 private unblockVideos (videos: Video[]) {
226 this.videoBlockService.unblockVideo(videos.map(v => v.id))
229 this.notifier.success(
230 prepareIcu($localize`Unblocked {count, plural, =1 {1 video} other {{count} videos}}.`)(
231 { count: videos.length },
232 $localize`Unblocked ${videos.length} videos.`
239 error: err => this.notifier.error(err.message)
243 private async removeVideoFiles (videos: Video[], type: 'hls' | 'webtorrent') {
246 if (type === 'hls') {
247 // eslint-disable-next-line max-len
248 message = prepareIcu($localize`Are you sure you want to delete {count, plural, =1 {1 HLS streaming playlist} other {{count} HLS streaming playlists}}?`)(
249 { count: videos.length },
250 $localize`Are you sure you want to delete ${videos.length} HLS streaming playlists?`
253 // eslint-disable-next-line max-len
254 message = prepareIcu($localize`Are you sure you want to delete WebTorrent files of {count, plural, =1 {1 video} other {{count} videos}}?`)(
255 { count: videos.length },
256 $localize`Are you sure you want to delete WebTorrent files of ${videos.length} videos?`
260 const res = await this.confirmService.confirm(message, $localize`Delete`)
261 if (res === false) return
263 this.videoService.removeVideoFiles(videos.map(v => v.id), type)
266 this.notifier.success($localize`Files were removed.`)
270 error: err => this.notifier.error(err.message)
274 private runTranscoding (videos: Video[], type: 'hls' | 'webtorrent') {
275 this.videoService.runTranscoding(videos.map(v => v.id), type)
278 this.notifier.success($localize`Transcoding jobs created.`)
283 error: err => this.notifier.error(err.message)