From 1942f11d5ee6926ad93dc1b79fae18325ba5de18 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 23 Jun 2020 14:49:20 +0200 Subject: Lazy load all routes --- .../shared/i18n-primeng-calendar.service.ts | 94 ------- .../shared/video-caption-add-modal.component.html | 47 ---- .../shared/video-caption-add-modal.component.scss | 20 -- .../shared/video-caption-add-modal.component.ts | 85 ------ .../+video-edit/shared/video-edit.component.html | 280 ------------------- .../+video-edit/shared/video-edit.component.scss | 197 ------------- .../+video-edit/shared/video-edit.component.ts | 274 ------------------ .../videos/+video-edit/shared/video-edit.module.ts | 38 --- .../video-add-components/drag-drop.directive.ts | 30 -- .../video-import-torrent.component.html | 76 ----- .../video-import-torrent.component.scss | 18 -- .../video-import-torrent.component.ts | 147 ---------- .../video-import-url.component.html | 72 ----- .../video-import-url.component.ts | 178 ------------ .../video-add-components/video-send.scss | 46 ---- .../+video-edit/video-add-components/video-send.ts | 71 ----- .../video-upload.component.html | 90 ------ .../video-upload.component.scss | 49 ---- .../video-add-components/video-upload.component.ts | 306 --------------------- .../videos/+video-edit/video-add-routing.module.ts | 20 -- .../videos/+video-edit/video-add.component.html | 46 ---- .../videos/+video-edit/video-add.component.scss | 89 ------ .../app/videos/+video-edit/video-add.component.ts | 77 ------ .../src/app/videos/+video-edit/video-add.module.ts | 32 --- .../+video-edit/video-update-routing.module.ts | 24 -- .../videos/+video-edit/video-update.component.html | 22 -- .../videos/+video-edit/video-update.component.ts | 155 ----------- .../app/videos/+video-edit/video-update.module.ts | 26 -- .../videos/+video-edit/video-update.resolver.ts | 44 --- 29 files changed, 2653 deletions(-) delete mode 100644 client/src/app/videos/+video-edit/shared/i18n-primeng-calendar.service.ts delete mode 100644 client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.html delete mode 100644 client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.scss delete mode 100644 client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.ts delete mode 100644 client/src/app/videos/+video-edit/shared/video-edit.component.html delete mode 100644 client/src/app/videos/+video-edit/shared/video-edit.component.scss delete mode 100644 client/src/app/videos/+video-edit/shared/video-edit.component.ts delete mode 100644 client/src/app/videos/+video-edit/shared/video-edit.module.ts delete mode 100644 client/src/app/videos/+video-edit/video-add-components/drag-drop.directive.ts delete mode 100644 client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.html delete mode 100644 client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.scss delete mode 100644 client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts delete mode 100644 client/src/app/videos/+video-edit/video-add-components/video-import-url.component.html delete mode 100644 client/src/app/videos/+video-edit/video-add-components/video-import-url.component.ts delete mode 100644 client/src/app/videos/+video-edit/video-add-components/video-send.scss delete mode 100644 client/src/app/videos/+video-edit/video-add-components/video-send.ts delete mode 100644 client/src/app/videos/+video-edit/video-add-components/video-upload.component.html delete mode 100644 client/src/app/videos/+video-edit/video-add-components/video-upload.component.scss delete mode 100644 client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts delete mode 100644 client/src/app/videos/+video-edit/video-add-routing.module.ts delete mode 100644 client/src/app/videos/+video-edit/video-add.component.html delete mode 100644 client/src/app/videos/+video-edit/video-add.component.scss delete mode 100644 client/src/app/videos/+video-edit/video-add.component.ts delete mode 100644 client/src/app/videos/+video-edit/video-add.module.ts delete mode 100644 client/src/app/videos/+video-edit/video-update-routing.module.ts delete mode 100644 client/src/app/videos/+video-edit/video-update.component.html delete mode 100644 client/src/app/videos/+video-edit/video-update.component.ts delete mode 100644 client/src/app/videos/+video-edit/video-update.module.ts delete mode 100644 client/src/app/videos/+video-edit/video-update.resolver.ts (limited to 'client/src/app/videos/+video-edit') diff --git a/client/src/app/videos/+video-edit/shared/i18n-primeng-calendar.service.ts b/client/src/app/videos/+video-edit/shared/i18n-primeng-calendar.service.ts deleted file mode 100644 index b05852ff8..000000000 --- a/client/src/app/videos/+video-edit/shared/i18n-primeng-calendar.service.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { I18n } from '@ngx-translate/i18n-polyfill' -import { Injectable } from '@angular/core' - -@Injectable() -export class I18nPrimengCalendarService { - private readonly calendarLocale: any = {} - - constructor (private i18n: I18n) { - this.calendarLocale = { - firstDayOfWeek: 0, - dayNames: [ - this.i18n('Sunday'), - this.i18n('Monday'), - this.i18n('Tuesday'), - this.i18n('Wednesday'), - this.i18n('Thursday'), - this.i18n('Friday'), - this.i18n('Saturday') - ], - - dayNamesShort: [ - this.i18n({ value: 'Sun', description: 'Day name short' }), - this.i18n({ value: 'Mon', description: 'Day name short' }), - this.i18n({ value: 'Tue', description: 'Day name short' }), - this.i18n({ value: 'Wed', description: 'Day name short' }), - this.i18n({ value: 'Thu', description: 'Day name short' }), - this.i18n({ value: 'Fri', description: 'Day name short' }), - this.i18n({ value: 'Sat', description: 'Day name short' }) - ], - - dayNamesMin: [ - this.i18n({ value: 'Su', description: 'Day name min' }), - this.i18n({ value: 'Mo', description: 'Day name min' }), - this.i18n({ value: 'Tu', description: 'Day name min' }), - this.i18n({ value: 'We', description: 'Day name min' }), - this.i18n({ value: 'Th', description: 'Day name min' }), - this.i18n({ value: 'Fr', description: 'Day name min' }), - this.i18n({ value: 'Sa', description: 'Day name min' }) - ], - - monthNames: [ - this.i18n('January'), - this.i18n('February'), - this.i18n('March'), - this.i18n('April'), - this.i18n('May'), - this.i18n('June'), - this.i18n('July'), - this.i18n('August'), - this.i18n('September'), - this.i18n('October'), - this.i18n('November'), - this.i18n('December') - ], - - monthNamesShort: [ - this.i18n({ value: 'Jan', description: 'Month name short' }), - this.i18n({ value: 'Feb', description: 'Month name short' }), - this.i18n({ value: 'Mar', description: 'Month name short' }), - this.i18n({ value: 'Apr', description: 'Month name short' }), - this.i18n({ value: 'May', description: 'Month name short' }), - this.i18n({ value: 'Jun', description: 'Month name short' }), - this.i18n({ value: 'Jul', description: 'Month name short' }), - this.i18n({ value: 'Aug', description: 'Month name short' }), - this.i18n({ value: 'Sep', description: 'Month name short' }), - this.i18n({ value: 'Oct', description: 'Month name short' }), - this.i18n({ value: 'Nov', description: 'Month name short' }), - this.i18n({ value: 'Dec', description: 'Month name short' }) - ], - - today: this.i18n('Today'), - - clear: this.i18n('Clear') - } - } - - getCalendarLocale () { - return this.calendarLocale - } - - getTimezone () { - const gmt = new Date().toString().match(/([A-Z]+[\+-][0-9]+)/)[1] - const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone - - return `${timezone} - ${gmt}` - } - - getDateFormat () { - return this.i18n({ - value: 'yy-mm-dd ', - description: 'Date format in this locale.' - }) - } -} diff --git a/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.html b/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.html deleted file mode 100644 index 6a9e31b5a..000000000 --- a/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - diff --git a/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.scss b/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.scss deleted file mode 100644 index b257a16a9..000000000 --- a/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.scss +++ /dev/null @@ -1,20 +0,0 @@ -@import '_variables'; -@import '_mixins'; - -.peertube-select-container { - @include peertube-select-container(auto); -} - -.caption-file { - margin-top: 20px; - width: max-content; - - ::ng-deep .root { - width: max-content; - } -} - -.warning-replace-caption { - color: red; - margin-top: 10px; -} \ No newline at end of file diff --git a/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.ts b/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.ts deleted file mode 100644 index a90d04ce8..000000000 --- a/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' -import { ServerService } from '@app/core' -import { FormReactive, FormValidatorService, VideoCaptionsValidatorsService } from '@app/shared/shared-forms' -import { VideoCaptionEdit } from '@app/shared/shared-main' -import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' -import { ServerConfig, VideoConstant } from '@shared/models' - -@Component({ - selector: 'my-video-caption-add-modal', - styleUrls: [ './video-caption-add-modal.component.scss' ], - templateUrl: './video-caption-add-modal.component.html' -}) - -export class VideoCaptionAddModalComponent extends FormReactive implements OnInit { - @Input() existingCaptions: string[] - @Input() serverConfig: ServerConfig - - @Output() captionAdded = new EventEmitter() - - @ViewChild('modal', { static: true }) modal: ElementRef - - videoCaptionLanguages: VideoConstant[] = [] - - private openedModal: NgbModalRef - private closingModal = false - - constructor ( - protected formValidatorService: FormValidatorService, - private modalService: NgbModal, - private serverService: ServerService, - private videoCaptionsValidatorsService: VideoCaptionsValidatorsService - ) { - super() - } - - get videoCaptionExtensions () { - return this.serverConfig.videoCaption.file.extensions - } - - get videoCaptionMaxSize () { - return this.serverConfig.videoCaption.file.size.max - } - - ngOnInit () { - this.serverService.getVideoLanguages() - .subscribe(languages => this.videoCaptionLanguages = languages) - - this.buildForm({ - language: this.videoCaptionsValidatorsService.VIDEO_CAPTION_LANGUAGE, - captionfile: this.videoCaptionsValidatorsService.VIDEO_CAPTION_FILE - }) - } - - show () { - this.closingModal = false - - this.openedModal = this.modalService.open(this.modal, { centered: true, keyboard: false }) - } - - hide () { - this.closingModal = true - this.openedModal.close() - this.form.reset() - } - - isReplacingExistingCaption () { - if (this.closingModal === true) return false - - const languageId = this.form.value[ 'language' ] - - return languageId && this.existingCaptions.indexOf(languageId) !== -1 - } - - async addCaption () { - const languageId = this.form.value[ 'language' ] - const languageObject = this.videoCaptionLanguages.find(l => l.id === languageId) - - this.captionAdded.emit({ - language: languageObject, - captionfile: this.form.value[ 'captionfile' ] - }) - - this.hide() - } -} diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.html b/client/src/app/videos/+video-edit/shared/video-edit.component.html deleted file mode 100644 index c11a60dce..000000000 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.html +++ /dev/null @@ -1,280 +0,0 @@ -
- - -
-
- - diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.scss b/client/src/app/videos/+video-edit/shared/video-edit.component.scss deleted file mode 100644 index 69b907288..000000000 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.scss +++ /dev/null @@ -1,197 +0,0 @@ -// Bootstrap grid utilities require functions, variables and mixins -@import 'node_modules/bootstrap/scss/functions'; -@import 'node_modules/bootstrap/scss/variables'; -@import 'node_modules/bootstrap/scss/mixins'; -@import 'node_modules/bootstrap/scss/grid'; - -@import 'variables'; -@import 'mixins'; - -label { - font-weight: $font-regular; - font-size: 100%; -} - -.peertube-select-container { - @include peertube-select-container(auto); -} - -.title-page a { - color: pvar(--mainForegroundColor); - - &:hover { - text-decoration: none; - opacity: .8; - } -} - -my-peertube-checkbox { - display: block; - margin-bottom: 1rem; -} - -.nav-tabs { - margin-bottom: 15px; -} - -.video-edit { - height: 100%; - min-height: 300px; - - .form-group { - margin-bottom: 25px; - } - - input { - @include peertube-input-text(100%); - display: block; - } - - .label-tags + span { - font-size: 15px; - } - - .advanced-settings .form-group { - margin-bottom: 20px; - } -} - -.captions { - - .captions-header { - text-align: right; - margin-bottom: 1rem; - - .create-caption { - @include create-button; - } - } - - .caption-entry { - display: flex; - height: 40px; - align-items: center; - - a.caption-entry-label { - @include disable-default-a-behaviour; - - flex-grow: 1; - color: #000; - - &:hover { - opacity: 0.8; - } - } - - .caption-entry-label { - font-size: 15px; - font-weight: bold; - - margin-right: 20px; - width: 150px; - } - - .caption-entry-state { - width: 200px; - - &.caption-entry-state-create { - color: #39CC0B; - } - - &.caption-entry-state-delete { - color: #FF0000; - } - } - - .caption-entry-delete { - @include peertube-button; - @include grey-button; - } - } - - .no-caption { - text-align: center; - font-size: 15px; - } -} - -.submit-container { - text-align: right; - - .message-submit { - display: inline-block; - margin-right: 25px; - - color: pvar(--greyForegroundColor); - font-size: 15px; - } - - .submit-button { - @include peertube-button; - @include orange-button; - @include button-with-icon(20px, 1px); - - display: inline-block; - - input { - cursor: inherit; - background-color: inherit; - border: none; - padding: 0; - outline: 0; - color: inherit; - font-weight: $font-semibold; - } - } -} - -p-calendar { - display: block; - - ::ng-deep { - input, - .ui-calendar { - width: 100%; - } - - input { - @include peertube-input-text(100%); - color: #000; - } - } -} - -@include ng2-tags; - -// columns for the video -.col-video-edit { - @include make-col-ready(); - - @include media-breakpoint-up(md) { - @include make-col(7); - - & + .col-video-edit { - @include make-col(5); - } - } - - @include media-breakpoint-up(xl) { - @include make-col(8); - - & + .col-video-edit { - @include make-col(4); - } - } -} - -:host-context(.expanded) { - .col-video-edit { - @include media-breakpoint-up(md) { - @include make-col(8); - - & + .col-video-edit { - @include make-col(4); - } - } - } -} diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.ts b/client/src/app/videos/+video-edit/shared/video-edit.component.ts deleted file mode 100644 index 239e453ad..000000000 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.ts +++ /dev/null @@ -1,274 +0,0 @@ -import { map } from 'rxjs/operators' -import { Component, Input, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core' -import { FormArray, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms' -import { ServerService } from '@app/core' -import { removeElementFromArray } from '@app/helpers' -import { FormReactiveValidationMessages, FormValidatorService, VideoValidatorsService } from '@app/shared/shared-forms' -import { VideoCaptionEdit, VideoEdit, VideoService } from '@app/shared/shared-main' -import { ServerConfig, VideoConstant, VideoPrivacy } from '@shared/models' -import { I18nPrimengCalendarService } from './i18n-primeng-calendar.service' -import { VideoCaptionAddModalComponent } from './video-caption-add-modal.component' - -@Component({ - selector: 'my-video-edit', - styleUrls: [ './video-edit.component.scss' ], - templateUrl: './video-edit.component.html' -}) -export class VideoEditComponent implements OnInit, OnDestroy { - @Input() form: FormGroup - @Input() formErrors: { [ id: string ]: string } = {} - @Input() validationMessages: FormReactiveValidationMessages = {} - @Input() userVideoChannels: { id: number, label: string, support: string }[] = [] - @Input() schedulePublicationPossible = true - @Input() videoCaptions: (VideoCaptionEdit & { captionPath?: string })[] = [] - @Input() waitTranscodingEnabled = true - - @ViewChild('videoCaptionAddModal', { static: true }) videoCaptionAddModal: VideoCaptionAddModalComponent - - // So that it can be accessed in the template - readonly SPECIAL_SCHEDULED_PRIVACY = VideoEdit.SPECIAL_SCHEDULED_PRIVACY - - videoPrivacies: VideoConstant[] = [] - videoCategories: VideoConstant[] = [] - videoLicences: VideoConstant[] = [] - videoLanguages: VideoConstant[] = [] - - tagValidators: ValidatorFn[] - tagValidatorsMessages: { [ name: string ]: string } - - schedulePublicationEnabled = false - - calendarLocale: any = {} - minScheduledDate = new Date() - myYearRange = '1880:' + (new Date()).getFullYear() - - calendarTimezone: string - calendarDateFormat: string - - serverConfig: ServerConfig - - private schedulerInterval: any - private firstPatchDone = false - private initialVideoCaptions: string[] = [] - - constructor ( - private formValidatorService: FormValidatorService, - private videoValidatorsService: VideoValidatorsService, - private videoService: VideoService, - private serverService: ServerService, - private i18nPrimengCalendarService: I18nPrimengCalendarService, - private ngZone: NgZone - ) { - this.tagValidators = this.videoValidatorsService.VIDEO_TAGS.VALIDATORS - this.tagValidatorsMessages = this.videoValidatorsService.VIDEO_TAGS.MESSAGES - - this.calendarLocale = this.i18nPrimengCalendarService.getCalendarLocale() - this.calendarTimezone = this.i18nPrimengCalendarService.getTimezone() - this.calendarDateFormat = this.i18nPrimengCalendarService.getDateFormat() - } - - get existingCaptions () { - return this.videoCaptions - .filter(c => c.action !== 'REMOVE') - .map(c => c.language.id) - } - - updateForm () { - const defaultValues: any = { - nsfw: 'false', - commentsEnabled: 'true', - downloadEnabled: 'true', - waitTranscoding: 'true', - tags: [] - } - const obj: any = { - name: this.videoValidatorsService.VIDEO_NAME, - privacy: this.videoValidatorsService.VIDEO_PRIVACY, - channelId: this.videoValidatorsService.VIDEO_CHANNEL, - nsfw: null, - commentsEnabled: null, - downloadEnabled: null, - waitTranscoding: null, - category: this.videoValidatorsService.VIDEO_CATEGORY, - licence: this.videoValidatorsService.VIDEO_LICENCE, - language: this.videoValidatorsService.VIDEO_LANGUAGE, - description: this.videoValidatorsService.VIDEO_DESCRIPTION, - tags: null, - previewfile: null, - support: this.videoValidatorsService.VIDEO_SUPPORT, - schedulePublicationAt: this.videoValidatorsService.VIDEO_SCHEDULE_PUBLICATION_AT, - originallyPublishedAt: this.videoValidatorsService.VIDEO_ORIGINALLY_PUBLISHED_AT - } - - this.formValidatorService.updateForm( - this.form, - this.formErrors, - this.validationMessages, - obj, - defaultValues - ) - - this.form.addControl('captions', new FormArray([ - new FormGroup({ - language: new FormControl(), - captionfile: new FormControl() - }) - ])) - - this.trackChannelChange() - this.trackPrivacyChange() - } - - ngOnInit () { - this.updateForm() - - this.serverService.getVideoCategories() - .subscribe(res => this.videoCategories = res) - this.serverService.getVideoLicences() - .subscribe(res => this.videoLicences = res) - this.serverService.getVideoLanguages() - .subscribe(res => this.videoLanguages = res) - - this.serverService.getVideoPrivacies() - .subscribe(privacies => this.videoPrivacies = this.videoService.explainedPrivacyLabels(privacies)) - - this.serverConfig = this.serverService.getTmpConfig() - this.serverService.getConfig() - .subscribe(config => this.serverConfig = config) - - this.initialVideoCaptions = this.videoCaptions.map(c => c.language.id) - - this.ngZone.runOutsideAngular(() => { - this.schedulerInterval = setInterval(() => this.minScheduledDate = new Date(), 1000 * 60) // Update every minute - }) - } - - ngOnDestroy () { - if (this.schedulerInterval) clearInterval(this.schedulerInterval) - } - - onCaptionAdded (caption: VideoCaptionEdit) { - const existingCaption = this.videoCaptions.find(c => c.language.id === caption.language.id) - - // Replace existing caption? - if (existingCaption) { - Object.assign(existingCaption, caption, { action: 'CREATE' as 'CREATE' }) - } else { - this.videoCaptions.push( - Object.assign(caption, { action: 'CREATE' as 'CREATE' }) - ) - } - - this.sortVideoCaptions() - } - - async deleteCaption (caption: VideoCaptionEdit) { - // Caption recovers his former state - if (caption.action && this.initialVideoCaptions.indexOf(caption.language.id) !== -1) { - caption.action = undefined - return - } - - // This caption is not on the server, just remove it from our array - if (caption.action === 'CREATE') { - removeElementFromArray(this.videoCaptions, caption) - return - } - - caption.action = 'REMOVE' as 'REMOVE' - } - - openAddCaptionModal () { - this.videoCaptionAddModal.show() - } - - private sortVideoCaptions () { - this.videoCaptions.sort((v1, v2) => { - if (v1.language.label < v2.language.label) return -1 - if (v1.language.label === v2.language.label) return 0 - - return 1 - }) - } - - private trackPrivacyChange () { - // We will update the schedule input and the wait transcoding checkbox validators - this.form.controls[ 'privacy' ] - .valueChanges - .pipe(map(res => parseInt(res.toString(), 10))) - .subscribe( - newPrivacyId => { - - this.schedulePublicationEnabled = newPrivacyId === this.SPECIAL_SCHEDULED_PRIVACY - - // Value changed - const scheduleControl = this.form.get('schedulePublicationAt') - const waitTranscodingControl = this.form.get('waitTranscoding') - - if (this.schedulePublicationEnabled) { - scheduleControl.setValidators([ Validators.required ]) - - waitTranscodingControl.disable() - waitTranscodingControl.setValue(false) - } else { - scheduleControl.clearValidators() - - waitTranscodingControl.enable() - - // Do not update the control value on first patch (values come from the server) - if (this.firstPatchDone === true) { - waitTranscodingControl.setValue(true) - } - } - - scheduleControl.updateValueAndValidity() - waitTranscodingControl.updateValueAndValidity() - - this.firstPatchDone = true - - } - ) - } - - private trackChannelChange () { - // We will update the "support" field depending on the channel - this.form.controls[ 'channelId' ] - .valueChanges - .pipe(map(res => parseInt(res.toString(), 10))) - .subscribe( - newChannelId => { - const oldChannelId = parseInt(this.form.value[ 'channelId' ], 10) - - // Not initialized yet - if (isNaN(newChannelId)) return - const newChannel = this.userVideoChannels.find(c => c.id === newChannelId) - if (!newChannel) return - - // Wait support field update - setTimeout(() => { - const currentSupport = this.form.value[ 'support' ] - - // First time we set the channel? - if (isNaN(oldChannelId) && !currentSupport) return this.updateSupportField(newChannel.support) - - const oldChannel = this.userVideoChannels.find(c => c.id === oldChannelId) - if (!newChannel || !oldChannel) { - console.error('Cannot find new or old channel.') - return - } - - // If the current support text is not the same than the old channel, the user updated it. - // We don't want the user to lose his text, so stop here - if (currentSupport && currentSupport !== oldChannel.support) return - - // Update the support text with our new channel - this.updateSupportField(newChannel.support) - }) - } - ) - } - - private updateSupportField (support: string) { - return this.form.patchValue({ support: support || '' }) - } -} diff --git a/client/src/app/videos/+video-edit/shared/video-edit.module.ts b/client/src/app/videos/+video-edit/shared/video-edit.module.ts deleted file mode 100644 index 96061a300..000000000 --- a/client/src/app/videos/+video-edit/shared/video-edit.module.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { TagInputModule } from 'ngx-chips' -import { CalendarModule } from 'primeng/calendar' -import { NgModule } from '@angular/core' -import { SharedFormModule } from '@app/shared/shared-forms' -import { SharedGlobalIconModule } from '@app/shared/shared-icons' -import { SharedMainModule } from '@app/shared/shared-main' -import { VideoCaptionAddModalComponent } from './video-caption-add-modal.component' -import { VideoEditComponent } from './video-edit.component' - -@NgModule({ - imports: [ - TagInputModule, - CalendarModule, - - SharedMainModule, - SharedFormModule, - SharedGlobalIconModule - ], - - declarations: [ - VideoEditComponent, - VideoCaptionAddModalComponent - ], - - exports: [ - TagInputModule, - CalendarModule, - - SharedMainModule, - SharedFormModule, - SharedGlobalIconModule, - - VideoEditComponent - ], - - providers: [] -}) -export class VideoEditModule { } diff --git a/client/src/app/videos/+video-edit/video-add-components/drag-drop.directive.ts b/client/src/app/videos/+video-edit/video-add-components/drag-drop.directive.ts deleted file mode 100644 index 7b1a38c62..000000000 --- a/client/src/app/videos/+video-edit/video-add-components/drag-drop.directive.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Directive, Output, EventEmitter, HostBinding, HostListener } from '@angular/core' - -@Directive({ - selector: '[dragDrop]' -}) -export class DragDropDirective { - @Output() fileDropped = new EventEmitter() - - @HostBinding('class.dragover') dragover = false - - @HostListener('dragover', ['$event']) onDragOver (e: Event) { - e.preventDefault() - e.stopPropagation() - this.dragover = true - } - - @HostListener('dragleave', ['$event']) public onDragLeave (e: Event) { - e.preventDefault() - e.stopPropagation() - this.dragover = false - } - - @HostListener('drop', ['$event']) public ondrop (e: DragEvent) { - e.preventDefault() - e.stopPropagation() - this.dragover = false - const files = e.dataTransfer.files - if (files.length > 0) this.fileDropped.emit(files) - } -} diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.html b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.html deleted file mode 100644 index 7287f799d..000000000 --- a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.html +++ /dev/null @@ -1,76 +0,0 @@ -
-
- - -
- Select the torrent to import - -
- -
- -
- - - - - You can import any torrent file that points to a mp4 file. - You should make sure you have diffusion rights over the content it points to, otherwise it could cause legal trouble to yourself and your instance. - - - - - -
- -
- -
- -
-
- -
- -
- -
-
- - -
-
- -
-
Sorry, but something went wrong
- {{ error }} -
- -
- Congratulations, the video will be imported with BitTorrent! You can already add information about this video. -
- - -
- - -
-
- - -
-
-
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.scss b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.scss deleted file mode 100644 index 1fef74994..000000000 --- a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.scss +++ /dev/null @@ -1,18 +0,0 @@ -@import 'variables'; -@import 'mixins'; - -.first-step-block { - .torrent-or-magnet { - @include divider($color: pvar(--inputPlaceholderColor), $background: pvar(--submenuColor)); - - &[data-content] { - margin: 1.5rem 0; - } - } - - .form-group-magnet-uri { - margin-bottom: 40px; - } -} - - diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts deleted file mode 100644 index 5b453a1d9..000000000 --- a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { Component, ElementRef, EventEmitter, OnInit, Output, ViewChild } from '@angular/core' -import { Router } from '@angular/router' -import { AuthService, CanComponentDeactivate, Notifier, ServerService } from '@app/core' -import { scrollToTop } from '@app/helpers' -import { FormValidatorService } from '@app/shared/shared-forms' -import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' -import { VideoSend } from '@app/videos/+video-edit/video-add-components/video-send' -import { LoadingBarService } from '@ngx-loading-bar/core' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { VideoPrivacy, VideoUpdate } from '@shared/models' - -@Component({ - selector: 'my-video-import-torrent', - templateUrl: './video-import-torrent.component.html', - styleUrls: [ - '../shared/video-edit.component.scss', - './video-import-torrent.component.scss', - './video-send.scss' - ] -}) -export class VideoImportTorrentComponent extends VideoSend implements OnInit, CanComponentDeactivate { - @Output() firstStepDone = new EventEmitter() - @Output() firstStepError = new EventEmitter() - @ViewChild('torrentfileInput') torrentfileInput: ElementRef - - magnetUri = '' - - isImportingVideo = false - hasImportedVideo = false - isUpdatingVideo = false - - video: VideoEdit - error: string - - protected readonly DEFAULT_VIDEO_PRIVACY = VideoPrivacy.PUBLIC - - constructor ( - protected formValidatorService: FormValidatorService, - protected loadingBar: LoadingBarService, - protected notifier: Notifier, - protected authService: AuthService, - protected serverService: ServerService, - protected videoService: VideoService, - protected videoCaptionService: VideoCaptionService, - private router: Router, - private videoImportService: VideoImportService, - private i18n: I18n - ) { - super() - } - - ngOnInit () { - super.ngOnInit() - } - - canDeactivate () { - return { canDeactivate: true } - } - - isMagnetUrlValid () { - return !!this.magnetUri - } - - fileChange () { - const torrentfile = this.torrentfileInput.nativeElement.files[0] - if (!torrentfile) return - - this.importVideo(torrentfile) - } - - setTorrentFile (files: FileList) { - this.torrentfileInput.nativeElement.files = files - this.fileChange() - } - - importVideo (torrentfile?: Blob) { - this.isImportingVideo = true - - const videoUpdate: VideoUpdate = { - privacy: this.firstStepPrivacyId, - waitTranscoding: false, - commentsEnabled: true, - downloadEnabled: true, - channelId: this.firstStepChannelId - } - - this.loadingBar.start() - - this.videoImportService.importVideoTorrent(torrentfile || this.magnetUri, videoUpdate).subscribe( - res => { - this.loadingBar.complete() - this.firstStepDone.emit(res.video.name) - this.isImportingVideo = false - this.hasImportedVideo = true - - this.video = new VideoEdit(Object.assign(res.video, { - commentsEnabled: videoUpdate.commentsEnabled, - downloadEnabled: videoUpdate.downloadEnabled, - support: null, - thumbnailUrl: null, - previewUrl: null - })) - - this.hydrateFormFromVideo() - }, - - err => { - this.loadingBar.complete() - this.isImportingVideo = false - this.firstStepError.emit() - this.notifier.error(err.message) - } - ) - } - - updateSecondStep () { - if (this.checkForm() === false) { - return - } - - this.video.patch(this.form.value) - - this.isUpdatingVideo = true - - // Update the video - this.updateVideoAndCaptions(this.video) - .subscribe( - () => { - this.isUpdatingVideo = false - this.notifier.success(this.i18n('Video to import updated.')) - - this.router.navigate([ '/my-account', 'video-imports' ]) - }, - - err => { - this.error = err.message - scrollToTop() - console.error(err) - } - ) - - } - - private hydrateFormFromVideo () { - this.form.patchValue(this.video.toFormPatch()) - } -} diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.html b/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.html deleted file mode 100644 index 1910da403..000000000 --- a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.html +++ /dev/null @@ -1,72 +0,0 @@ -
-
- - -
- - - - - - You can import any URL supported by youtube-dl - or URL that points to a raw MP4 file. - You should make sure you have diffusion rights over the content it points to, otherwise it could cause legal trouble to yourself and your instance. - - - - - -
- -
- -
- -
-
- -
- -
- -
-
- - -
-
- - -
-
Sorry, but something went wrong
- {{ error }} -
- -
- Congratulations, the video behind {{ targetUrl }} will be imported! You can already add information about this video. -
- - -
- - -
-
- - -
-
-
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.ts b/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.ts deleted file mode 100644 index d0bd1f54d..000000000 --- a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { map, switchMap } from 'rxjs/operators' -import { Component, EventEmitter, OnInit, Output } from '@angular/core' -import { Router } from '@angular/router' -import { AuthService, CanComponentDeactivate, Notifier, ServerService } from '@app/core' -import { getAbsoluteAPIUrl, scrollToTop } from '@app/helpers' -import { FormValidatorService } from '@app/shared/shared-forms' -import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' -import { VideoSend } from '@app/videos/+video-edit/video-add-components/video-send' -import { LoadingBarService } from '@ngx-loading-bar/core' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { VideoPrivacy, VideoUpdate } from '@shared/models' - -@Component({ - selector: 'my-video-import-url', - templateUrl: './video-import-url.component.html', - styleUrls: [ - '../shared/video-edit.component.scss', - './video-send.scss' - ] -}) -export class VideoImportUrlComponent extends VideoSend implements OnInit, CanComponentDeactivate { - @Output() firstStepDone = new EventEmitter() - @Output() firstStepError = new EventEmitter() - - targetUrl = '' - - isImportingVideo = false - hasImportedVideo = false - isUpdatingVideo = false - - video: VideoEdit - error: string - - protected readonly DEFAULT_VIDEO_PRIVACY = VideoPrivacy.PUBLIC - - constructor ( - protected formValidatorService: FormValidatorService, - protected loadingBar: LoadingBarService, - protected notifier: Notifier, - protected authService: AuthService, - protected serverService: ServerService, - protected videoService: VideoService, - protected videoCaptionService: VideoCaptionService, - private router: Router, - private videoImportService: VideoImportService, - private i18n: I18n - ) { - super() - } - - ngOnInit () { - super.ngOnInit() - } - - canDeactivate () { - return { canDeactivate: true } - } - - isTargetUrlValid () { - return this.targetUrl && this.targetUrl.match(/https?:\/\//) - } - - importVideo () { - this.isImportingVideo = true - - const videoUpdate: VideoUpdate = { - privacy: this.firstStepPrivacyId, - waitTranscoding: false, - commentsEnabled: true, - downloadEnabled: true, - channelId: this.firstStepChannelId - } - - this.loadingBar.start() - - this.videoImportService - .importVideoUrl(this.targetUrl, videoUpdate) - .pipe( - switchMap(res => { - return this.videoCaptionService - .listCaptions(res.video.id) - .pipe( - map(result => ({ video: res.video, videoCaptions: result.data })) - ) - }) - ) - .subscribe( - ({ video, videoCaptions }) => { - this.loadingBar.complete() - this.firstStepDone.emit(video.name) - this.isImportingVideo = false - this.hasImportedVideo = true - - const absoluteAPIUrl = getAbsoluteAPIUrl() - - const thumbnailUrl = video.thumbnailPath - ? absoluteAPIUrl + video.thumbnailPath - : null - - const previewUrl = video.previewPath - ? absoluteAPIUrl + video.previewPath - : null - - this.video = new VideoEdit(Object.assign(video, { - commentsEnabled: videoUpdate.commentsEnabled, - downloadEnabled: videoUpdate.downloadEnabled, - support: null, - thumbnailUrl, - previewUrl - })) - - this.videoCaptions = videoCaptions - - this.hydrateFormFromVideo() - }, - - err => { - this.loadingBar.complete() - this.isImportingVideo = false - this.firstStepError.emit() - this.notifier.error(err.message) - } - ) - } - - updateSecondStep () { - if (this.checkForm() === false) { - return - } - - this.video.patch(this.form.value) - - this.isUpdatingVideo = true - - // Update the video - this.updateVideoAndCaptions(this.video) - .subscribe( - () => { - this.isUpdatingVideo = false - this.notifier.success(this.i18n('Video to import updated.')) - - this.router.navigate([ '/my-account', 'video-imports' ]) - }, - - err => { - this.error = err.message - scrollToTop() - console.error(err) - } - ) - - } - - private hydrateFormFromVideo () { - this.form.patchValue(this.video.toFormPatch()) - - const objects = [ - { - url: 'thumbnailUrl', - name: 'thumbnailfile' - }, - { - url: 'previewUrl', - name: 'previewfile' - } - ] - - for (const obj of objects) { - fetch(this.video[obj.url]) - .then(response => response.blob()) - .then(data => { - this.form.patchValue({ - [ obj.name ]: data - }) - }) - } - } -} diff --git a/client/src/app/videos/+video-edit/video-add-components/video-send.scss b/client/src/app/videos/+video-edit/video-add-components/video-send.scss deleted file mode 100644 index ebe14c59e..000000000 --- a/client/src/app/videos/+video-edit/video-add-components/video-send.scss +++ /dev/null @@ -1,46 +0,0 @@ -@import 'variables'; -@import 'mixins'; - -$width-size: 190px; - -.alert.alert-danger { - text-align: center; - - & > div { - font-weight: $font-semibold; - } -} - -.first-step-block { - display: flex; - flex-direction: column; - align-items: center; - - .upload-icon { - width: 90px; - margin-bottom: 25px; - - @include apply-svg-color(#C6C6C6); - } - - .peertube-select-container { - @include peertube-select-container($width-size); - } - - input[type=text] { - @include peertube-input-text($width-size); - display: block; - } - - input[type=button] { - @include peertube-button; - @include orange-button; - - width: $width-size; - margin-top: 30px; - } - - .button-file { - @include peertube-button-file(max-content); - } -} diff --git a/client/src/app/videos/+video-edit/video-add-components/video-send.ts b/client/src/app/videos/+video-edit/video-add-components/video-send.ts deleted file mode 100644 index 94479321d..000000000 --- a/client/src/app/videos/+video-edit/video-add-components/video-send.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { catchError, switchMap, tap } from 'rxjs/operators' -import { EventEmitter, OnInit } from '@angular/core' -import { AuthService, CanComponentDeactivateResult, Notifier, ServerService } from '@app/core' -import { populateAsyncUserVideoChannels } from '@app/helpers' -import { FormReactive } from '@app/shared/shared-forms' -import { VideoCaptionEdit, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' -import { LoadingBarService } from '@ngx-loading-bar/core' -import { ServerConfig, VideoConstant, VideoPrivacy } from '@shared/models' - -export abstract class VideoSend extends FormReactive implements OnInit { - userVideoChannels: { id: number, label: string, support: string }[] = [] - videoPrivacies: VideoConstant[] = [] - videoCaptions: VideoCaptionEdit[] = [] - - firstStepPrivacyId = 0 - firstStepChannelId = 0 - - abstract firstStepDone: EventEmitter - abstract firstStepError: EventEmitter - protected abstract readonly DEFAULT_VIDEO_PRIVACY: VideoPrivacy - - protected loadingBar: LoadingBarService - protected notifier: Notifier - protected authService: AuthService - protected serverService: ServerService - protected videoService: VideoService - protected videoCaptionService: VideoCaptionService - protected serverConfig: ServerConfig - - abstract canDeactivate (): CanComponentDeactivateResult - - ngOnInit () { - this.buildForm({}) - - populateAsyncUserVideoChannels(this.authService, this.userVideoChannels) - .then(() => this.firstStepChannelId = this.userVideoChannels[ 0 ].id) - - this.serverConfig = this.serverService.getTmpConfig() - this.serverService.getConfig() - .subscribe(config => this.serverConfig = config) - - this.serverService.getVideoPrivacies() - .subscribe( - privacies => { - this.videoPrivacies = privacies - - this.firstStepPrivacyId = this.DEFAULT_VIDEO_PRIVACY - }) - } - - checkForm () { - this.forceCheck() - - return this.form.valid - } - - protected updateVideoAndCaptions (video: VideoEdit) { - this.loadingBar.start() - - return this.videoService.updateVideo(video) - .pipe( - // Then update captions - switchMap(() => this.videoCaptionService.updateCaptions(video.id, this.videoCaptions)), - tap(() => this.loadingBar.complete()), - catchError(err => { - this.loadingBar.complete() - throw err - }) - ) - } -} diff --git a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.html b/client/src/app/videos/+video-edit/video-add-components/video-upload.component.html deleted file mode 100644 index dad88a661..000000000 --- a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.html +++ /dev/null @@ -1,90 +0,0 @@ -
-
- - -
- Select the file to upload - -
- -
- -
- -
-
- -
- -
- -
-
- - -
- - -
- Image that will be merged with your audio file. -
- The chosen image will be definitive and cannot be modified. -
- - -
- -
- -
-
-
-
- -
-
-
- Processing… - {{ videoUploadPercents }}% -
-
- -
- -
-
Sorry, but something went wrong
- {{ error }} -
- -
- Congratulations! Your video is now available in your private library. -
- - -
- - -
-
Publish will be available when upload is finished
- -
- - -
-
-
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.scss b/client/src/app/videos/+video-edit/video-add-components/video-upload.component.scss deleted file mode 100644 index a4f87b0b8..000000000 --- a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.scss +++ /dev/null @@ -1,49 +0,0 @@ -@import 'variables'; -@import 'mixins'; - -.first-step-block { - .form-group-channel { - margin-bottom: 20px; - margin-top: 35px; - } - - .audio-image-info { - margin-bottom: 10px; - } - - .audio-preview { - margin: 30px 0; - } -} - -.upload-progress-cancel { - display: flex; - margin-top: 25px; - margin-bottom: 40px; - - .progress { - @include progressbar; - flex-grow: 1; - height: 30px; - font-size: 15px; - background-color: rgba(11, 204, 41, 0.16); - - .progress-bar { - background-color: $green; - line-height: 30px; - text-align: left; - font-weight: $font-bold; - - span { - margin-left: 18px; - } - } - } - - input { - @include peertube-button; - @include grey-button; - - margin-left: 10px; - } -} 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 deleted file mode 100644 index eb7ac32ae..000000000 --- a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts +++ /dev/null @@ -1,306 +0,0 @@ -import { BytesPipe } from 'ngx-pipes' -import { Subscription } from 'rxjs' -import { HttpEventType, HttpResponse } from '@angular/common/http' -import { Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core' -import { Router } from '@angular/router' -import { AuthService, CanComponentDeactivate, Notifier, ServerService, UserService } from '@app/core' -import { scrollToTop } from '@app/helpers' -import { FormValidatorService } from '@app/shared/shared-forms' -import { VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' -import { VideoSend } from '@app/videos/+video-edit/video-add-components/video-send' -import { LoadingBarService } from '@ngx-loading-bar/core' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { VideoPrivacy } from '@shared/models' - -@Component({ - selector: 'my-video-upload', - templateUrl: './video-upload.component.html', - styleUrls: [ - '../shared/video-edit.component.scss', - './video-upload.component.scss', - './video-send.scss' - ] -}) -export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy, CanComponentDeactivate { - @Output() firstStepDone = new EventEmitter() - @Output() firstStepError = new EventEmitter() - @ViewChild('videofileInput') videofileInput: ElementRef - - // So that it can be accessed in the template - readonly SPECIAL_SCHEDULED_PRIVACY = VideoEdit.SPECIAL_SCHEDULED_PRIVACY - - userVideoQuotaUsed = 0 - userVideoQuotaUsedDaily = 0 - - isUploadingAudioFile = false - isUploadingVideo = false - isUpdatingVideo = false - - videoUploaded = false - videoUploadObservable: Subscription = null - videoUploadPercents = 0 - videoUploadedIds = { - id: 0, - uuid: '' - } - - waitTranscodingEnabled = true - previewfileUpload: File - - error: string - - protected readonly DEFAULT_VIDEO_PRIVACY = VideoPrivacy.PUBLIC - - constructor ( - protected formValidatorService: FormValidatorService, - protected loadingBar: LoadingBarService, - protected notifier: Notifier, - protected authService: AuthService, - protected serverService: ServerService, - protected videoService: VideoService, - protected videoCaptionService: VideoCaptionService, - private userService: UserService, - private router: Router, - private i18n: I18n - ) { - super() - } - - get videoExtensions () { - return this.serverConfig.video.file.extensions.join(', ') - } - - ngOnInit () { - super.ngOnInit() - - this.userService.getMyVideoQuotaUsed() - .subscribe(data => { - this.userVideoQuotaUsed = data.videoQuotaUsed - this.userVideoQuotaUsedDaily = data.videoQuotaUsedDaily - }) - } - - ngOnDestroy () { - if (this.videoUploadObservable) this.videoUploadObservable.unsubscribe() - } - - canDeactivate () { - let text = '' - - if (this.videoUploaded === true) { - // FIXME: cannot concatenate strings inside i18n service :/ - text = this.i18n('Your video was uploaded to your account and is private.') + ' ' + - this.i18n('But associated data (tags, description...) will be lost, are you sure you want to leave this page?') - } else { - text = this.i18n('Your video is not uploaded yet, are you sure you want to leave this page?') - } - - return { - canDeactivate: !this.isUploadingVideo, - text - } - } - - getVideoFile () { - return this.videofileInput.nativeElement.files[0] - } - - setVideoFile (files: FileList) { - this.videofileInput.nativeElement.files = files - this.fileChange() - } - - getAudioUploadLabel () { - const videofile = this.getVideoFile() - if (!videofile) return this.i18n('Upload') - - return this.i18n('Upload {{videofileName}}', { videofileName: videofile.name }) - } - - fileChange () { - this.uploadFirstStep() - } - - cancelUpload () { - if (this.videoUploadObservable !== null) { - this.videoUploadObservable.unsubscribe() - - this.isUploadingVideo = false - this.videoUploadPercents = 0 - this.videoUploadObservable = null - - this.firstStepError.emit() - - this.notifier.info(this.i18n('Upload cancelled')) - } - } - - uploadFirstStep (clickedOnButton = false) { - const videofile = this.getVideoFile() - if (!videofile) return - - if (!this.checkGlobalUserQuota(videofile)) return - if (!this.checkDailyUserQuota(videofile)) return - - if (clickedOnButton === false && this.isAudioFile(videofile.name)) { - this.isUploadingAudioFile = true - return - } - - // Build name field - const nameWithoutExtension = videofile.name.replace(/\.[^/.]+$/, '') - let name: string - - // If the name of the file is very small, keep the extension - if (nameWithoutExtension.length < 3) name = videofile.name - else name = nameWithoutExtension - - // Force user to wait transcoding for unsupported video types in web browsers - if (!videofile.name.endsWith('.mp4') && !videofile.name.endsWith('.webm') && !videofile.name.endsWith('.ogv')) { - this.waitTranscodingEnabled = false - } - - const privacy = this.firstStepPrivacyId.toString() - const nsfw = this.serverConfig.instance.isNSFW - const waitTranscoding = true - const commentsEnabled = true - const downloadEnabled = true - const channelId = this.firstStepChannelId.toString() - - const formData = new FormData() - formData.append('name', name) - // Put the video "private" -> we are waiting the user validation of the second step - formData.append('privacy', VideoPrivacy.PRIVATE.toString()) - formData.append('nsfw', '' + nsfw) - formData.append('commentsEnabled', '' + commentsEnabled) - formData.append('downloadEnabled', '' + downloadEnabled) - formData.append('waitTranscoding', '' + waitTranscoding) - formData.append('channelId', '' + channelId) - formData.append('videofile', videofile) - - if (this.previewfileUpload) { - formData.append('previewfile', this.previewfileUpload) - formData.append('thumbnailfile', this.previewfileUpload) - } - - this.isUploadingVideo = true - this.firstStepDone.emit(name) - - this.form.patchValue({ - name, - privacy, - nsfw, - channelId, - previewfile: this.previewfileUpload - }) - - this.videoUploadObservable = this.videoService.uploadVideo(formData).subscribe( - event => { - if (event.type === HttpEventType.UploadProgress) { - this.videoUploadPercents = Math.round(100 * event.loaded / event.total) - } else if (event instanceof HttpResponse) { - this.videoUploaded = true - - this.videoUploadedIds = event.body.video - - this.videoUploadObservable = null - } - }, - - err => { - // Reset progress - this.isUploadingVideo = false - this.videoUploadPercents = 0 - this.videoUploadObservable = null - this.firstStepError.emit() - this.notifier.error(err.message) - } - ) - } - - isPublishingButtonDisabled () { - return !this.form.valid || - this.isUpdatingVideo === true || - this.videoUploaded !== true - } - - updateSecondStep () { - if (this.checkForm() === false) { - return - } - - const video = new VideoEdit() - video.patch(this.form.value) - video.id = this.videoUploadedIds.id - video.uuid = this.videoUploadedIds.uuid - - this.isUpdatingVideo = true - - this.updateVideoAndCaptions(video) - .subscribe( - () => { - this.isUpdatingVideo = false - this.isUploadingVideo = false - - this.notifier.success(this.i18n('Video published.')) - this.router.navigate([ '/videos/watch', video.uuid ]) - }, - - err => { - this.error = err.message - scrollToTop() - console.error(err) - } - ) - } - - private checkGlobalUserQuota (videofile: File) { - const bytePipes = new BytesPipe() - - // Check global user quota - const videoQuota = this.authService.getUser().videoQuota - if (videoQuota !== -1 && (this.userVideoQuotaUsed + videofile.size) > videoQuota) { - const msg = this.i18n( - 'Your video quota is exceeded with this video (video size: {{videoSize}}, used: {{videoQuotaUsed}}, quota: {{videoQuota}})', - { - videoSize: bytePipes.transform(videofile.size, 0), - videoQuotaUsed: bytePipes.transform(this.userVideoQuotaUsed, 0), - videoQuota: bytePipes.transform(videoQuota, 0) - } - ) - this.notifier.error(msg) - - return false - } - - return true - } - - private checkDailyUserQuota (videofile: File) { - const bytePipes = new BytesPipe() - - // Check daily user quota - const videoQuotaDaily = this.authService.getUser().videoQuotaDaily - if (videoQuotaDaily !== -1 && (this.userVideoQuotaUsedDaily + videofile.size) > videoQuotaDaily) { - const msg = this.i18n( - 'Your daily video quota is exceeded with this video (video size: {{videoSize}}, used: {{quotaUsedDaily}}, quota: {{quotaDaily}})', - { - videoSize: bytePipes.transform(videofile.size, 0), - quotaUsedDaily: bytePipes.transform(this.userVideoQuotaUsedDaily, 0), - quotaDaily: bytePipes.transform(videoQuotaDaily, 0) - } - ) - this.notifier.error(msg) - - return false - } - - return true - } - - private isAudioFile (filename: string) { - const extensions = [ '.mp3', '.flac', '.ogg', '.wma', '.wav' ] - - return extensions.some(e => filename.endsWith(e)) - } -} diff --git a/client/src/app/videos/+video-edit/video-add-routing.module.ts b/client/src/app/videos/+video-edit/video-add-routing.module.ts deleted file mode 100644 index 9ff66bea0..000000000 --- a/client/src/app/videos/+video-edit/video-add-routing.module.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { NgModule } from '@angular/core' -import { RouterModule, Routes } from '@angular/router' -import { CanDeactivateGuard, LoginGuard } from '@app/core' -import { MetaGuard } from '@ngx-meta/core' -import { VideoAddComponent } from './video-add.component' - -const videoAddRoutes: Routes = [ - { - path: '', - component: VideoAddComponent, - canActivate: [ MetaGuard, LoginGuard ], - canDeactivate: [ CanDeactivateGuard ] - } -] - -@NgModule({ - imports: [ RouterModule.forChild(videoAddRoutes) ], - exports: [ RouterModule ] -}) -export class VideoAddRoutingModule {} diff --git a/client/src/app/videos/+video-edit/video-add.component.html b/client/src/app/videos/+video-edit/video-add.component.html deleted file mode 100644 index 79bfc6e5c..000000000 --- a/client/src/app/videos/+video-edit/video-add.component.html +++ /dev/null @@ -1,46 +0,0 @@ -
-
- We recommend you to not use the root user to publish your videos, since it's the super-admin account of your instance. -
- Instead, create a dedicated account to upload your videos. -
- -
- Import {{ videoName }} - Upload {{ videoName }} -
- - - -
-
diff --git a/client/src/app/videos/+video-edit/video-add.component.scss b/client/src/app/videos/+video-edit/video-add.component.scss deleted file mode 100644 index 0ad57d897..000000000 --- a/client/src/app/videos/+video-edit/video-add.component.scss +++ /dev/null @@ -1,89 +0,0 @@ -@import '_variables'; -@import '_mixins'; - -$border-width: 3px; -$border-type: solid; -$border-color: #EAEAEA; -$nav-link-height: 40px; - -.margin-content { - padding-top: 50px; -} - -.alert { - font-size: 15px; -} - -::ng-deep .video-add-nav { - border-bottom: $border-width $border-type $border-color; - margin: 50px 0 0 0 !important; - - &.hide-nav { - display: none !important; - } - - a.nav-link { - @include disable-default-a-behaviour; - - margin-bottom: -$border-width; - height: $nav-link-height !important; - padding: 0 30px !important; - font-size: 15px; - - &.active { - border: $border-width $border-type $border-color; - border-bottom: none; - background-color: pvar(--submenuColor) !important; - - span { - border-bottom: 2px solid pvar(--mainColor); - font-weight: $font-bold; - } - } - } -} - -::ng-deep .upload-video-container { - border: $border-width $border-type $border-color; - border-top: transparent; - - background-color: pvar(--submenuColor); - border-bottom-left-radius: 3px; - border-bottom-right-radius: 3px; - width: 100%; - min-height: 440px; - padding-bottom: 20px; - display: flex; - justify-content: center; - align-items: center; - - &.dragover { - border: 3px dashed pvar(--mainColor); - } -} - -@mixin nav-scroll { - ::ng-deep .video-add-nav { - height: #{$nav-link-height + $border-width * 2}; - overflow-x: auto; - white-space: nowrap; - flex-wrap: unset; - - /* Hide active tab style to not have a moving tab effect */ - a.nav-link.active { - border: none; - background-color: pvar(--mainBackgroundColor) !important; - } - } -} - -/* Make .video-add-nav tabs scrollable on small devices */ -@media screen and (max-width: $small-view) { - @include nav-scroll(); -} - -@media screen and (max-width: #{$small-view + $menu-width}) { - :host-context(.main-col:not(.expanded)) { - @include nav-scroll(); - } -} diff --git a/client/src/app/videos/+video-edit/video-add.component.ts b/client/src/app/videos/+video-edit/video-add.component.ts deleted file mode 100644 index 5bd768809..000000000 --- a/client/src/app/videos/+video-edit/video-add.component.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { Component, HostListener, OnInit, ViewChild } from '@angular/core' -import { AuthService, CanComponentDeactivate, ServerService } from '@app/core' -import { ServerConfig } from '@shared/models' -import { VideoImportTorrentComponent } from './video-add-components/video-import-torrent.component' -import { VideoImportUrlComponent } from './video-add-components/video-import-url.component' -import { VideoUploadComponent } from './video-add-components/video-upload.component' - -@Component({ - selector: 'my-videos-add', - templateUrl: './video-add.component.html', - styleUrls: [ './video-add.component.scss' ] -}) -export class VideoAddComponent implements OnInit, CanComponentDeactivate { - @ViewChild('videoUpload') videoUpload: VideoUploadComponent - @ViewChild('videoImportUrl') videoImportUrl: VideoImportUrlComponent - @ViewChild('videoImportTorrent') videoImportTorrent: VideoImportTorrentComponent - - secondStepType: 'upload' | 'import-url' | 'import-torrent' - videoName: string - serverConfig: ServerConfig - - constructor ( - private auth: AuthService, - private serverService: ServerService - ) {} - - ngOnInit () { - this.serverConfig = this.serverService.getTmpConfig() - - this.serverService.getConfig() - .subscribe(config => this.serverConfig = config) - } - - onFirstStepDone (type: 'upload' | 'import-url' | 'import-torrent', videoName: string) { - this.secondStepType = type - this.videoName = videoName - } - - onError () { - this.videoName = undefined - this.secondStepType = undefined - } - - @HostListener('window:beforeunload', [ '$event' ]) - onUnload (event: any) { - const { text, canDeactivate } = this.canDeactivate() - - if (canDeactivate) return - - event.returnValue = text - return text - } - - canDeactivate (): { canDeactivate: boolean, text?: string} { - if (this.secondStepType === 'upload') return this.videoUpload.canDeactivate() - if (this.secondStepType === 'import-url') return this.videoImportUrl.canDeactivate() - if (this.secondStepType === 'import-torrent') return this.videoImportTorrent.canDeactivate() - - return { canDeactivate: true } - } - - isVideoImportHttpEnabled () { - return this.serverConfig.import.videos.http.enabled - } - - isVideoImportTorrentEnabled () { - return this.serverConfig.import.videos.torrent.enabled - } - - isInSecondStep () { - return !!this.secondStepType - } - - isRootUser () { - return this.auth.getUser().username === 'root' - } -} diff --git a/client/src/app/videos/+video-edit/video-add.module.ts b/client/src/app/videos/+video-edit/video-add.module.ts deleted file mode 100644 index 477c1cf5e..000000000 --- a/client/src/app/videos/+video-edit/video-add.module.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { NgModule } from '@angular/core' -import { CanDeactivateGuard } from '@app/core' -import { VideoEditModule } from './shared/video-edit.module' -import { DragDropDirective } from './video-add-components/drag-drop.directive' -import { VideoImportTorrentComponent } from './video-add-components/video-import-torrent.component' -import { VideoImportUrlComponent } from './video-add-components/video-import-url.component' -import { VideoUploadComponent } from './video-add-components/video-upload.component' -import { VideoAddRoutingModule } from './video-add-routing.module' -import { VideoAddComponent } from './video-add.component' - -@NgModule({ - imports: [ - VideoAddRoutingModule, - - VideoEditModule - ], - - declarations: [ - VideoAddComponent, - VideoUploadComponent, - VideoImportUrlComponent, - VideoImportTorrentComponent, - DragDropDirective - ], - - exports: [ ], - - providers: [ - CanDeactivateGuard - ] -}) -export class VideoAddModule { } diff --git a/client/src/app/videos/+video-edit/video-update-routing.module.ts b/client/src/app/videos/+video-edit/video-update-routing.module.ts deleted file mode 100644 index a04351b05..000000000 --- a/client/src/app/videos/+video-edit/video-update-routing.module.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { NgModule } from '@angular/core' -import { RouterModule, Routes } from '@angular/router' -import { CanDeactivateGuard, LoginGuard } from '@app/core' -import { MetaGuard } from '@ngx-meta/core' -import { VideoUpdateComponent } from './video-update.component' -import { VideoUpdateResolver } from './video-update.resolver' - -const videoUpdateRoutes: Routes = [ - { - path: '', - component: VideoUpdateComponent, - canActivate: [ MetaGuard, LoginGuard ], - canDeactivate: [ CanDeactivateGuard ], - resolve: { - videoData: VideoUpdateResolver - } - } -] - -@NgModule({ - imports: [ RouterModule.forChild(videoUpdateRoutes) ], - exports: [ RouterModule ] -}) -export class VideoUpdateRoutingModule {} diff --git a/client/src/app/videos/+video-edit/video-update.component.html b/client/src/app/videos/+video-edit/video-update.component.html deleted file mode 100644 index fbc642db9..000000000 --- a/client/src/app/videos/+video-edit/video-update.component.html +++ /dev/null @@ -1,22 +0,0 @@ -
-
- Update - {{ video?.name }} -
- -
- - - -
-
- - -
-
-
-
diff --git a/client/src/app/videos/+video-edit/video-update.component.ts b/client/src/app/videos/+video-edit/video-update.component.ts deleted file mode 100644 index 7bd6eb553..000000000 --- a/client/src/app/videos/+video-edit/video-update.component.ts +++ /dev/null @@ -1,155 +0,0 @@ -import { map, switchMap } from 'rxjs/operators' -import { Component, HostListener, OnInit } from '@angular/core' -import { ActivatedRoute, Router } from '@angular/router' -import { Notifier } from '@app/core' -import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' -import { VideoCaptionEdit, VideoCaptionService, VideoDetails, VideoEdit, VideoService } from '@app/shared/shared-main' -import { LoadingBarService } from '@ngx-loading-bar/core' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { VideoPrivacy } from '@shared/models' - -@Component({ - selector: 'my-videos-update', - styleUrls: [ './shared/video-edit.component.scss' ], - templateUrl: './video-update.component.html' -}) -export class VideoUpdateComponent extends FormReactive implements OnInit { - video: VideoEdit - - isUpdatingVideo = false - userVideoChannels: { id: number, label: string, support: string }[] = [] - schedulePublicationPossible = false - videoCaptions: VideoCaptionEdit[] = [] - waitTranscodingEnabled = true - - private updateDone = false - - constructor ( - protected formValidatorService: FormValidatorService, - private route: ActivatedRoute, - private router: Router, - private notifier: Notifier, - private videoService: VideoService, - private loadingBar: LoadingBarService, - private videoCaptionService: VideoCaptionService, - private i18n: I18n - ) { - super() - } - - ngOnInit () { - this.buildForm({}) - - this.route.data - .pipe(map(data => data.videoData)) - .subscribe(({ video, videoChannels, videoCaptions }) => { - this.video = new VideoEdit(video) - this.userVideoChannels = videoChannels - this.videoCaptions = videoCaptions - - this.schedulePublicationPossible = this.video.privacy === VideoPrivacy.PRIVATE - - const videoFiles = (video as VideoDetails).getFiles() - if (videoFiles.length > 1) { // Already transcoded - this.waitTranscodingEnabled = false - } - - // FIXME: Angular does not detect the change inside this subscription, so use the patched setTimeout - setTimeout(() => this.hydrateFormFromVideo()) - }, - - err => { - console.error(err) - this.notifier.error(err.message) - } - ) - } - - @HostListener('window:beforeunload', [ '$event' ]) - onUnload (event: any) { - const { text, canDeactivate } = this.canDeactivate() - - if (canDeactivate) return - - event.returnValue = text - return text - } - - canDeactivate (): { canDeactivate: boolean, text?: string } { - if (this.updateDone === true) return { canDeactivate: true } - - const text = this.i18n('You have unsaved changes! If you leave, your changes will be lost.') - - for (const caption of this.videoCaptions) { - if (caption.action) return { canDeactivate: false, text } - } - - return { canDeactivate: this.formChanged === false, text } - } - - checkForm () { - this.forceCheck() - - return this.form.valid - } - - update () { - if (this.checkForm() === false - || this.isUpdatingVideo === true) { - return - } - - this.video.patch(this.form.value) - - this.loadingBar.start() - this.isUpdatingVideo = true - - // Update the video - this.videoService.updateVideo(this.video) - .pipe( - // Then update captions - switchMap(() => this.videoCaptionService.updateCaptions(this.video.id, this.videoCaptions)) - ) - .subscribe( - () => { - this.updateDone = true - this.isUpdatingVideo = false - this.loadingBar.complete() - this.notifier.success(this.i18n('Video updated.')) - this.router.navigate([ '/videos/watch', this.video.uuid ]) - }, - - err => { - this.loadingBar.complete() - this.isUpdatingVideo = false - this.notifier.error(err.message) - console.error(err) - } - ) - } - - private hydrateFormFromVideo () { - this.form.patchValue(this.video.toFormPatch()) - - const objects = [ - { - url: 'thumbnailUrl', - name: 'thumbnailfile' - }, - { - url: 'previewUrl', - name: 'previewfile' - } - ] - - for (const obj of objects) { - fetch(this.video[obj.url]) - .then(response => response.blob()) - .then(data => { - this.form.patchValue({ - [ obj.name ]: data - }) - }) - } - } -} diff --git a/client/src/app/videos/+video-edit/video-update.module.ts b/client/src/app/videos/+video-edit/video-update.module.ts deleted file mode 100644 index 322c69629..000000000 --- a/client/src/app/videos/+video-edit/video-update.module.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { NgModule } from '@angular/core' -import { CanDeactivateGuard } from '@app/core' -import { VideoUpdateResolver } from '@app/videos/+video-edit/video-update.resolver' -import { VideoEditModule } from './shared/video-edit.module' -import { VideoUpdateRoutingModule } from './video-update-routing.module' -import { VideoUpdateComponent } from './video-update.component' - -@NgModule({ - imports: [ - VideoUpdateRoutingModule, - - VideoEditModule - ], - - declarations: [ - VideoUpdateComponent - ], - - exports: [ ], - - providers: [ - VideoUpdateResolver, - CanDeactivateGuard - ] -}) -export class VideoUpdateModule { } diff --git a/client/src/app/videos/+video-edit/video-update.resolver.ts b/client/src/app/videos/+video-edit/video-update.resolver.ts deleted file mode 100644 index 30bcf4d74..000000000 --- a/client/src/app/videos/+video-edit/video-update.resolver.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { forkJoin } from 'rxjs' -import { map, switchMap } from 'rxjs/operators' -import { Injectable } from '@angular/core' -import { ActivatedRouteSnapshot, Resolve } from '@angular/router' -import { VideoCaptionService, VideoChannelService, VideoService } from '@app/shared/shared-main' - -@Injectable() -export class VideoUpdateResolver implements Resolve { - constructor ( - private videoService: VideoService, - private videoChannelService: VideoChannelService, - private videoCaptionService: VideoCaptionService - ) { - } - - resolve (route: ActivatedRouteSnapshot) { - const uuid: string = route.params[ 'uuid' ] - - return this.videoService.getVideo({ videoId: uuid }) - .pipe( - switchMap(video => { - return forkJoin([ - this.videoService - .loadCompleteDescription(video.descriptionPath) - .pipe(map(description => Object.assign(video, { description }))), - - this.videoChannelService - .listAccountVideoChannels(video.account) - .pipe( - map(result => result.data), - map(videoChannels => videoChannels.map(c => ({ id: c.id, label: c.displayName, support: c.support }))) - ), - - this.videoCaptionService - .listCaptions(video.id) - .pipe( - map(result => result.data) - ) - ]) - }), - map(([ video, videoChannels, videoCaptions ]) => ({ video, videoChannels, videoCaptions })) - ) - } -} -- cgit v1.2.3