diff options
Diffstat (limited to 'client/src/app/videos/video-edit')
6 files changed, 688 insertions, 0 deletions
diff --git a/client/src/app/videos/video-edit/index.ts b/client/src/app/videos/video-edit/index.ts new file mode 100644 index 000000000..5ce4fb9b1 --- /dev/null +++ b/client/src/app/videos/video-edit/index.ts | |||
@@ -0,0 +1,2 @@ | |||
1 | export * from './video-add.component'; | ||
2 | export * from './video-update.component'; | ||
diff --git a/client/src/app/videos/video-edit/video-add.component.html b/client/src/app/videos/video-edit/video-add.component.html new file mode 100644 index 000000000..104747a8c --- /dev/null +++ b/client/src/app/videos/video-edit/video-add.component.html | |||
@@ -0,0 +1,128 @@ | |||
1 | <h3>Upload a video</h3> | ||
2 | |||
3 | <div *ngIf="error" class="alert alert-danger">{{ error }}</div> | ||
4 | |||
5 | <form novalidate [formGroup]="form"> | ||
6 | <div class="form-group"> | ||
7 | <label for="name">Name</label> | ||
8 | <input | ||
9 | type="text" class="form-control" id="name" | ||
10 | formControlName="name" | ||
11 | > | ||
12 | <div *ngIf="formErrors.name" class="alert alert-danger"> | ||
13 | {{ formErrors.name }} | ||
14 | </div> | ||
15 | </div> | ||
16 | |||
17 | <div class="form-group"> | ||
18 | <label for="nsfw">NSFW</label> | ||
19 | <input | ||
20 | type="checkbox" id="nsfw" | ||
21 | formControlName="nsfw" | ||
22 | > | ||
23 | </div> | ||
24 | |||
25 | <div class="form-group"> | ||
26 | <label for="category">Category</label> | ||
27 | <select class="form-control" id="category" formControlName="category"> | ||
28 | <option></option> | ||
29 | <option *ngFor="let category of videoCategories" [value]="category.id">{{ category.label }}</option> | ||
30 | </select> | ||
31 | |||
32 | <div *ngIf="formErrors.category" class="alert alert-danger"> | ||
33 | {{ formErrors.category }} | ||
34 | </div> | ||
35 | </div> | ||
36 | |||
37 | <div class="form-group"> | ||
38 | <label for="licence">Licence</label> | ||
39 | <select class="form-control" id="licence" formControlName="licence"> | ||
40 | <option></option> | ||
41 | <option *ngFor="let licence of videoLicences" [value]="licence.id">{{ licence.label }}</option> | ||
42 | </select> | ||
43 | |||
44 | <div *ngIf="formErrors.licence" class="alert alert-danger"> | ||
45 | {{ formErrors.licence }} | ||
46 | </div> | ||
47 | </div> | ||
48 | |||
49 | <div class="form-group"> | ||
50 | <label for="language">Language</label> | ||
51 | <select class="form-control" id="language" formControlName="language"> | ||
52 | <option></option> | ||
53 | <option *ngFor="let language of videoLanguages" [value]="language.id">{{ language.label }}</option> | ||
54 | </select> | ||
55 | |||
56 | <div *ngIf="formErrors.language" class="alert alert-danger"> | ||
57 | {{ formErrors.language }} | ||
58 | </div> | ||
59 | </div> | ||
60 | |||
61 | <div class="form-group"> | ||
62 | <label for="tags">Tags</label> <span class="little-information">(press enter to add the tag)</span> | ||
63 | <input | ||
64 | type="text" class="form-control" id="currentTag" | ||
65 | formControlName="currentTag" (keyup)="onTagKeyPress($event)" | ||
66 | > | ||
67 | <div *ngIf="formErrors.currentTag" class="alert alert-danger"> | ||
68 | {{ formErrors.currentTag }} | ||
69 | </div> | ||
70 | </div> | ||
71 | |||
72 | <div class="tags"> | ||
73 | <div class="label label-primary tag" *ngFor="let tag of tags"> | ||
74 | {{ tag }} | ||
75 | <span class="remove" (click)="removeTag(tag)">x</span> | ||
76 | </div> | ||
77 | </div> | ||
78 | |||
79 | <div *ngIf="tagsError" class="alert alert-danger"> | ||
80 | {{ tagsError }} | ||
81 | </div> | ||
82 | |||
83 | <div class="form-group"> | ||
84 | <label for="videofile">File</label> | ||
85 | <div class="btn btn-default btn-file" [ngClass]="{ 'disabled': filename !== null }" > | ||
86 | <span>Select the video...</span> | ||
87 | <input | ||
88 | type="file" name="videofile" id="videofile" | ||
89 | ng2FileSelect [uploader]="uploader" [disabled]="filename !== null" | ||
90 | (change)="fileChanged()" | ||
91 | > | ||
92 | </div> | ||
93 | </div> | ||
94 | |||
95 | <div class="file-to-upload"> | ||
96 | <div class="file" *ngIf="uploader.queue.length > 0"> | ||
97 | <span class="filename">{{ filename }}</span> | ||
98 | <span class="glyphicon glyphicon-remove" (click)="removeFile()"></span> | ||
99 | </div> | ||
100 | </div> | ||
101 | |||
102 | <div *ngIf="fileError" class="alert alert-danger"> | ||
103 | {{ fileError }} | ||
104 | </div> | ||
105 | |||
106 | <div class="form-group"> | ||
107 | <label for="description">Description</label> | ||
108 | <textarea | ||
109 | id="description" class="form-control" placeholder="Description..." | ||
110 | formControlName="description" | ||
111 | > | ||
112 | </textarea> | ||
113 | <div *ngIf="formErrors.description" class="alert alert-danger"> | ||
114 | {{ formErrors.description }} | ||
115 | </div> | ||
116 | </div> | ||
117 | |||
118 | <div class="progress"> | ||
119 | <progressbar [value]="uploader.progress" max="100"></progressbar> | ||
120 | </div> | ||
121 | |||
122 | <div class="form-group"> | ||
123 | <input | ||
124 | type="button" value="Upload" class="btn btn-default form-control" | ||
125 | (click)="upload()" | ||
126 | > | ||
127 | </div> | ||
128 | </form> | ||
diff --git a/client/src/app/videos/video-edit/video-add.component.ts b/client/src/app/videos/video-edit/video-add.component.ts new file mode 100644 index 000000000..e3cf0e9d8 --- /dev/null +++ b/client/src/app/videos/video-edit/video-add.component.ts | |||
@@ -0,0 +1,230 @@ | |||
1 | import { Component, ElementRef, OnInit } from '@angular/core'; | ||
2 | import { FormBuilder, FormGroup } from '@angular/forms'; | ||
3 | import { Router } from '@angular/router'; | ||
4 | |||
5 | import { FileUploader } from 'ng2-file-upload/ng2-file-upload'; | ||
6 | import { NotificationsService } from 'angular2-notifications'; | ||
7 | |||
8 | import { AuthService } from '../../core'; | ||
9 | import { | ||
10 | FormReactive, | ||
11 | VIDEO_NAME, | ||
12 | VIDEO_CATEGORY, | ||
13 | VIDEO_LICENCE, | ||
14 | VIDEO_LANGUAGE, | ||
15 | VIDEO_DESCRIPTION, | ||
16 | VIDEO_TAGS | ||
17 | } from '../../shared'; | ||
18 | import { VideoService } from '../shared'; | ||
19 | |||
20 | @Component({ | ||
21 | selector: 'my-videos-add', | ||
22 | styleUrls: [ './video-edit.component.scss' ], | ||
23 | templateUrl: './video-add.component.html' | ||
24 | }) | ||
25 | |||
26 | export class VideoAddComponent extends FormReactive implements OnInit { | ||
27 | tags: string[] = []; | ||
28 | uploader: FileUploader; | ||
29 | videoCategories = []; | ||
30 | videoLicences = []; | ||
31 | videoLanguages = []; | ||
32 | |||
33 | error: string = null; | ||
34 | form: FormGroup; | ||
35 | formErrors = { | ||
36 | name: '', | ||
37 | category: '', | ||
38 | licence: '', | ||
39 | language: '', | ||
40 | description: '', | ||
41 | currentTag: '' | ||
42 | }; | ||
43 | validationMessages = { | ||
44 | name: VIDEO_NAME.MESSAGES, | ||
45 | category: VIDEO_CATEGORY.MESSAGES, | ||
46 | licence: VIDEO_LICENCE.MESSAGES, | ||
47 | language: VIDEO_LANGUAGE.MESSAGES, | ||
48 | description: VIDEO_DESCRIPTION.MESSAGES, | ||
49 | currentTag: VIDEO_TAGS.MESSAGES | ||
50 | }; | ||
51 | |||
52 | // Special error messages | ||
53 | tagsError = ''; | ||
54 | fileError = ''; | ||
55 | |||
56 | constructor( | ||
57 | private authService: AuthService, | ||
58 | private elementRef: ElementRef, | ||
59 | private formBuilder: FormBuilder, | ||
60 | private router: Router, | ||
61 | private notificationsService: NotificationsService, | ||
62 | private videoService: VideoService | ||
63 | ) { | ||
64 | super(); | ||
65 | } | ||
66 | |||
67 | get filename() { | ||
68 | if (this.uploader.queue.length === 0) { | ||
69 | return null; | ||
70 | } | ||
71 | |||
72 | return this.uploader.queue[0].file.name; | ||
73 | } | ||
74 | |||
75 | buildForm() { | ||
76 | this.form = this.formBuilder.group({ | ||
77 | name: [ '', VIDEO_NAME.VALIDATORS ], | ||
78 | nsfw: [ false ], | ||
79 | category: [ '', VIDEO_CATEGORY.VALIDATORS ], | ||
80 | licence: [ '', VIDEO_LICENCE.VALIDATORS ], | ||
81 | language: [ '', VIDEO_LANGUAGE.VALIDATORS ], | ||
82 | description: [ '', VIDEO_DESCRIPTION.VALIDATORS ], | ||
83 | currentTag: [ '', VIDEO_TAGS.VALIDATORS ] | ||
84 | }); | ||
85 | |||
86 | this.form.valueChanges.subscribe(data => this.onValueChanged(data)); | ||
87 | } | ||
88 | |||
89 | ngOnInit() { | ||
90 | this.videoCategories = this.videoService.videoCategories; | ||
91 | this.videoLicences = this.videoService.videoLicences; | ||
92 | this.videoLanguages = this.videoService.videoLanguages; | ||
93 | |||
94 | this.uploader = new FileUploader({ | ||
95 | authToken: this.authService.getRequestHeaderValue(), | ||
96 | queueLimit: 1, | ||
97 | url: '/api/v1/videos', | ||
98 | removeAfterUpload: true | ||
99 | }); | ||
100 | |||
101 | this.uploader.onBuildItemForm = (item, form) => { | ||
102 | const name = this.form.value['name']; | ||
103 | const nsfw = this.form.value['nsfw']; | ||
104 | const category = this.form.value['category']; | ||
105 | const licence = this.form.value['licence']; | ||
106 | const language = this.form.value['language']; | ||
107 | const description = this.form.value['description']; | ||
108 | |||
109 | form.append('name', name); | ||
110 | form.append('category', category); | ||
111 | form.append('nsfw', nsfw); | ||
112 | form.append('licence', licence); | ||
113 | |||
114 | // Language is optional | ||
115 | if (language) { | ||
116 | form.append('language', language); | ||
117 | } | ||
118 | |||
119 | form.append('description', description); | ||
120 | |||
121 | for (let i = 0; i < this.tags.length; i++) { | ||
122 | form.append(`tags[${i}]`, this.tags[i]); | ||
123 | } | ||
124 | }; | ||
125 | |||
126 | this.buildForm(); | ||
127 | } | ||
128 | |||
129 | checkForm() { | ||
130 | this.forceCheck(); | ||
131 | |||
132 | if (this.filename === null) { | ||
133 | this.fileError = 'You did not add a file.'; | ||
134 | } | ||
135 | |||
136 | return this.form.valid === true && this.tagsError === '' && this.fileError === ''; | ||
137 | } | ||
138 | |||
139 | fileChanged() { | ||
140 | this.fileError = ''; | ||
141 | } | ||
142 | |||
143 | onTagKeyPress(event: KeyboardEvent) { | ||
144 | // Enter press | ||
145 | if (event.keyCode === 13) { | ||
146 | this.addTagIfPossible(); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | removeFile() { | ||
151 | this.uploader.clearQueue(); | ||
152 | } | ||
153 | |||
154 | removeTag(tag: string) { | ||
155 | this.tags.splice(this.tags.indexOf(tag), 1); | ||
156 | this.form.get('currentTag').enable(); | ||
157 | } | ||
158 | |||
159 | upload() { | ||
160 | // Maybe the user forgot to press "enter" when he filled the field | ||
161 | this.addTagIfPossible(); | ||
162 | |||
163 | if (this.checkForm() === false) { | ||
164 | return; | ||
165 | } | ||
166 | |||
167 | const item = this.uploader.queue[0]; | ||
168 | // TODO: wait for https://github.com/valor-software/ng2-file-upload/pull/242 | ||
169 | item.alias = 'videofile'; | ||
170 | |||
171 | // FIXME: remove | ||
172 | // Run detection change for progress bar | ||
173 | const interval = setInterval(() => { ; }, 250); | ||
174 | |||
175 | item.onSuccess = () => { | ||
176 | clearInterval(interval); | ||
177 | |||
178 | console.log('Video uploaded.'); | ||
179 | this.notificationsService.success('Success', 'Video uploaded.'); | ||
180 | |||
181 | |||
182 | // Print all the videos once it's finished | ||
183 | this.router.navigate(['/videos/list']); | ||
184 | }; | ||
185 | |||
186 | item.onError = (response: string, status: number) => { | ||
187 | clearInterval(interval); | ||
188 | |||
189 | // We need to handle manually these cases beceause we use the FileUpload component | ||
190 | if (status === 400) { | ||
191 | this.error = response; | ||
192 | } else if (status === 401) { | ||
193 | this.error = 'Access token was expired, refreshing token...'; | ||
194 | this.authService.refreshAccessToken().subscribe( | ||
195 | () => { | ||
196 | // Update the uploader request header | ||
197 | this.uploader.authToken = this.authService.getRequestHeaderValue(); | ||
198 | this.error += ' access token refreshed. Please retry your request.'; | ||
199 | } | ||
200 | ); | ||
201 | } else { | ||
202 | this.error = 'Unknow error'; | ||
203 | console.error(this.error); | ||
204 | } | ||
205 | }; | ||
206 | |||
207 | this.uploader.uploadAll(); | ||
208 | } | ||
209 | |||
210 | private addTagIfPossible() { | ||
211 | const currentTag = this.form.value['currentTag']; | ||
212 | if (currentTag === undefined) return; | ||
213 | |||
214 | // Check if the tag is valid and does not already exist | ||
215 | if ( | ||
216 | currentTag.length >= 2 && | ||
217 | this.form.controls['currentTag'].valid && | ||
218 | this.tags.indexOf(currentTag) === -1 | ||
219 | ) { | ||
220 | this.tags.push(currentTag); | ||
221 | this.form.patchValue({ currentTag: '' }); | ||
222 | |||
223 | if (this.tags.length >= 3) { | ||
224 | this.form.get('currentTag').disable(); | ||
225 | } | ||
226 | |||
227 | this.tagsError = ''; | ||
228 | } | ||
229 | } | ||
230 | } | ||
diff --git a/client/src/app/videos/video-edit/video-edit.component.scss b/client/src/app/videos/video-edit/video-edit.component.scss new file mode 100644 index 000000000..11ee3297e --- /dev/null +++ b/client/src/app/videos/video-edit/video-edit.component.scss | |||
@@ -0,0 +1,57 @@ | |||
1 | .btn-file { | ||
2 | position: relative; | ||
3 | overflow: hidden; | ||
4 | display: block; | ||
5 | } | ||
6 | |||
7 | .btn-file input[type=file] { | ||
8 | position: absolute; | ||
9 | top: 0; | ||
10 | right: 0; | ||
11 | min-width: 100%; | ||
12 | min-height: 100%; | ||
13 | font-size: 100px; | ||
14 | text-align: right; | ||
15 | filter: alpha(opacity=0); | ||
16 | opacity: 0; | ||
17 | outline: none; | ||
18 | background: white; | ||
19 | cursor: inherit; | ||
20 | display: block; | ||
21 | } | ||
22 | |||
23 | .name_file { | ||
24 | display: inline-block; | ||
25 | margin-left: 10px; | ||
26 | } | ||
27 | |||
28 | .form-group { | ||
29 | margin-bottom: 10px; | ||
30 | } | ||
31 | |||
32 | div.tags { | ||
33 | height: 40px; | ||
34 | font-size: 20px; | ||
35 | margin-top: 20px; | ||
36 | |||
37 | .tag { | ||
38 | margin-right: 10px; | ||
39 | |||
40 | .remove { | ||
41 | cursor: pointer; | ||
42 | } | ||
43 | } | ||
44 | } | ||
45 | |||
46 | div.file-to-upload { | ||
47 | height: 40px; | ||
48 | |||
49 | .glyphicon-remove { | ||
50 | cursor: pointer; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | .little-information { | ||
55 | font-size: 0.8em; | ||
56 | font-style: italic; | ||
57 | } | ||
diff --git a/client/src/app/videos/video-edit/video-update.component.html b/client/src/app/videos/video-edit/video-update.component.html new file mode 100644 index 000000000..665a952d0 --- /dev/null +++ b/client/src/app/videos/video-edit/video-update.component.html | |||
@@ -0,0 +1,101 @@ | |||
1 | <h3>Update {{ video.name }}</h3> | ||
2 | |||
3 | <div *ngIf="error" class="alert alert-danger">{{ error }}</div> | ||
4 | |||
5 | <form novalidate [formGroup]="form"> | ||
6 | <div class="form-group"> | ||
7 | <label for="name">Name</label> | ||
8 | <input | ||
9 | type="text" class="form-control" id="name" | ||
10 | formControlName="name" | ||
11 | > | ||
12 | <div *ngIf="formErrors.name" class="alert alert-danger"> | ||
13 | {{ formErrors.name }} | ||
14 | </div> | ||
15 | </div> | ||
16 | |||
17 | <div class="form-group"> | ||
18 | <label for="nsfw">NSFW</label> | ||
19 | <input | ||
20 | type="checkbox" id="nsfw" | ||
21 | formControlName="nsfw" | ||
22 | > | ||
23 | </div> | ||
24 | |||
25 | <div class="form-group"> | ||
26 | <label for="category">Category</label> | ||
27 | <select class="form-control" id="category" formControlName="category"> | ||
28 | <option></option> | ||
29 | <option *ngFor="let category of videoCategories" [value]="category.id">{{ category.label }}</option> | ||
30 | </select> | ||
31 | |||
32 | <div *ngIf="formErrors.category" class="alert alert-danger"> | ||
33 | {{ formErrors.category }} | ||
34 | </div> | ||
35 | </div> | ||
36 | |||
37 | <div class="form-group"> | ||
38 | <label for="licence">Licence</label> | ||
39 | <select class="form-control" id="licence" formControlName="licence"> | ||
40 | <option></option> | ||
41 | <option *ngFor="let licence of videoLicences" [value]="licence.id">{{ licence.label }}</option> | ||
42 | </select> | ||
43 | |||
44 | <div *ngIf="formErrors.licence" class="alert alert-danger"> | ||
45 | {{ formErrors.licence }} | ||
46 | </div> | ||
47 | </div> | ||
48 | |||
49 | <div class="form-group"> | ||
50 | <label for="language">Language</label> | ||
51 | <select class="form-control" id="language" formControlName="language"> | ||
52 | <option></option> | ||
53 | <option *ngFor="let language of videoLanguages" [value]="language.id">{{ language.label }}</option> | ||
54 | </select> | ||
55 | |||
56 | <div *ngIf="formErrors.language" class="alert alert-danger"> | ||
57 | {{ formErrors.language }} | ||
58 | </div> | ||
59 | </div> | ||
60 | |||
61 | <div class="form-group"> | ||
62 | <label for="tags">Tags</label> <span class="little-information">(press enter to add the tag)</span> | ||
63 | <input | ||
64 | type="text" class="form-control" id="currentTag" | ||
65 | formControlName="currentTag" (keyup)="onTagKeyPress($event)" | ||
66 | > | ||
67 | <div *ngIf="formErrors.currentTag" class="alert alert-danger"> | ||
68 | {{ formErrors.currentTag }} | ||
69 | </div> | ||
70 | </div> | ||
71 | |||
72 | <div class="tags"> | ||
73 | <div class="label label-primary tag" *ngFor="let tag of tags"> | ||
74 | {{ tag }} | ||
75 | <span class="remove" (click)="removeTag(tag)">x</span> | ||
76 | </div> | ||
77 | </div> | ||
78 | |||
79 | <div *ngIf="tagsError" class="alert alert-danger"> | ||
80 | {{ tagsError }} | ||
81 | </div> | ||
82 | |||
83 | <div class="form-group"> | ||
84 | <label for="description">Description</label> | ||
85 | <textarea | ||
86 | id="description" class="form-control" placeholder="Description..." | ||
87 | formControlName="description" | ||
88 | > | ||
89 | </textarea> | ||
90 | <div *ngIf="formErrors.description" class="alert alert-danger"> | ||
91 | {{ formErrors.description }} | ||
92 | </div> | ||
93 | </div> | ||
94 | |||
95 | <div class="form-group"> | ||
96 | <input | ||
97 | type="button" value="Update" class="btn btn-default form-control" | ||
98 | (click)="update()" | ||
99 | > | ||
100 | </div> | ||
101 | </form> | ||
diff --git a/client/src/app/videos/video-edit/video-update.component.ts b/client/src/app/videos/video-edit/video-update.component.ts new file mode 100644 index 000000000..b45780a41 --- /dev/null +++ b/client/src/app/videos/video-edit/video-update.component.ts | |||
@@ -0,0 +1,170 @@ | |||
1 | import { Component, ElementRef, OnInit } from '@angular/core'; | ||
2 | import { FormBuilder, FormGroup } from '@angular/forms'; | ||
3 | import { ActivatedRoute, Router } from '@angular/router'; | ||
4 | |||
5 | import { FileUploader } from 'ng2-file-upload/ng2-file-upload'; | ||
6 | import { NotificationsService } from 'angular2-notifications'; | ||
7 | |||
8 | import { AuthService } from '../../core'; | ||
9 | import { | ||
10 | FormReactive, | ||
11 | VIDEO_NAME, | ||
12 | VIDEO_CATEGORY, | ||
13 | VIDEO_LICENCE, | ||
14 | VIDEO_LANGUAGE, | ||
15 | VIDEO_DESCRIPTION, | ||
16 | VIDEO_TAGS | ||
17 | } from '../../shared'; | ||
18 | import { Video, VideoService } from '../shared'; | ||
19 | |||
20 | @Component({ | ||
21 | selector: 'my-videos-update', | ||
22 | styleUrls: [ './video-edit.component.scss' ], | ||
23 | templateUrl: './video-update.component.html' | ||
24 | }) | ||
25 | |||
26 | export class VideoUpdateComponent extends FormReactive implements OnInit { | ||
27 | tags: string[] = []; | ||
28 | videoCategories = []; | ||
29 | videoLicences = []; | ||
30 | videoLanguages = []; | ||
31 | video: Video; | ||
32 | |||
33 | error: string = null; | ||
34 | form: FormGroup; | ||
35 | formErrors = { | ||
36 | name: '', | ||
37 | category: '', | ||
38 | licence: '', | ||
39 | language: '', | ||
40 | description: '', | ||
41 | currentTag: '' | ||
42 | }; | ||
43 | validationMessages = { | ||
44 | name: VIDEO_NAME.MESSAGES, | ||
45 | category: VIDEO_CATEGORY.MESSAGES, | ||
46 | licence: VIDEO_LICENCE.MESSAGES, | ||
47 | language: VIDEO_LANGUAGE.MESSAGES, | ||
48 | description: VIDEO_DESCRIPTION.MESSAGES, | ||
49 | currentTag: VIDEO_TAGS.MESSAGES | ||
50 | }; | ||
51 | |||
52 | // Special error messages | ||
53 | tagsError = ''; | ||
54 | fileError = ''; | ||
55 | |||
56 | constructor( | ||
57 | private authService: AuthService, | ||
58 | private elementRef: ElementRef, | ||
59 | private formBuilder: FormBuilder, | ||
60 | private route: ActivatedRoute, | ||
61 | private router: Router, | ||
62 | private notificationsService: NotificationsService, | ||
63 | private videoService: VideoService | ||
64 | ) { | ||
65 | super(); | ||
66 | } | ||
67 | |||
68 | buildForm() { | ||
69 | this.form = this.formBuilder.group({ | ||
70 | name: [ '', VIDEO_NAME.VALIDATORS ], | ||
71 | nsfw: [ false ], | ||
72 | category: [ '', VIDEO_CATEGORY.VALIDATORS ], | ||
73 | licence: [ '', VIDEO_LICENCE.VALIDATORS ], | ||
74 | language: [ '', VIDEO_LANGUAGE.VALIDATORS ], | ||
75 | description: [ '', VIDEO_DESCRIPTION.VALIDATORS ], | ||
76 | currentTag: [ '', VIDEO_TAGS.VALIDATORS ] | ||
77 | }); | ||
78 | |||
79 | this.form.valueChanges.subscribe(data => this.onValueChanged(data)); | ||
80 | } | ||
81 | |||
82 | ngOnInit() { | ||
83 | this.buildForm(); | ||
84 | |||
85 | this.videoCategories = this.videoService.videoCategories; | ||
86 | this.videoLicences = this.videoService.videoLicences; | ||
87 | this.videoLanguages = this.videoService.videoLanguages; | ||
88 | |||
89 | const id = this.route.snapshot.params['id']; | ||
90 | this.videoService.getVideo(id) | ||
91 | .subscribe( | ||
92 | video => { | ||
93 | this.video = video; | ||
94 | |||
95 | this.hydrateFormFromVideo(); | ||
96 | }, | ||
97 | |||
98 | err => this.error = 'Cannot fetch video.' | ||
99 | ); | ||
100 | } | ||
101 | |||
102 | checkForm() { | ||
103 | this.forceCheck(); | ||
104 | |||
105 | return this.form.valid === true && this.tagsError === '' && this.fileError === ''; | ||
106 | } | ||
107 | |||
108 | |||
109 | onTagKeyPress(event: KeyboardEvent) { | ||
110 | // Enter press | ||
111 | if (event.keyCode === 13) { | ||
112 | this.addTagIfPossible(); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | removeTag(tag: string) { | ||
117 | this.tags.splice(this.tags.indexOf(tag), 1); | ||
118 | this.form.get('currentTag').enable(); | ||
119 | } | ||
120 | |||
121 | update() { | ||
122 | // Maybe the user forgot to press "enter" when he filled the field | ||
123 | this.addTagIfPossible(); | ||
124 | |||
125 | if (this.checkForm() === false) { | ||
126 | return; | ||
127 | } | ||
128 | |||
129 | this.video.patch(this.form.value); | ||
130 | |||
131 | this.videoService.updateVideo(this.video) | ||
132 | .subscribe( | ||
133 | () => { | ||
134 | this.notificationsService.success('Success', 'Video updated.'); | ||
135 | this.router.navigate([ '/videos/watch', this.video.id ]); | ||
136 | }, | ||
137 | |||
138 | err => { | ||
139 | this.error = 'Cannot update the video.'; | ||
140 | console.error(err); | ||
141 | } | ||
142 | ); | ||
143 | |||
144 | } | ||
145 | |||
146 | private addTagIfPossible() { | ||
147 | const currentTag = this.form.value['currentTag']; | ||
148 | if (currentTag === undefined) return; | ||
149 | |||
150 | // Check if the tag is valid and does not already exist | ||
151 | if ( | ||
152 | currentTag.length >= 2 && | ||
153 | this.form.controls['currentTag'].valid && | ||
154 | this.tags.indexOf(currentTag) === -1 | ||
155 | ) { | ||
156 | this.tags.push(currentTag); | ||
157 | this.form.patchValue({ currentTag: '' }); | ||
158 | |||
159 | if (this.tags.length >= 3) { | ||
160 | this.form.get('currentTag').disable(); | ||
161 | } | ||
162 | |||
163 | this.tagsError = ''; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | private hydrateFormFromVideo() { | ||
168 | this.form.patchValue(this.video.toJSON()); | ||
169 | } | ||
170 | } | ||