Begin videos of an account
[oweals/peertube.git] / client / src / app / videos / +video-edit / video-add.component.ts
1 import { HttpEventType, HttpResponse } from '@angular/common/http'
2 import { Component, OnInit, ViewChild } from '@angular/core'
3 import { FormBuilder, FormGroup } from '@angular/forms'
4 import { Router } from '@angular/router'
5 import { NotificationsService } from 'angular2-notifications'
6 import { VideoService } from 'app/shared/video/video.service'
7 import { VideoCreate } from '../../../../../shared'
8 import { AuthService, ServerService } from '../../core'
9 import {
10   FormReactive,
11   VIDEO_CATEGORY,
12   VIDEO_CHANNEL,
13   VIDEO_DESCRIPTION,
14   VIDEO_FILE,
15   VIDEO_LANGUAGE,
16   VIDEO_LICENCE,
17   VIDEO_NAME,
18   VIDEO_PRIVACY,
19   VIDEO_TAGS
20 } from '../../shared'
21
22 @Component({
23   selector: 'my-videos-add',
24   styleUrls: [ './shared/video-edit.component.scss' ],
25   templateUrl: './video-add.component.html'
26 })
27
28 export class VideoAddComponent extends FormReactive implements OnInit {
29   @ViewChild('videofileInput') videofileInput
30
31   progressPercent = 0
32   tags: string[] = []
33   videoCategories = []
34   videoLicences = []
35   videoLanguages = []
36   videoPrivacies = []
37   userVideoChannels = []
38
39   tagValidators = VIDEO_TAGS.VALIDATORS
40   tagValidatorsMessages = VIDEO_TAGS.MESSAGES
41
42   error: string
43   form: FormGroup
44   formErrors = {
45     name: '',
46     privacy: '',
47     category: '',
48     licence: '',
49     language: '',
50     channelId: '',
51     description: '',
52     videofile: ''
53   }
54   validationMessages = {
55     name: VIDEO_NAME.MESSAGES,
56     privacy: VIDEO_PRIVACY.MESSAGES,
57     category: VIDEO_CATEGORY.MESSAGES,
58     licence: VIDEO_LICENCE.MESSAGES,
59     language: VIDEO_LANGUAGE.MESSAGES,
60     channelId: VIDEO_CHANNEL.MESSAGES,
61     description: VIDEO_DESCRIPTION.MESSAGES,
62     videofile: VIDEO_FILE.MESSAGES
63   }
64
65   constructor (
66     private formBuilder: FormBuilder,
67     private router: Router,
68     private notificationsService: NotificationsService,
69     private authService: AuthService,
70     private serverService: ServerService,
71     private videoService: VideoService
72   ) {
73     super()
74   }
75
76   get filename () {
77     return this.form.value['videofile']
78   }
79
80   buildForm () {
81     this.form = this.formBuilder.group({
82       name: [ '', VIDEO_NAME.VALIDATORS ],
83       nsfw: [ false ],
84       privacy: [ '', VIDEO_PRIVACY.VALIDATORS ],
85       category: [ '', VIDEO_CATEGORY.VALIDATORS ],
86       licence: [ '', VIDEO_LICENCE.VALIDATORS ],
87       language: [ '', VIDEO_LANGUAGE.VALIDATORS ],
88       channelId: [ '', VIDEO_CHANNEL.VALIDATORS ],
89       description: [ '', VIDEO_DESCRIPTION.VALIDATORS ],
90       videofile: [ '', VIDEO_FILE.VALIDATORS ],
91       tags: [ '' ]
92     })
93
94     this.form.valueChanges.subscribe(data => this.onValueChanged(data))
95   }
96
97   ngOnInit () {
98     this.videoCategories = this.serverService.getVideoCategories()
99     this.videoLicences = this.serverService.getVideoLicences()
100     this.videoLanguages = this.serverService.getVideoLanguages()
101     this.videoPrivacies = this.serverService.getVideoPrivacies()
102
103     this.buildForm()
104
105     this.authService.userInformationLoaded
106       .subscribe(
107         () => {
108           const user = this.authService.getUser()
109           if (!user) return
110
111           const videoChannels = user.videoChannels
112           if (Array.isArray(videoChannels) === false) return
113
114           this.userVideoChannels = videoChannels.map(v => ({ id: v.id, label: v.name }))
115
116           this.form.patchValue({ channelId: this.userVideoChannels[0].id })
117         }
118       )
119   }
120
121   // The goal is to keep reactive form validation (required field)
122   // https://stackoverflow.com/a/44238894
123   fileChange ($event) {
124     this.form.controls['videofile'].setValue($event.target.files[0].name)
125   }
126
127   removeFile () {
128     this.videofileInput.nativeElement.value = ''
129     this.form.controls['videofile'].setValue('')
130   }
131
132   checkForm () {
133     this.forceCheck()
134
135     return this.form.valid
136   }
137
138   upload () {
139     if (this.checkForm() === false) {
140       return
141     }
142
143     const formValue: VideoCreate = this.form.value
144
145     const name = formValue.name
146     const privacy = formValue.privacy
147     const nsfw = formValue.nsfw
148     const category = formValue.category
149     const licence = formValue.licence
150     const language = formValue.language
151     const channelId = formValue.channelId
152     const description = formValue.description
153     const tags = formValue.tags
154     const videofile = this.videofileInput.nativeElement.files[0]
155
156     const formData = new FormData()
157     formData.append('name', name)
158     formData.append('privacy', privacy.toString())
159     formData.append('category', '' + category)
160     formData.append('nsfw', '' + nsfw)
161     formData.append('licence', '' + licence)
162     formData.append('channelId', '' + channelId)
163     formData.append('videofile', videofile)
164
165     // Language is optional
166     if (language) {
167       formData.append('language', '' + language)
168     }
169
170     formData.append('description', description)
171
172     for (let i = 0; i < tags.length; i++) {
173       formData.append(`tags[${i}]`, tags[i])
174     }
175
176     this.videoService.uploadVideo(formData).subscribe(
177       event => {
178         if (event.type === HttpEventType.UploadProgress) {
179           this.progressPercent = Math.round(100 * event.loaded / event.total)
180         } else if (event instanceof HttpResponse) {
181           console.log('Video uploaded.')
182           this.notificationsService.success('Success', 'Video uploaded.')
183
184           // Display all the videos once it's finished
185           this.router.navigate([ '/videos/trending' ])
186         }
187       },
188
189       err => {
190         // Reset progress
191         this.progressPercent = 0
192         this.error = err.message
193       }
194     )
195   }
196 }