aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app')
-rw-r--r--client/src/app/+admin/overview/videos/video-list.component.ts20
-rw-r--r--client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts2
-rw-r--r--client/src/app/+videos/+video-watch/video-watch.component.ts2
-rw-r--r--client/src/app/core/rest/rest.service.ts13
-rw-r--r--client/src/app/shared/shared-main/video-caption/video-caption.service.ts6
-rw-r--r--client/src/app/shared/shared-main/video/video.service.ts79
6 files changed, 79 insertions, 43 deletions
diff --git a/client/src/app/+admin/overview/videos/video-list.component.ts b/client/src/app/+admin/overview/videos/video-list.component.ts
index ed3a86b96..31bf1707b 100644
--- a/client/src/app/+admin/overview/videos/video-list.component.ts
+++ b/client/src/app/+admin/overview/videos/video-list.component.ts
@@ -24,21 +24,7 @@ export class VideoListComponent extends RestTable implements OnInit {
24 24
25 selectedVideos: Video[] = [] 25 selectedVideos: Video[] = []
26 26
27 inputFilters: AdvancedInputFilter[] = [ 27 inputFilters: AdvancedInputFilter[]
28 {
29 title: $localize`Advanced filters`,
30 children: [
31 {
32 queryParams: { search: 'isLocal:false' },
33 label: $localize`Remote videos`
34 },
35 {
36 queryParams: { search: 'isLocal:true' },
37 label: $localize`Local videos`
38 }
39 ]
40 }
41 ]
42 28
43 videoActionsOptions: VideoActionsDisplayType = { 29 videoActionsOptions: VideoActionsDisplayType = {
44 playlist: false, 30 playlist: false,
@@ -52,7 +38,7 @@ export class VideoListComponent extends RestTable implements OnInit {
52 liveInfo: false 38 liveInfo: false
53 } 39 }
54 40
55 loading = false 41 loading = true
56 42
57 constructor ( 43 constructor (
58 protected route: ActivatedRoute, 44 protected route: ActivatedRoute,
@@ -72,6 +58,8 @@ export class VideoListComponent extends RestTable implements OnInit {
72 ngOnInit () { 58 ngOnInit () {
73 this.initialize() 59 this.initialize()
74 60
61 this.inputFilters = this.videoService.buildAdminInputFilter()
62
75 this.bulkVideoActions = [ 63 this.bulkVideoActions = [
76 [ 64 [
77 { 65 {
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts
index 91d89a535..7a7a898a1 100644
--- a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts
+++ b/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts
@@ -49,7 +49,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
49 schedulePublicationPossible = false 49 schedulePublicationPossible = false
50 50
51 // So that it can be accessed in the template 51 // So that it can be accessed in the template
52 protected readonly BASE_VIDEO_UPLOAD_URL = VideoService.BASE_VIDEO_URL + 'upload-resumable' 52 protected readonly BASE_VIDEO_UPLOAD_URL = VideoService.BASE_VIDEO_URL + '/upload-resumable'
53 53
54 private uploadxOptions: UploadxOptions 54 private uploadxOptions: UploadxOptions
55 private isUpdatingVideo = false 55 private isUpdatingVideo = false
diff --git a/client/src/app/+videos/+video-watch/video-watch.component.ts b/client/src/app/+videos/+video-watch/video-watch.component.ts
index f0d159be3..5ca9d5fa9 100644
--- a/client/src/app/+videos/+video-watch/video-watch.component.ts
+++ b/client/src/app/+videos/+video-watch/video-watch.component.ts
@@ -288,7 +288,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
288 private async handleRequestError (err: any) { 288 private async handleRequestError (err: any) {
289 const errorBody = err.body as PeerTubeProblemDocument 289 const errorBody = err.body as PeerTubeProblemDocument
290 290
291 if (errorBody.code === ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS && errorBody.originUrl) { 291 if (errorBody?.code === ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS && errorBody.originUrl) {
292 const originUrl = errorBody.originUrl + (window.location.search ?? '') 292 const originUrl = errorBody.originUrl + (window.location.search ?? '')
293 293
294 const res = await this.confirmService.confirm( 294 const res = await this.confirmService.confirm(
diff --git a/client/src/app/core/rest/rest.service.ts b/client/src/app/core/rest/rest.service.ts
index 93b5f56b2..59152e658 100644
--- a/client/src/app/core/rest/rest.service.ts
+++ b/client/src/app/core/rest/rest.service.ts
@@ -1,13 +1,16 @@
1import * as debug from 'debug'
1import { SortMeta } from 'primeng/api' 2import { SortMeta } from 'primeng/api'
2import { HttpParams } from '@angular/common/http' 3import { HttpParams } from '@angular/common/http'
3import { Injectable } from '@angular/core' 4import { Injectable } from '@angular/core'
4import { ComponentPaginationLight } from './component-pagination.model' 5import { ComponentPaginationLight } from './component-pagination.model'
5import { RestPagination } from './rest-pagination' 6import { RestPagination } from './rest-pagination'
6 7
8const logger = debug('peertube:rest')
9
7interface QueryStringFilterPrefixes { 10interface QueryStringFilterPrefixes {
8 [key: string]: { 11 [key: string]: {
9 prefix: string 12 prefix: string
10 handler?: (v: string) => string | number 13 handler?: (v: string) => string | number | boolean
11 multiple?: boolean 14 multiple?: boolean
12 isBoolean?: boolean 15 isBoolean?: boolean
13 } 16 }
@@ -87,6 +90,8 @@ export class RestService {
87 const prefixeStrings = Object.values(prefixes) 90 const prefixeStrings = Object.values(prefixes)
88 .map(p => p.prefix) 91 .map(p => p.prefix)
89 92
93 logger(`Built tokens "${tokens.join(', ')}" for prefixes "${prefixeStrings.join(', ')}"`)
94
90 // Search is the querystring minus defined filters 95 // Search is the querystring minus defined filters
91 const searchTokens = tokens.filter(t => { 96 const searchTokens = tokens.filter(t => {
92 return prefixeStrings.every(prefixString => t.startsWith(prefixString) === false) 97 return prefixeStrings.every(prefixString => t.startsWith(prefixString) === false)
@@ -122,8 +127,12 @@ export class RestService {
122 : matchedTokens[0] 127 : matchedTokens[0]
123 } 128 }
124 129
130 const search = searchTokens.join(' ') || undefined
131
132 logger('Built search: ' + search, additionalFilters)
133
125 return { 134 return {
126 search: searchTokens.join(' ') || undefined, 135 search,
127 136
128 ...additionalFilters 137 ...additionalFilters
129 } 138 }
diff --git a/client/src/app/shared/shared-main/video-caption/video-caption.service.ts b/client/src/app/shared/shared-main/video-caption/video-caption.service.ts
index 283c63f98..29d6d0f4c 100644
--- a/client/src/app/shared/shared-main/video-caption/video-caption.service.ts
+++ b/client/src/app/shared/shared-main/video-caption/video-caption.service.ts
@@ -18,7 +18,7 @@ export class VideoCaptionService {
18 ) {} 18 ) {}
19 19
20 listCaptions (videoId: number | string): Observable<ResultList<VideoCaption>> { 20 listCaptions (videoId: number | string): Observable<ResultList<VideoCaption>> {
21 return this.authHttp.get<ResultList<VideoCaption>>(VideoService.BASE_VIDEO_URL + videoId + '/captions') 21 return this.authHttp.get<ResultList<VideoCaption>>(`${VideoService.BASE_VIDEO_URL}/${videoId}/captions`)
22 .pipe( 22 .pipe(
23 switchMap(captionsResult => { 23 switchMap(captionsResult => {
24 return this.serverService.getServerLocale() 24 return this.serverService.getServerLocale()
@@ -41,7 +41,7 @@ export class VideoCaptionService {
41 } 41 }
42 42
43 removeCaption (videoId: number | string, language: string) { 43 removeCaption (videoId: number | string, language: string) {
44 return this.authHttp.delete(VideoService.BASE_VIDEO_URL + videoId + '/captions/' + language) 44 return this.authHttp.delete(`${VideoService.BASE_VIDEO_URL}/${videoId}/captions/${language}`)
45 .pipe( 45 .pipe(
46 map(this.restExtractor.extractDataBool), 46 map(this.restExtractor.extractDataBool),
47 catchError(res => this.restExtractor.handleError(res)) 47 catchError(res => this.restExtractor.handleError(res))
@@ -52,7 +52,7 @@ export class VideoCaptionService {
52 const body = { captionfile } 52 const body = { captionfile }
53 const data = objectToFormData(body) 53 const data = objectToFormData(body)
54 54
55 return this.authHttp.put(VideoService.BASE_VIDEO_URL + videoId + '/captions/' + language, data) 55 return this.authHttp.put(`${VideoService.BASE_VIDEO_URL}/${videoId}/captions/${language}`, data)
56 .pipe( 56 .pipe(
57 map(this.restExtractor.extractDataBool), 57 map(this.restExtractor.extractDataBool),
58 catchError(res => this.restExtractor.handleError(res)) 58 catchError(res => this.restExtractor.handleError(res))
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 819847ac6..b7c563dca 100644
--- a/client/src/app/shared/shared-main/video/video.service.ts
+++ b/client/src/app/shared/shared-main/video/video.service.ts
@@ -5,6 +5,7 @@ import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http'
5import { Injectable } from '@angular/core' 5import { Injectable } from '@angular/core'
6import { ComponentPaginationLight, RestExtractor, RestPagination, RestService, ServerService, UserService } from '@app/core' 6import { ComponentPaginationLight, RestExtractor, RestPagination, RestService, ServerService, UserService } from '@app/core'
7import { objectToFormData } from '@app/helpers' 7import { objectToFormData } from '@app/helpers'
8import { AdvancedInputFilter } from '@app/shared/shared-forms'
8import { 9import {
9 BooleanBothQuery, 10 BooleanBothQuery,
10 FeedFormat, 11 FeedFormat,
@@ -60,18 +61,18 @@ export class VideoService {
60 ) {} 61 ) {}
61 62
62 getVideoViewUrl (uuid: string) { 63 getVideoViewUrl (uuid: string) {
63 return VideoService.BASE_VIDEO_URL + '/' + uuid + '/views' 64 return `${VideoService.BASE_VIDEO_URL}/${uuid}/views`
64 } 65 }
65 66
66 getUserWatchingVideoUrl (uuid: string) { 67 getUserWatchingVideoUrl (uuid: string) {
67 return VideoService.BASE_VIDEO_URL + '/' + uuid + '/watching' 68 return `${VideoService.BASE_VIDEO_URL}/${uuid}/watching`
68 } 69 }
69 70
70 getVideo (options: { videoId: string }): Observable<VideoDetails> { 71 getVideo (options: { videoId: string }): Observable<VideoDetails> {
71 return this.serverService.getServerLocale() 72 return this.serverService.getServerLocale()
72 .pipe( 73 .pipe(
73 switchMap(translations => { 74 switchMap(translations => {
74 return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + '/' + options.videoId) 75 return this.authHttp.get<VideoDetailsServerModel>(`${VideoService.BASE_VIDEO_URL}/${options.videoId}`)
75 .pipe(map(videoHash => ({ videoHash, translations }))) 76 .pipe(map(videoHash => ({ videoHash, translations })))
76 }), 77 }),
77 map(({ videoHash, translations }) => new VideoDetails(videoHash, translations)), 78 map(({ videoHash, translations }) => new VideoDetails(videoHash, translations)),
@@ -111,7 +112,7 @@ export class VideoService {
111 112
112 const data = objectToFormData(body) 113 const data = objectToFormData(body)
113 114
114 return this.authHttp.put(VideoService.BASE_VIDEO_URL + '/' + video.id, data) 115 return this.authHttp.put(`${VideoService.BASE_VIDEO_URL}/${video.id}`, data)
115 .pipe( 116 .pipe(
116 map(this.restExtractor.extractDataBool), 117 map(this.restExtractor.extractDataBool),
117 catchError(err => this.restExtractor.handleError(err)) 118 catchError(err => this.restExtractor.handleError(err))
@@ -119,7 +120,7 @@ export class VideoService {
119 } 120 }
120 121
121 uploadVideo (video: FormData) { 122 uploadVideo (video: FormData) {
122 const req = new HttpRequest('POST', VideoService.BASE_VIDEO_URL + '/' + 'upload', video, { reportProgress: true }) 123 const req = new HttpRequest('POST', `${VideoService.BASE_VIDEO_URL}/upload`, video, { reportProgress: true })
123 124
124 return this.authHttp 125 return this.authHttp
125 .request<{ video: { id: number, uuid: string } }>(req) 126 .request<{ video: { id: number, uuid: string } }>(req)
@@ -204,25 +205,17 @@ export class VideoService {
204 } 205 }
205 206
206 getAdminVideos ( 207 getAdminVideos (
207 parameters: CommonVideoParams & { pagination: RestPagination, search?: string } 208 options: CommonVideoParams & { pagination: RestPagination, search?: string }
208 ): Observable<ResultList<Video>> { 209 ): Observable<ResultList<Video>> {
209 const { pagination, search } = parameters 210 const { pagination, search } = options
210
211 const include = VideoInclude.BLACKLISTED |
212 VideoInclude.BLOCKED_OWNER |
213 VideoInclude.HIDDEN_PRIVACY |
214 VideoInclude.NOT_PUBLISHED_STATE |
215 VideoInclude.FILES
216 211
217 let params = new HttpParams() 212 let params = new HttpParams()
218 params = this.buildCommonVideosParams({ params, include, ...parameters }) 213 params = this.buildCommonVideosParams({ params, ...options })
219 214
220 params = params.set('start', pagination.start.toString()) 215 params = params.set('start', pagination.start.toString())
221 .set('count', pagination.count.toString()) 216 .set('count', pagination.count.toString())
222 217
223 if (search) { 218 params = this.buildAdminParamsFromSearch(search, params)
224 params = this.buildAdminParamsFromSearch(search, params)
225 }
226 219
227 return this.authHttp 220 return this.authHttp
228 .get<ResultList<Video>>(VideoService.BASE_VIDEO_URL, { params }) 221 .get<ResultList<Video>>(VideoService.BASE_VIDEO_URL, { params })
@@ -321,7 +314,7 @@ export class VideoService {
321 314
322 return from(ids) 315 return from(ids)
323 .pipe( 316 .pipe(
324 concatMap(id => this.authHttp.delete(VideoService.BASE_VIDEO_URL + '/' + id)), 317 concatMap(id => this.authHttp.delete(`${VideoService.BASE_VIDEO_URL}/${id}`)),
325 toArray(), 318 toArray(),
326 catchError(err => this.restExtractor.handleError(err)) 319 catchError(err => this.restExtractor.handleError(err))
327 ) 320 )
@@ -413,7 +406,7 @@ export class VideoService {
413 } 406 }
414 407
415 private setVideoRate (id: number, rateType: UserVideoRateType) { 408 private setVideoRate (id: number, rateType: UserVideoRateType) {
416 const url = VideoService.BASE_VIDEO_URL + '/' + id + '/rate' 409 const url = `${VideoService.BASE_VIDEO_URL}/${id}/rate`
417 const body: UserVideoRateUpdate = { 410 const body: UserVideoRateUpdate = {
418 rating: rateType 411 rating: rateType
419 } 412 }
@@ -460,14 +453,60 @@ export class VideoService {
460 return newParams 453 return newParams
461 } 454 }
462 455
456 buildAdminInputFilter (): AdvancedInputFilter[] {
457 return [
458 {
459 title: $localize`Videos scope`,
460 children: [
461 {
462 queryParams: { search: 'isLocal:false' },
463 label: $localize`Remote videos`
464 },
465 {
466 queryParams: { search: 'isLocal:true' },
467 label: $localize`Local videos`
468 }
469 ]
470 },
471
472 {
473 title: $localize`Include/Exclude`,
474 children: [
475 {
476 queryParams: { search: 'excludeMuted' },
477 label: $localize`Exclude muted accounts`
478 }
479 ]
480 }
481 ]
482 }
483
463 private buildAdminParamsFromSearch (search: string, params: HttpParams) { 484 private buildAdminParamsFromSearch (search: string, params: HttpParams) {
485 let include = VideoInclude.BLACKLISTED |
486 VideoInclude.BLOCKED_OWNER |
487 VideoInclude.HIDDEN_PRIVACY |
488 VideoInclude.NOT_PUBLISHED_STATE |
489 VideoInclude.FILES
490
491 if (!search) return this.restService.addObjectParams(params, { include })
492
464 const filters = this.restService.parseQueryStringFilter(search, { 493 const filters = this.restService.parseQueryStringFilter(search, {
465 isLocal: { 494 isLocal: {
466 prefix: 'isLocal:', 495 prefix: 'isLocal:',
467 isBoolean: true 496 isBoolean: true
497 },
498 excludeMuted: {
499 prefix: 'excludeMuted',
500 handler: () => true
468 } 501 }
469 }) 502 })
470 503
471 return this.restService.addObjectParams(params, filters) 504 if (filters.excludeMuted) {
505 include &= ~VideoInclude.BLOCKED_OWNER
506
507 filters.excludeMuted = undefined
508 }
509
510 return this.restService.addObjectParams(params, { ...filters, include })
472 } 511 }
473} 512}