From d8e689b864749648d03cf4391fd4a475126f01cd Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 10 Apr 2017 21:15:28 +0200 Subject: Client: add basic support for updating a video --- client/src/app/videos/index.ts | 2 +- client/src/app/videos/shared/video.model.ts | 38 ++++ client/src/app/videos/shared/video.service.ts | 19 +- client/src/app/videos/video-add/index.ts | 1 - .../app/videos/video-add/video-add.component.html | 128 ------------ .../app/videos/video-add/video-add.component.scss | 57 ----- .../app/videos/video-add/video-add.component.ts | 230 --------------------- client/src/app/videos/video-edit/index.ts | 2 + .../app/videos/video-edit/video-add.component.html | 128 ++++++++++++ .../app/videos/video-edit/video-add.component.ts | 230 +++++++++++++++++++++ .../videos/video-edit/video-edit.component.scss | 57 +++++ .../videos/video-edit/video-update.component.html | 101 +++++++++ .../videos/video-edit/video-update.component.ts | 170 +++++++++++++++ .../videos/video-watch/video-watch.component.html | 6 + .../videos/video-watch/video-watch.component.ts | 5 + client/src/app/videos/videos-routing.module.ts | 11 +- client/src/app/videos/videos.module.ts | 3 +- 17 files changed, 768 insertions(+), 420 deletions(-) delete mode 100644 client/src/app/videos/video-add/index.ts delete mode 100644 client/src/app/videos/video-add/video-add.component.html delete mode 100644 client/src/app/videos/video-add/video-add.component.scss delete mode 100644 client/src/app/videos/video-add/video-add.component.ts create mode 100644 client/src/app/videos/video-edit/index.ts create mode 100644 client/src/app/videos/video-edit/video-add.component.html create mode 100644 client/src/app/videos/video-edit/video-add.component.ts create mode 100644 client/src/app/videos/video-edit/video-edit.component.scss create mode 100644 client/src/app/videos/video-edit/video-update.component.html create mode 100644 client/src/app/videos/video-edit/video-update.component.ts diff --git a/client/src/app/videos/index.ts b/client/src/app/videos/index.ts index ca386a51d..5158a23f8 100644 --- a/client/src/app/videos/index.ts +++ b/client/src/app/videos/index.ts @@ -1,5 +1,5 @@ export * from './shared'; -export * from './video-add'; +export * from './video-edit'; export * from './video-list'; export * from './video-watch'; export * from './videos-routing.module'; diff --git a/client/src/app/videos/shared/video.model.ts b/client/src/app/videos/shared/video.model.ts index f135ca707..404e3bf45 100644 --- a/client/src/app/videos/shared/video.model.ts +++ b/client/src/app/videos/shared/video.model.ts @@ -5,8 +5,11 @@ export class Video { by: string; createdAt: Date; categoryLabel: string; + category: string; licenceLabel: string; + licence: string; languageLabel: string; + language: string; description: string; duration: string; id: string; @@ -38,8 +41,11 @@ export class Video { author: string, createdAt: string, categoryLabel: string, + category: string, licenceLabel: string, + licence: string, languageLabel: string; + language: string; description: string, duration: number; id: string, @@ -57,8 +63,11 @@ export class Video { this.author = hash.author; this.createdAt = new Date(hash.createdAt); this.categoryLabel = hash.categoryLabel; + this.category = hash.category; this.licenceLabel = hash.licenceLabel; + this.licence = hash.licence; this.languageLabel = hash.languageLabel; + this.language = hash.language; this.description = hash.description; this.duration = Video.createDurationString(hash.duration); this.id = hash.id; @@ -84,4 +93,33 @@ export class Video { // If the video is NSFW and the user is not logged in, or the user does not want to display NSFW videos... return (this.nsfw && (!user || user.displayNSFW === false)); } + + patch(values: Object) { + Object.keys(values).forEach((key) => { + this[key] = values[key]; + }); + } + + toJSON() { + return { + author: this.author, + createdAt: this.createdAt, + category: this.category, + licence: this.licence, + language: this.language, + description: this.description, + duration: this.duration, + id: this.id, + isLocal: this.isLocal, + magnetUri: this.magnetUri, + name: this.name, + podHost: this.podHost, + tags: this.tags, + thumbnailPath: this.thumbnailPath, + views: this.views, + likes: this.likes, + dislikes: this.dislikes, + nsfw: this.nsfw + }; + } } diff --git a/client/src/app/videos/shared/video.service.ts b/client/src/app/videos/shared/video.service.ts index 13d4ca246..ee67bc1ae 100644 --- a/client/src/app/videos/shared/video.service.ts +++ b/client/src/app/videos/shared/video.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { Http } from '@angular/http'; +import { Http, Headers, RequestOptions } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/map'; @@ -80,6 +80,23 @@ export class VideoService { .catch((res) => this.restExtractor.handleError(res)); } + updateVideo(video: Video) { + const body = { + name: video.name, + category: video.category, + licence: video.licence, + language: video.language, + description: video.description, + tags: video.tags + }; + const headers = new Headers({ 'Content-Type': 'application/json' }); + const options = new RequestOptions({ headers: headers }); + + return this.authHttp.put(`${VideoService.BASE_VIDEO_URL}/${video.id}`, body, options) + .map(this.restExtractor.extractDataBool) + .catch(this.restExtractor.handleError); + } + getVideos(pagination: RestPagination, sort: SortField) { const params = this.restService.buildRestGetParams(pagination, sort); diff --git a/client/src/app/videos/video-add/index.ts b/client/src/app/videos/video-add/index.ts deleted file mode 100644 index 79488e851..000000000 --- a/client/src/app/videos/video-add/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './video-add.component'; diff --git a/client/src/app/videos/video-add/video-add.component.html b/client/src/app/videos/video-add/video-add.component.html deleted file mode 100644 index 104747a8c..000000000 --- a/client/src/app/videos/video-add/video-add.component.html +++ /dev/null @@ -1,128 +0,0 @@ -

Upload a video

- -
{{ error }}
- -
-
- - -
- {{ formErrors.name }} -
-
- -
- - -
- -
- - - -
- {{ formErrors.category }} -
-
- -
- - - -
- {{ formErrors.licence }} -
-
- -
- - - -
- {{ formErrors.language }} -
-
- -
- (press enter to add the tag) - -
- {{ formErrors.currentTag }} -
-
- -
-
- {{ tag }} - x -
-
- -
- {{ tagsError }} -
- -
- -
- Select the video... - -
-
- -
-
- {{ filename }} - -
-
- -
- {{ fileError }} -
- -
- - -
- {{ formErrors.description }} -
-
- -
- -
- -
- -
-
diff --git a/client/src/app/videos/video-add/video-add.component.scss b/client/src/app/videos/video-add/video-add.component.scss deleted file mode 100644 index 11ee3297e..000000000 --- a/client/src/app/videos/video-add/video-add.component.scss +++ /dev/null @@ -1,57 +0,0 @@ -.btn-file { - position: relative; - overflow: hidden; - display: block; -} - -.btn-file input[type=file] { - position: absolute; - top: 0; - right: 0; - min-width: 100%; - min-height: 100%; - font-size: 100px; - text-align: right; - filter: alpha(opacity=0); - opacity: 0; - outline: none; - background: white; - cursor: inherit; - display: block; -} - -.name_file { - display: inline-block; - margin-left: 10px; -} - -.form-group { - margin-bottom: 10px; -} - -div.tags { - height: 40px; - font-size: 20px; - margin-top: 20px; - - .tag { - margin-right: 10px; - - .remove { - cursor: pointer; - } - } -} - -div.file-to-upload { - height: 40px; - - .glyphicon-remove { - cursor: pointer; - } -} - -.little-information { - font-size: 0.8em; - font-style: italic; -} diff --git a/client/src/app/videos/video-add/video-add.component.ts b/client/src/app/videos/video-add/video-add.component.ts deleted file mode 100644 index da556f48d..000000000 --- a/client/src/app/videos/video-add/video-add.component.ts +++ /dev/null @@ -1,230 +0,0 @@ -import { Component, ElementRef, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup } from '@angular/forms'; -import { Router } from '@angular/router'; - -import { FileUploader } from 'ng2-file-upload/ng2-file-upload'; -import { NotificationsService } from 'angular2-notifications'; - -import { AuthService } from '../../core'; -import { - FormReactive, - VIDEO_NAME, - VIDEO_CATEGORY, - VIDEO_LICENCE, - VIDEO_LANGUAGE, - VIDEO_DESCRIPTION, - VIDEO_TAGS -} from '../../shared'; -import { VideoService } from '../shared'; - -@Component({ - selector: 'my-videos-add', - styleUrls: [ './video-add.component.scss' ], - templateUrl: './video-add.component.html' -}) - -export class VideoAddComponent extends FormReactive implements OnInit { - tags: string[] = []; - uploader: FileUploader; - videoCategories = []; - videoLicences = []; - videoLanguages = []; - - error: string = null; - form: FormGroup; - formErrors = { - name: '', - category: '', - licence: '', - language: '', - description: '', - currentTag: '' - }; - validationMessages = { - name: VIDEO_NAME.MESSAGES, - category: VIDEO_CATEGORY.MESSAGES, - licence: VIDEO_LICENCE.MESSAGES, - language: VIDEO_LANGUAGE.MESSAGES, - description: VIDEO_DESCRIPTION.MESSAGES, - currentTag: VIDEO_TAGS.MESSAGES - }; - - // Special error messages - tagsError = ''; - fileError = ''; - - constructor( - private authService: AuthService, - private elementRef: ElementRef, - private formBuilder: FormBuilder, - private router: Router, - private notificationsService: NotificationsService, - private videoService: VideoService - ) { - super(); - } - - get filename() { - if (this.uploader.queue.length === 0) { - return null; - } - - return this.uploader.queue[0].file.name; - } - - buildForm() { - this.form = this.formBuilder.group({ - name: [ '', VIDEO_NAME.VALIDATORS ], - nsfw: [ false ], - category: [ '', VIDEO_CATEGORY.VALIDATORS ], - licence: [ '', VIDEO_LICENCE.VALIDATORS ], - language: [ '', VIDEO_LANGUAGE.VALIDATORS ], - description: [ '', VIDEO_DESCRIPTION.VALIDATORS ], - currentTag: [ '', VIDEO_TAGS.VALIDATORS ] - }); - - this.form.valueChanges.subscribe(data => this.onValueChanged(data)); - } - - ngOnInit() { - this.videoCategories = this.videoService.videoCategories; - this.videoLicences = this.videoService.videoLicences; - this.videoLanguages = this.videoService.videoLanguages; - - this.uploader = new FileUploader({ - authToken: this.authService.getRequestHeaderValue(), - queueLimit: 1, - url: '/api/v1/videos', - removeAfterUpload: true - }); - - this.uploader.onBuildItemForm = (item, form) => { - const name = this.form.value['name']; - const nsfw = this.form.value['nsfw']; - const category = this.form.value['category']; - const licence = this.form.value['licence']; - const language = this.form.value['language']; - const description = this.form.value['description']; - - form.append('name', name); - form.append('category', category); - form.append('nsfw', nsfw); - form.append('licence', licence); - - // Language is optional - if (language) { - form.append('language', language); - } - - form.append('description', description); - - for (let i = 0; i < this.tags.length; i++) { - form.append(`tags[${i}]`, this.tags[i]); - } - }; - - this.buildForm(); - } - - checkForm() { - this.forceCheck(); - - if (this.filename === null) { - this.fileError = 'You did not add a file.'; - } - - return this.form.valid === true && this.tagsError === '' && this.fileError === ''; - } - - fileChanged() { - this.fileError = ''; - } - - onTagKeyPress(event: KeyboardEvent) { - // Enter press - if (event.keyCode === 13) { - this.addTagIfPossible(); - } - } - - removeFile() { - this.uploader.clearQueue(); - } - - removeTag(tag: string) { - this.tags.splice(this.tags.indexOf(tag), 1); - this.form.get('currentTag').enable(); - } - - upload() { - // Maybe the user forgot to press "enter" when he filled the field - this.addTagIfPossible(); - - if (this.checkForm() === false) { - return; - } - - const item = this.uploader.queue[0]; - // TODO: wait for https://github.com/valor-software/ng2-file-upload/pull/242 - item.alias = 'videofile'; - - // FIXME: remove - // Run detection change for progress bar - const interval = setInterval(() => { ; }, 250); - - item.onSuccess = () => { - clearInterval(interval); - - console.log('Video uploaded.'); - this.notificationsService.success('Success', 'Video uploaded.'); - - - // Print all the videos once it's finished - this.router.navigate(['/videos/list']); - }; - - item.onError = (response: string, status: number) => { - clearInterval(interval); - - // We need to handle manually these cases beceause we use the FileUpload component - if (status === 400) { - this.error = response; - } else if (status === 401) { - this.error = 'Access token was expired, refreshing token...'; - this.authService.refreshAccessToken().subscribe( - () => { - // Update the uploader request header - this.uploader.authToken = this.authService.getRequestHeaderValue(); - this.error += ' access token refreshed. Please retry your request.'; - } - ); - } else { - this.error = 'Unknow error'; - console.error(this.error); - } - }; - - this.uploader.uploadAll(); - } - - private addTagIfPossible() { - const currentTag = this.form.value['currentTag']; - if (currentTag === undefined) return; - - // Check if the tag is valid and does not already exist - if ( - currentTag.length >= 2 && - this.form.controls['currentTag'].valid && - this.tags.indexOf(currentTag) === -1 - ) { - this.tags.push(currentTag); - this.form.patchValue({ currentTag: '' }); - - if (this.tags.length >= 3) { - this.form.get('currentTag').disable(); - } - - this.tagsError = ''; - } - } -} 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 @@ +export * from './video-add.component'; +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 @@ +

Upload a video

+ +
{{ error }}
+ +
+
+ + +
+ {{ formErrors.name }} +
+
+ +
+ + +
+ +
+ + + +
+ {{ formErrors.category }} +
+
+ +
+ + + +
+ {{ formErrors.licence }} +
+
+ +
+ + + +
+ {{ formErrors.language }} +
+
+ +
+ (press enter to add the tag) + +
+ {{ formErrors.currentTag }} +
+
+ +
+
+ {{ tag }} + x +
+
+ +
+ {{ tagsError }} +
+ +
+ +
+ Select the video... + +
+
+ +
+
+ {{ filename }} + +
+
+ +
+ {{ fileError }} +
+ +
+ + +
+ {{ formErrors.description }} +
+
+ +
+ +
+ +
+ +
+
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 @@ +import { Component, ElementRef, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { Router } from '@angular/router'; + +import { FileUploader } from 'ng2-file-upload/ng2-file-upload'; +import { NotificationsService } from 'angular2-notifications'; + +import { AuthService } from '../../core'; +import { + FormReactive, + VIDEO_NAME, + VIDEO_CATEGORY, + VIDEO_LICENCE, + VIDEO_LANGUAGE, + VIDEO_DESCRIPTION, + VIDEO_TAGS +} from '../../shared'; +import { VideoService } from '../shared'; + +@Component({ + selector: 'my-videos-add', + styleUrls: [ './video-edit.component.scss' ], + templateUrl: './video-add.component.html' +}) + +export class VideoAddComponent extends FormReactive implements OnInit { + tags: string[] = []; + uploader: FileUploader; + videoCategories = []; + videoLicences = []; + videoLanguages = []; + + error: string = null; + form: FormGroup; + formErrors = { + name: '', + category: '', + licence: '', + language: '', + description: '', + currentTag: '' + }; + validationMessages = { + name: VIDEO_NAME.MESSAGES, + category: VIDEO_CATEGORY.MESSAGES, + licence: VIDEO_LICENCE.MESSAGES, + language: VIDEO_LANGUAGE.MESSAGES, + description: VIDEO_DESCRIPTION.MESSAGES, + currentTag: VIDEO_TAGS.MESSAGES + }; + + // Special error messages + tagsError = ''; + fileError = ''; + + constructor( + private authService: AuthService, + private elementRef: ElementRef, + private formBuilder: FormBuilder, + private router: Router, + private notificationsService: NotificationsService, + private videoService: VideoService + ) { + super(); + } + + get filename() { + if (this.uploader.queue.length === 0) { + return null; + } + + return this.uploader.queue[0].file.name; + } + + buildForm() { + this.form = this.formBuilder.group({ + name: [ '', VIDEO_NAME.VALIDATORS ], + nsfw: [ false ], + category: [ '', VIDEO_CATEGORY.VALIDATORS ], + licence: [ '', VIDEO_LICENCE.VALIDATORS ], + language: [ '', VIDEO_LANGUAGE.VALIDATORS ], + description: [ '', VIDEO_DESCRIPTION.VALIDATORS ], + currentTag: [ '', VIDEO_TAGS.VALIDATORS ] + }); + + this.form.valueChanges.subscribe(data => this.onValueChanged(data)); + } + + ngOnInit() { + this.videoCategories = this.videoService.videoCategories; + this.videoLicences = this.videoService.videoLicences; + this.videoLanguages = this.videoService.videoLanguages; + + this.uploader = new FileUploader({ + authToken: this.authService.getRequestHeaderValue(), + queueLimit: 1, + url: '/api/v1/videos', + removeAfterUpload: true + }); + + this.uploader.onBuildItemForm = (item, form) => { + const name = this.form.value['name']; + const nsfw = this.form.value['nsfw']; + const category = this.form.value['category']; + const licence = this.form.value['licence']; + const language = this.form.value['language']; + const description = this.form.value['description']; + + form.append('name', name); + form.append('category', category); + form.append('nsfw', nsfw); + form.append('licence', licence); + + // Language is optional + if (language) { + form.append('language', language); + } + + form.append('description', description); + + for (let i = 0; i < this.tags.length; i++) { + form.append(`tags[${i}]`, this.tags[i]); + } + }; + + this.buildForm(); + } + + checkForm() { + this.forceCheck(); + + if (this.filename === null) { + this.fileError = 'You did not add a file.'; + } + + return this.form.valid === true && this.tagsError === '' && this.fileError === ''; + } + + fileChanged() { + this.fileError = ''; + } + + onTagKeyPress(event: KeyboardEvent) { + // Enter press + if (event.keyCode === 13) { + this.addTagIfPossible(); + } + } + + removeFile() { + this.uploader.clearQueue(); + } + + removeTag(tag: string) { + this.tags.splice(this.tags.indexOf(tag), 1); + this.form.get('currentTag').enable(); + } + + upload() { + // Maybe the user forgot to press "enter" when he filled the field + this.addTagIfPossible(); + + if (this.checkForm() === false) { + return; + } + + const item = this.uploader.queue[0]; + // TODO: wait for https://github.com/valor-software/ng2-file-upload/pull/242 + item.alias = 'videofile'; + + // FIXME: remove + // Run detection change for progress bar + const interval = setInterval(() => { ; }, 250); + + item.onSuccess = () => { + clearInterval(interval); + + console.log('Video uploaded.'); + this.notificationsService.success('Success', 'Video uploaded.'); + + + // Print all the videos once it's finished + this.router.navigate(['/videos/list']); + }; + + item.onError = (response: string, status: number) => { + clearInterval(interval); + + // We need to handle manually these cases beceause we use the FileUpload component + if (status === 400) { + this.error = response; + } else if (status === 401) { + this.error = 'Access token was expired, refreshing token...'; + this.authService.refreshAccessToken().subscribe( + () => { + // Update the uploader request header + this.uploader.authToken = this.authService.getRequestHeaderValue(); + this.error += ' access token refreshed. Please retry your request.'; + } + ); + } else { + this.error = 'Unknow error'; + console.error(this.error); + } + }; + + this.uploader.uploadAll(); + } + + private addTagIfPossible() { + const currentTag = this.form.value['currentTag']; + if (currentTag === undefined) return; + + // Check if the tag is valid and does not already exist + if ( + currentTag.length >= 2 && + this.form.controls['currentTag'].valid && + this.tags.indexOf(currentTag) === -1 + ) { + this.tags.push(currentTag); + this.form.patchValue({ currentTag: '' }); + + if (this.tags.length >= 3) { + this.form.get('currentTag').disable(); + } + + this.tagsError = ''; + } + } +} 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 @@ +.btn-file { + position: relative; + overflow: hidden; + display: block; +} + +.btn-file input[type=file] { + position: absolute; + top: 0; + right: 0; + min-width: 100%; + min-height: 100%; + font-size: 100px; + text-align: right; + filter: alpha(opacity=0); + opacity: 0; + outline: none; + background: white; + cursor: inherit; + display: block; +} + +.name_file { + display: inline-block; + margin-left: 10px; +} + +.form-group { + margin-bottom: 10px; +} + +div.tags { + height: 40px; + font-size: 20px; + margin-top: 20px; + + .tag { + margin-right: 10px; + + .remove { + cursor: pointer; + } + } +} + +div.file-to-upload { + height: 40px; + + .glyphicon-remove { + cursor: pointer; + } +} + +.little-information { + font-size: 0.8em; + font-style: italic; +} 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 @@ +

Update {{ video.name }}

+ +
{{ error }}
+ +
+
+ + +
+ {{ formErrors.name }} +
+
+ +
+ + +
+ +
+ + + +
+ {{ formErrors.category }} +
+
+ +
+ + + +
+ {{ formErrors.licence }} +
+
+ +
+ + + +
+ {{ formErrors.language }} +
+
+ +
+ (press enter to add the tag) + +
+ {{ formErrors.currentTag }} +
+
+ +
+
+ {{ tag }} + x +
+
+ +
+ {{ tagsError }} +
+ +
+ + +
+ {{ formErrors.description }} +
+
+ +
+ +
+
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 @@ +import { Component, ElementRef, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; + +import { FileUploader } from 'ng2-file-upload/ng2-file-upload'; +import { NotificationsService } from 'angular2-notifications'; + +import { AuthService } from '../../core'; +import { + FormReactive, + VIDEO_NAME, + VIDEO_CATEGORY, + VIDEO_LICENCE, + VIDEO_LANGUAGE, + VIDEO_DESCRIPTION, + VIDEO_TAGS +} from '../../shared'; +import { Video, VideoService } from '../shared'; + +@Component({ + selector: 'my-videos-update', + styleUrls: [ './video-edit.component.scss' ], + templateUrl: './video-update.component.html' +}) + +export class VideoUpdateComponent extends FormReactive implements OnInit { + tags: string[] = []; + videoCategories = []; + videoLicences = []; + videoLanguages = []; + video: Video; + + error: string = null; + form: FormGroup; + formErrors = { + name: '', + category: '', + licence: '', + language: '', + description: '', + currentTag: '' + }; + validationMessages = { + name: VIDEO_NAME.MESSAGES, + category: VIDEO_CATEGORY.MESSAGES, + licence: VIDEO_LICENCE.MESSAGES, + language: VIDEO_LANGUAGE.MESSAGES, + description: VIDEO_DESCRIPTION.MESSAGES, + currentTag: VIDEO_TAGS.MESSAGES + }; + + // Special error messages + tagsError = ''; + fileError = ''; + + constructor( + private authService: AuthService, + private elementRef: ElementRef, + private formBuilder: FormBuilder, + private route: ActivatedRoute, + private router: Router, + private notificationsService: NotificationsService, + private videoService: VideoService + ) { + super(); + } + + buildForm() { + this.form = this.formBuilder.group({ + name: [ '', VIDEO_NAME.VALIDATORS ], + nsfw: [ false ], + category: [ '', VIDEO_CATEGORY.VALIDATORS ], + licence: [ '', VIDEO_LICENCE.VALIDATORS ], + language: [ '', VIDEO_LANGUAGE.VALIDATORS ], + description: [ '', VIDEO_DESCRIPTION.VALIDATORS ], + currentTag: [ '', VIDEO_TAGS.VALIDATORS ] + }); + + this.form.valueChanges.subscribe(data => this.onValueChanged(data)); + } + + ngOnInit() { + this.buildForm(); + + this.videoCategories = this.videoService.videoCategories; + this.videoLicences = this.videoService.videoLicences; + this.videoLanguages = this.videoService.videoLanguages; + + const id = this.route.snapshot.params['id']; + this.videoService.getVideo(id) + .subscribe( + video => { + this.video = video; + + this.hydrateFormFromVideo(); + }, + + err => this.error = 'Cannot fetch video.' + ); + } + + checkForm() { + this.forceCheck(); + + return this.form.valid === true && this.tagsError === '' && this.fileError === ''; + } + + + onTagKeyPress(event: KeyboardEvent) { + // Enter press + if (event.keyCode === 13) { + this.addTagIfPossible(); + } + } + + removeTag(tag: string) { + this.tags.splice(this.tags.indexOf(tag), 1); + this.form.get('currentTag').enable(); + } + + update() { + // Maybe the user forgot to press "enter" when he filled the field + this.addTagIfPossible(); + + if (this.checkForm() === false) { + return; + } + + this.video.patch(this.form.value); + + this.videoService.updateVideo(this.video) + .subscribe( + () => { + this.notificationsService.success('Success', 'Video updated.'); + this.router.navigate([ '/videos/watch', this.video.id ]); + }, + + err => { + this.error = 'Cannot update the video.'; + console.error(err); + } + ); + + } + + private addTagIfPossible() { + const currentTag = this.form.value['currentTag']; + if (currentTag === undefined) return; + + // Check if the tag is valid and does not already exist + if ( + currentTag.length >= 2 && + this.form.controls['currentTag'].valid && + this.tags.indexOf(currentTag) === -1 + ) { + this.tags.push(currentTag); + this.form.patchValue({ currentTag: '' }); + + if (this.tags.length >= 3) { + this.form.get('currentTag').disable(); + } + + this.tagsError = ''; + } + } + + private hydrateFormFromVideo() { + this.form.patchValue(this.video.toJSON()); + } +} diff --git a/client/src/app/videos/video-watch/video-watch.component.html b/client/src/app/videos/video-watch/video-watch.component.html index a6ec7b20f..2a6b15dc9 100644 --- a/client/src/app/videos/video-watch/video-watch.component.html +++ b/client/src/app/videos/video-watch/video-watch.component.html @@ -79,6 +79,12 @@