From 231ff4af3bdb864d6bc66e487b12275e5f1fb44f Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 2 Nov 2021 11:50:03 +0100 Subject: Add ability to exclude muted accounts --- .../+admin/overview/videos/video-list.component.ts | 20 ++---- .../video-add-components/video-upload.component.ts | 2 +- .../+videos/+video-watch/video-watch.component.ts | 2 +- client/src/app/core/rest/rest.service.ts | 13 +++- .../video-caption/video-caption.service.ts | 6 +- .../app/shared/shared-main/video/video.service.ts | 79 ++++++++++++++++------ 6 files changed, 79 insertions(+), 43 deletions(-) (limited to 'client/src') 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 { selectedVideos: Video[] = [] - inputFilters: AdvancedInputFilter[] = [ - { - title: $localize`Advanced filters`, - children: [ - { - queryParams: { search: 'isLocal:false' }, - label: $localize`Remote videos` - }, - { - queryParams: { search: 'isLocal:true' }, - label: $localize`Local videos` - } - ] - } - ] + inputFilters: AdvancedInputFilter[] videoActionsOptions: VideoActionsDisplayType = { playlist: false, @@ -52,7 +38,7 @@ export class VideoListComponent extends RestTable implements OnInit { liveInfo: false } - loading = false + loading = true constructor ( protected route: ActivatedRoute, @@ -72,6 +58,8 @@ export class VideoListComponent extends RestTable implements OnInit { ngOnInit () { this.initialize() + this.inputFilters = this.videoService.buildAdminInputFilter() + this.bulkVideoActions = [ [ { 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 schedulePublicationPossible = false // So that it can be accessed in the template - protected readonly BASE_VIDEO_UPLOAD_URL = VideoService.BASE_VIDEO_URL + 'upload-resumable' + protected readonly BASE_VIDEO_UPLOAD_URL = VideoService.BASE_VIDEO_URL + '/upload-resumable' private uploadxOptions: UploadxOptions 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 { private async handleRequestError (err: any) { const errorBody = err.body as PeerTubeProblemDocument - if (errorBody.code === ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS && errorBody.originUrl) { + if (errorBody?.code === ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS && errorBody.originUrl) { const originUrl = errorBody.originUrl + (window.location.search ?? '') 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 @@ +import * as debug from 'debug' import { SortMeta } from 'primeng/api' import { HttpParams } from '@angular/common/http' import { Injectable } from '@angular/core' import { ComponentPaginationLight } from './component-pagination.model' import { RestPagination } from './rest-pagination' +const logger = debug('peertube:rest') + interface QueryStringFilterPrefixes { [key: string]: { prefix: string - handler?: (v: string) => string | number + handler?: (v: string) => string | number | boolean multiple?: boolean isBoolean?: boolean } @@ -87,6 +90,8 @@ export class RestService { const prefixeStrings = Object.values(prefixes) .map(p => p.prefix) + logger(`Built tokens "${tokens.join(', ')}" for prefixes "${prefixeStrings.join(', ')}"`) + // Search is the querystring minus defined filters const searchTokens = tokens.filter(t => { return prefixeStrings.every(prefixString => t.startsWith(prefixString) === false) @@ -122,8 +127,12 @@ export class RestService { : matchedTokens[0] } + const search = searchTokens.join(' ') || undefined + + logger('Built search: ' + search, additionalFilters) + return { - search: searchTokens.join(' ') || undefined, + search, ...additionalFilters } 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 { ) {} listCaptions (videoId: number | string): Observable> { - return this.authHttp.get>(VideoService.BASE_VIDEO_URL + videoId + '/captions') + return this.authHttp.get>(`${VideoService.BASE_VIDEO_URL}/${videoId}/captions`) .pipe( switchMap(captionsResult => { return this.serverService.getServerLocale() @@ -41,7 +41,7 @@ export class VideoCaptionService { } removeCaption (videoId: number | string, language: string) { - return this.authHttp.delete(VideoService.BASE_VIDEO_URL + videoId + '/captions/' + language) + return this.authHttp.delete(`${VideoService.BASE_VIDEO_URL}/${videoId}/captions/${language}`) .pipe( map(this.restExtractor.extractDataBool), catchError(res => this.restExtractor.handleError(res)) @@ -52,7 +52,7 @@ export class VideoCaptionService { const body = { captionfile } const data = objectToFormData(body) - return this.authHttp.put(VideoService.BASE_VIDEO_URL + videoId + '/captions/' + language, data) + return this.authHttp.put(`${VideoService.BASE_VIDEO_URL}/${videoId}/captions/${language}`, data) .pipe( map(this.restExtractor.extractDataBool), 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' import { Injectable } from '@angular/core' import { ComponentPaginationLight, RestExtractor, RestPagination, RestService, ServerService, UserService } from '@app/core' import { objectToFormData } from '@app/helpers' +import { AdvancedInputFilter } from '@app/shared/shared-forms' import { BooleanBothQuery, FeedFormat, @@ -60,18 +61,18 @@ export class VideoService { ) {} getVideoViewUrl (uuid: string) { - return VideoService.BASE_VIDEO_URL + '/' + uuid + '/views' + return `${VideoService.BASE_VIDEO_URL}/${uuid}/views` } getUserWatchingVideoUrl (uuid: string) { - return VideoService.BASE_VIDEO_URL + '/' + uuid + '/watching' + return `${VideoService.BASE_VIDEO_URL}/${uuid}/watching` } getVideo (options: { videoId: string }): Observable { return this.serverService.getServerLocale() .pipe( switchMap(translations => { - return this.authHttp.get(VideoService.BASE_VIDEO_URL + '/' + options.videoId) + return this.authHttp.get(`${VideoService.BASE_VIDEO_URL}/${options.videoId}`) .pipe(map(videoHash => ({ videoHash, translations }))) }), map(({ videoHash, translations }) => new VideoDetails(videoHash, translations)), @@ -111,7 +112,7 @@ export class VideoService { const data = objectToFormData(body) - return this.authHttp.put(VideoService.BASE_VIDEO_URL + '/' + video.id, data) + return this.authHttp.put(`${VideoService.BASE_VIDEO_URL}/${video.id}`, data) .pipe( map(this.restExtractor.extractDataBool), catchError(err => this.restExtractor.handleError(err)) @@ -119,7 +120,7 @@ export class VideoService { } uploadVideo (video: FormData) { - const req = new HttpRequest('POST', VideoService.BASE_VIDEO_URL + '/' + 'upload', video, { reportProgress: true }) + const req = new HttpRequest('POST', `${VideoService.BASE_VIDEO_URL}/upload`, video, { reportProgress: true }) return this.authHttp .request<{ video: { id: number, uuid: string } }>(req) @@ -204,25 +205,17 @@ export class VideoService { } getAdminVideos ( - parameters: CommonVideoParams & { pagination: RestPagination, search?: string } + options: CommonVideoParams & { pagination: RestPagination, search?: string } ): Observable> { - const { pagination, search } = parameters - - const include = VideoInclude.BLACKLISTED | - VideoInclude.BLOCKED_OWNER | - VideoInclude.HIDDEN_PRIVACY | - VideoInclude.NOT_PUBLISHED_STATE | - VideoInclude.FILES + const { pagination, search } = options let params = new HttpParams() - params = this.buildCommonVideosParams({ params, include, ...parameters }) + params = this.buildCommonVideosParams({ params, ...options }) params = params.set('start', pagination.start.toString()) .set('count', pagination.count.toString()) - if (search) { - params = this.buildAdminParamsFromSearch(search, params) - } + params = this.buildAdminParamsFromSearch(search, params) return this.authHttp .get>(VideoService.BASE_VIDEO_URL, { params }) @@ -321,7 +314,7 @@ export class VideoService { return from(ids) .pipe( - concatMap(id => this.authHttp.delete(VideoService.BASE_VIDEO_URL + '/' + id)), + concatMap(id => this.authHttp.delete(`${VideoService.BASE_VIDEO_URL}/${id}`)), toArray(), catchError(err => this.restExtractor.handleError(err)) ) @@ -413,7 +406,7 @@ export class VideoService { } private setVideoRate (id: number, rateType: UserVideoRateType) { - const url = VideoService.BASE_VIDEO_URL + '/' + id + '/rate' + const url = `${VideoService.BASE_VIDEO_URL}/${id}/rate` const body: UserVideoRateUpdate = { rating: rateType } @@ -460,14 +453,60 @@ export class VideoService { return newParams } + buildAdminInputFilter (): AdvancedInputFilter[] { + return [ + { + title: $localize`Videos scope`, + children: [ + { + queryParams: { search: 'isLocal:false' }, + label: $localize`Remote videos` + }, + { + queryParams: { search: 'isLocal:true' }, + label: $localize`Local videos` + } + ] + }, + + { + title: $localize`Include/Exclude`, + children: [ + { + queryParams: { search: 'excludeMuted' }, + label: $localize`Exclude muted accounts` + } + ] + } + ] + } + private buildAdminParamsFromSearch (search: string, params: HttpParams) { + let include = VideoInclude.BLACKLISTED | + VideoInclude.BLOCKED_OWNER | + VideoInclude.HIDDEN_PRIVACY | + VideoInclude.NOT_PUBLISHED_STATE | + VideoInclude.FILES + + if (!search) return this.restService.addObjectParams(params, { include }) + const filters = this.restService.parseQueryStringFilter(search, { isLocal: { prefix: 'isLocal:', isBoolean: true + }, + excludeMuted: { + prefix: 'excludeMuted', + handler: () => true } }) - return this.restService.addObjectParams(params, filters) + if (filters.excludeMuted) { + include &= ~VideoInclude.BLOCKED_OWNER + + filters.excludeMuted = undefined + } + + return this.restService.addObjectParams(params, { ...filters, include }) } } -- cgit v1.2.3