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