From b764380ac23f4e9d4677d08acdc3474c2931a16d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 10 Jan 2020 10:11:28 +0100 Subject: Add ability to list redundancies --- client/src/app/shared/video/redundancy.service.ts | 73 ++++++++++++++++++++++ .../video/video-actions-dropdown.component.ts | 28 ++++++++- .../app/shared/video/video-miniature.component.ts | 3 +- client/src/app/shared/video/video.model.ts | 4 ++ 4 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 client/src/app/shared/video/redundancy.service.ts (limited to 'client/src/app/shared/video') diff --git a/client/src/app/shared/video/redundancy.service.ts b/client/src/app/shared/video/redundancy.service.ts new file mode 100644 index 000000000..fb918d73b --- /dev/null +++ b/client/src/app/shared/video/redundancy.service.ts @@ -0,0 +1,73 @@ +import { catchError, map, toArray } from 'rxjs/operators' +import { HttpClient, HttpParams } from '@angular/common/http' +import { Injectable } from '@angular/core' +import { RestExtractor, RestPagination, RestService } from '@app/shared/rest' +import { SortMeta } from 'primeng/api' +import { ResultList, Video, VideoRedundanciesTarget, VideoRedundancy } from '@shared/models' +import { concat, Observable } from 'rxjs' +import { environment } from '../../../environments/environment' + +@Injectable() +export class RedundancyService { + static BASE_REDUNDANCY_URL = environment.apiUrl + '/api/v1/server/redundancy' + + constructor ( + private authHttp: HttpClient, + private restService: RestService, + private restExtractor: RestExtractor + ) { } + + updateRedundancy (host: string, redundancyAllowed: boolean) { + const url = RedundancyService.BASE_REDUNDANCY_URL + '/' + host + + const body = { redundancyAllowed } + + return this.authHttp.put(url, body) + .pipe( + map(this.restExtractor.extractDataBool), + catchError(err => this.restExtractor.handleError(err)) + ) + } + + listVideoRedundancies (options: { + pagination: RestPagination, + sort: SortMeta, + target?: VideoRedundanciesTarget + }): Observable> { + const { pagination, sort, target } = options + + let params = new HttpParams() + params = this.restService.addRestGetParams(params, pagination, sort) + + if (target) params = params.append('target', target) + + return this.authHttp.get>(RedundancyService.BASE_REDUNDANCY_URL + '/videos', { params }) + .pipe( + catchError(res => this.restExtractor.handleError(res)) + ) + } + + addVideoRedundancy (video: Video) { + return this.authHttp.post(RedundancyService.BASE_REDUNDANCY_URL + '/videos', { videoId: video.id }) + .pipe( + catchError(res => this.restExtractor.handleError(res)) + ) + } + + removeVideoRedundancies (redundancy: VideoRedundancy) { + const observables = redundancy.redundancies.streamingPlaylists.map(r => r.id) + .concat(redundancy.redundancies.files.map(r => r.id)) + .map(id => this.removeRedundancy(id)) + + return concat(...observables) + .pipe(toArray()) + } + + private removeRedundancy (redundancyId: number) { + return this.authHttp.delete(RedundancyService.BASE_REDUNDANCY_URL + '/videos/' + redundancyId) + .pipe( + map(this.restExtractor.extractDataBool), + catchError(res => this.restExtractor.handleError(res)) + ) + } +} diff --git a/client/src/app/shared/video/video-actions-dropdown.component.ts b/client/src/app/shared/video/video-actions-dropdown.component.ts index afdeab18d..390d74c52 100644 --- a/client/src/app/shared/video/video-actions-dropdown.component.ts +++ b/client/src/app/shared/video/video-actions-dropdown.component.ts @@ -14,6 +14,7 @@ import { VideoBlacklistComponent } from '@app/shared/video/modals/video-blacklis import { VideoBlacklistService } from '@app/shared/video-blacklist' import { ScreenService } from '@app/shared/misc/screen.service' import { VideoCaption } from '@shared/models' +import { RedundancyService } from '@app/shared/video/redundancy.service' export type VideoActionsDisplayType = { playlist?: boolean @@ -22,6 +23,7 @@ export type VideoActionsDisplayType = { blacklist?: boolean delete?: boolean report?: boolean + duplicate?: boolean } @Component({ @@ -46,7 +48,8 @@ export class VideoActionsDropdownComponent implements OnChanges { update: true, blacklist: true, delete: true, - report: true + report: true, + duplicate: true } @Input() placement = 'left' @@ -74,6 +77,7 @@ export class VideoActionsDropdownComponent implements OnChanges { private screenService: ScreenService, private videoService: VideoService, private blocklistService: BlocklistService, + private redundancyService: RedundancyService, private i18n: I18n ) { } @@ -144,6 +148,10 @@ export class VideoActionsDropdownComponent implements OnChanges { return this.video && this.video instanceof VideoDetails && this.video.downloadEnabled } + canVideoBeDuplicated () { + return this.video.canBeDuplicatedBy(this.user) + } + /* Action handlers */ async unblacklistVideo () { @@ -186,6 +194,18 @@ export class VideoActionsDropdownComponent implements OnChanges { ) } + duplicateVideo () { + this.redundancyService.addVideoRedundancy(this.video) + .subscribe( + () => { + const message = this.i18n('This video will be duplicated by your instance.') + this.notifier.success(message) + }, + + err => this.notifier.error(err.message) + ) + } + onVideoBlacklisted () { this.videoBlacklisted.emit() } @@ -233,6 +253,12 @@ export class VideoActionsDropdownComponent implements OnChanges { iconName: 'undo', isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoUnblacklistable() }, + { + label: this.i18n('Duplicate (redundancy)'), + handler: () => this.duplicateVideo(), + isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.duplicate && this.canVideoBeDuplicated(), + iconName: 'cloud-download' + }, { label: this.i18n('Delete'), handler: () => this.removeVideo(), diff --git a/client/src/app/shared/video/video-miniature.component.ts b/client/src/app/shared/video/video-miniature.component.ts index 598a7a983..1dfb3eec7 100644 --- a/client/src/app/shared/video/video-miniature.component.ts +++ b/client/src/app/shared/video/video-miniature.component.ts @@ -64,7 +64,8 @@ export class VideoMiniatureComponent implements OnInit { update: true, blacklist: true, delete: true, - report: true + report: true, + duplicate: false } showActions = false serverConfig: ServerConfig diff --git a/client/src/app/shared/video/video.model.ts b/client/src/app/shared/video/video.model.ts index fb98d5382..9eeaf41b0 100644 --- a/client/src/app/shared/video/video.model.ts +++ b/client/src/app/shared/video/video.model.ts @@ -152,4 +152,8 @@ export class Video implements VideoServerModel { isUpdatableBy (user: AuthUser) { return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.UPDATE_ANY_VIDEO)) } + + canBeDuplicatedBy (user: AuthUser) { + return user && this.isLocal === false && user.hasRight(UserRight.MANAGE_VIDEOS_REDUNDANCIES) + } } -- cgit v1.2.3