diff options
author | Chocobozzz <me@florianbigard.com> | 2021-11-02 11:50:03 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-11-02 11:50:03 +0100 |
commit | 231ff4af3bdb864d6bc66e487b12275e5f1fb44f (patch) | |
tree | b8537a67a26d86dcf68eb871ada8e17e286517e2 | |
parent | 61f85385bbd281e34573e250b2625860fd6a1408 (diff) | |
download | PeerTube-231ff4af3bdb864d6bc66e487b12275e5f1fb44f.tar.gz PeerTube-231ff4af3bdb864d6bc66e487b12275e5f1fb44f.tar.zst PeerTube-231ff4af3bdb864d6bc66e487b12275e5f1fb44f.zip |
Add ability to exclude muted accounts
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 @@ | |||
1 | import * as debug from 'debug' | ||
1 | import { SortMeta } from 'primeng/api' | 2 | import { SortMeta } from 'primeng/api' |
2 | import { HttpParams } from '@angular/common/http' | 3 | import { HttpParams } from '@angular/common/http' |
3 | import { Injectable } from '@angular/core' | 4 | import { Injectable } from '@angular/core' |
4 | import { ComponentPaginationLight } from './component-pagination.model' | 5 | import { ComponentPaginationLight } from './component-pagination.model' |
5 | import { RestPagination } from './rest-pagination' | 6 | import { RestPagination } from './rest-pagination' |
6 | 7 | ||
8 | const logger = debug('peertube:rest') | ||
9 | |||
7 | interface QueryStringFilterPrefixes { | 10 | interface 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' | |||
5 | import { Injectable } from '@angular/core' | 5 | import { Injectable } from '@angular/core' |
6 | import { ComponentPaginationLight, RestExtractor, RestPagination, RestService, ServerService, UserService } from '@app/core' | 6 | import { ComponentPaginationLight, RestExtractor, RestPagination, RestService, ServerService, UserService } from '@app/core' |
7 | import { objectToFormData } from '@app/helpers' | 7 | import { objectToFormData } from '@app/helpers' |
8 | import { AdvancedInputFilter } from '@app/shared/shared-forms' | ||
8 | import { | 9 | import { |
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 | } |