From 6de36768980ef6063b8fcd730b59fa685dd2b99c Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 16 Feb 2018 16:35:32 +0100 Subject: Add ability to update thumbnail and preview on client --- .../src/app/+admin/follows/follows.component.html | 2 - client/src/app/core/server/server.service.ts | 4 + .../src/app/shared/forms/form-validators/video.ts | 5 + .../shared/forms/markdown-textarea.component.html | 2 +- client/src/app/shared/misc/utils.ts | 24 ++- client/src/app/shared/shared.module.ts | 5 +- client/src/app/shared/video/video-edit.model.ts | 6 + .../shared/video/video-thumbnail.component.html | 2 +- client/src/app/shared/video/video.service.ts | 17 +- .../+video-edit/shared/video-edit.component.html | 224 ++++++++++++--------- .../+video-edit/shared/video-edit.component.scss | 12 ++ .../+video-edit/shared/video-edit.component.ts | 7 + .../videos/+video-edit/shared/video-edit.module.ts | 4 +- .../videos/+video-edit/video-update.component.ts | 26 ++- .../videos/+video-watch/video-watch.component.html | 2 +- .../videos/+video-watch/video-watch.component.ts | 6 + 16 files changed, 230 insertions(+), 118 deletions(-) (limited to 'client/src/app') diff --git a/client/src/app/+admin/follows/follows.component.html b/client/src/app/+admin/follows/follows.component.html index 1baba5a4d..d3d748622 100644 --- a/client/src/app/+admin/follows/follows.component.html +++ b/client/src/app/+admin/follows/follows.component.html @@ -10,6 +10,4 @@ - - diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts index 65714fd05..553ad8af6 100644 --- a/client/src/app/core/server/server.service.ts +++ b/client/src/app/core/server/server.service.ts @@ -35,6 +35,10 @@ export class ServerService { } }, video: { + image: { + size: { max: 0 }, + extensions: [] + }, file: { extensions: [] } diff --git a/client/src/app/shared/forms/form-validators/video.ts b/client/src/app/shared/forms/form-validators/video.ts index 500b5bc5f..34a237a12 100644 --- a/client/src/app/shared/forms/form-validators/video.ts +++ b/client/src/app/shared/forms/form-validators/video.ts @@ -31,6 +31,11 @@ export const VIDEO_LANGUAGE = { MESSAGES: {} } +export const VIDEO_IMAGE = { + VALIDATORS: [ ], + MESSAGES: {} +} + export const VIDEO_CHANNEL = { VALIDATORS: [ Validators.required ], MESSAGES: { diff --git a/client/src/app/shared/forms/markdown-textarea.component.html b/client/src/app/shared/forms/markdown-textarea.component.html index d2d4cf95c..e8c5ded5b 100644 --- a/client/src/app/shared/forms/markdown-textarea.component.html +++ b/client/src/app/shared/forms/markdown-textarea.component.html @@ -5,7 +5,7 @@ id="description" name="description"> - + diff --git a/client/src/app/shared/misc/utils.ts b/client/src/app/shared/misc/utils.ts index e6a697098..e2e4c5b36 100644 --- a/client/src/app/shared/misc/utils.ts +++ b/client/src/app/shared/misc/utils.ts @@ -67,6 +67,27 @@ function isInMobileView () { return window.innerWidth < 500 } +// Thanks: https://gist.github.com/ghinda/8442a57f22099bdb2e34 +function objectToFormData (obj: any, form?: FormData, namespace?: string) { + let fd = form || new FormData() + let formKey + + for (let key of Object.keys(obj)) { + if (namespace) formKey = `${namespace}[${key}]` + else formKey = key + + if (obj[key] === undefined) continue + + if (typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) { + objectToFormData(obj[ key ], fd, key) + } else { + fd.append(formKey, obj[ key ]) + } + } + + return fd +} + export { viewportHeight, getParameterByName, @@ -75,5 +96,6 @@ export { dateToHuman, isInSmallView, isInMobileView, - immutableAssign + immutableAssign, + objectToFormData } diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index 330a0ba84..2a9426479 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -40,10 +40,10 @@ import { VideoService } from './video/video.service' BsDropdownModule.forRoot(), ModalModule.forRoot(), + TabsModule.forRoot(), PrimeSharedModule, - NgPipesModule, - TabsModule.forRoot() + NgPipesModule ], declarations: [ @@ -69,6 +69,7 @@ import { VideoService } from './video/video.service' BsDropdownModule, ModalModule, + TabsModule, PrimeSharedModule, BytesPipe, KeysPipe, diff --git a/client/src/app/shared/video/video-edit.model.ts b/client/src/app/shared/video/video-edit.model.ts index b1c772217..c39252f46 100644 --- a/client/src/app/shared/video/video-edit.model.ts +++ b/client/src/app/shared/video/video-edit.model.ts @@ -12,6 +12,10 @@ export class VideoEdit { commentsEnabled: boolean channel: number privacy: VideoPrivacy + thumbnailfile?: any + previewfile?: any + thumbnailUrl: string + previewUrl: string uuid?: string id?: number @@ -29,6 +33,8 @@ export class VideoEdit { this.commentsEnabled = videoDetails.commentsEnabled this.channel = videoDetails.channel.id this.privacy = videoDetails.privacy + this.thumbnailUrl = videoDetails.thumbnailUrl + this.previewUrl = videoDetails.previewUrl } } diff --git a/client/src/app/shared/video/video-thumbnail.component.html b/client/src/app/shared/video/video-thumbnail.component.html index 8acfb3c41..4604d10e2 100644 --- a/client/src/app/shared/video/video-thumbnail.component.html +++ b/client/src/app/shared/video/video-thumbnail.component.html @@ -2,7 +2,7 @@ [routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.name" class="video-thumbnail" > -video thumbnail +
{{ video.durationLabel }} diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts index 01d32176b..2e7138cd1 100644 --- a/client/src/app/shared/video/video.service.ts +++ b/client/src/app/shared/video/video.service.ts @@ -18,6 +18,7 @@ import { SortField } from './sort-field.type' import { VideoDetails } from './video-details.model' import { VideoEdit } from './video-edit.model' import { Video } from './video.model' +import { objectToFormData } from '@app/shared/misc/utils' @Injectable() export class VideoService { @@ -46,10 +47,10 @@ export class VideoService { } updateVideo (video: VideoEdit) { - const language = video.language || null - const licence = video.licence || null - const category = video.category || null - const description = video.description || null + const language = video.language || undefined + const licence = video.licence || undefined + const category = video.category || undefined + const description = video.description || undefined const body: VideoUpdate = { name: video.name, @@ -60,10 +61,14 @@ export class VideoService { privacy: video.privacy, tags: video.tags, nsfw: video.nsfw, - commentsEnabled: video.commentsEnabled + commentsEnabled: video.commentsEnabled, + thumbnailfile: video.thumbnailfile, + previewfile: video.previewfile } - return this.authHttp.put(VideoService.BASE_VIDEO_URL + video.id, body) + const data = objectToFormData(body) + + return this.authHttp.put(VideoService.BASE_VIDEO_URL + video.id, data) .map(this.restExtractor.extractDataBool) .catch(this.restExtractor.handleError) } 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 index d031825bd..899249778 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.html +++ b/client/src/app/videos/+video-edit/shared/video-edit.component.html @@ -1,109 +1,133 @@
- -
-
- - -
- {{ formErrors.name }} -
-
- -
- (press Enter to add) - -
- -
- - - -
- {{ formErrors.description }} -
-
-
- -
-
- -
- -
-
- -
- -
- -
- -
- {{ formErrors.category }} -
-
- -
- -
- + + + +
+
+ + +
+ {{ formErrors.name }} +
+
+ +
+ (press Enter to add) + +
+ +
+ + + +
+ {{ formErrors.description }} +
+
-
- {{ formErrors.licence }} -
-
- -
- -
- -
+
+
+ +
+ +
+
+ +
+ +
+ +
+ +
+ {{ formErrors.category }} +
+
+ +
+ +
+ +
+ +
+ {{ formErrors.licence }} +
+
+ +
+ +
+ +
+ +
+ {{ formErrors.language }} +
+
+ +
+ +
+ +
+ +
+ {{ formErrors.privacy }} +
+
+ +
+ + + +
+ +
+ + + +
-
- {{ formErrors.language }}
-
- -
- -
- + + + +
+
+ +
+ +
+ +
+
-
- {{ formErrors.privacy }} -
-
- -
- - - -
- -
- - - -
+ -
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 index 1df9d4006..f78336fa8 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.scss +++ b/client/src/app/videos/+video-edit/shared/video-edit.component.scss @@ -47,6 +47,18 @@ .label-tags + span { font-size: 15px; } + + .root-tabset /deep/ > .nav { + margin-left: 15px; + margin-bottom: 15px; + + .nav-link { + display: flex !important; + align-items: center; + height: 30px !important; + padding: 0 15px !important; + } + } } .submit-container { 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 index 2b307d5fa..85e5cc3f5 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.ts +++ b/client/src/app/videos/+video-edit/shared/video-edit.component.ts @@ -1,6 +1,7 @@ import { Component, Input, OnInit } from '@angular/core' import { FormBuilder, FormControl, FormGroup } from '@angular/forms' import { ActivatedRoute, Router } from '@angular/router' +import { VIDEO_IMAGE } from '@app/shared' import { NotificationsService } from 'angular2-notifications' import 'rxjs/add/observable/forkJoin' import { ServerService } from '../../../core/server' @@ -57,6 +58,8 @@ export class VideoEditComponent implements OnInit { this.formErrors['licence'] = '' this.formErrors['language'] = '' this.formErrors['description'] = '' + this.formErrors['thumbnailfile'] = '' + this.formErrors['previewfile'] = '' this.validationMessages['name'] = VIDEO_NAME.MESSAGES this.validationMessages['privacy'] = VIDEO_PRIVACY.MESSAGES @@ -65,6 +68,8 @@ export class VideoEditComponent implements OnInit { this.validationMessages['licence'] = VIDEO_LICENCE.MESSAGES this.validationMessages['language'] = VIDEO_LANGUAGE.MESSAGES this.validationMessages['description'] = VIDEO_DESCRIPTION.MESSAGES + this.validationMessages['thumbnailfile'] = VIDEO_IMAGE.MESSAGES + this.validationMessages['previewfile'] = VIDEO_IMAGE.MESSAGES this.form.addControl('name', new FormControl('', VIDEO_NAME.VALIDATORS)) this.form.addControl('privacy', new FormControl('', VIDEO_PRIVACY.VALIDATORS)) @@ -76,6 +81,8 @@ export class VideoEditComponent implements OnInit { this.form.addControl('language', new FormControl('', VIDEO_LANGUAGE.VALIDATORS)) this.form.addControl('description', new FormControl('', VIDEO_DESCRIPTION.VALIDATORS)) this.form.addControl('tags', new FormControl('')) + this.form.addControl('thumbnailfile', new FormControl('')) + this.form.addControl('previewfile', new FormControl('')) } ngOnInit () { 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 index 098a71ae6..1b82281bf 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.module.ts +++ b/client/src/app/videos/+video-edit/shared/video-edit.module.ts @@ -1,4 +1,5 @@ import { NgModule } from '@angular/core' +import { VideoImageComponent } from '@app/videos/+video-edit/shared/video-image.component' import { TabsModule } from 'ngx-bootstrap/tabs' import { TagInputModule } from 'ngx-chips' import { SharedModule } from '../../../shared' @@ -12,7 +13,8 @@ import { VideoEditComponent } from './video-edit.component' ], declarations: [ - VideoEditComponent + VideoEditComponent, + VideoImageComponent ], exports: [ diff --git a/client/src/app/videos/+video-edit/video-update.component.ts b/client/src/app/videos/+video-edit/video-update.component.ts index 7f41b56d8..ad6452835 100644 --- a/client/src/app/videos/+video-edit/video-update.component.ts +++ b/client/src/app/videos/+video-edit/video-update.component.ts @@ -48,11 +48,10 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { this.buildForm() this.serverService.videoPrivaciesLoaded - .subscribe( - () => this.videoPrivacies = this.serverService.getVideoPrivacies() - ) + .subscribe(() => this.videoPrivacies = this.serverService.getVideoPrivacies()) populateAsyncUserVideoChannels(this.authService, this.userVideoChannels) + .catch(err => console.error('Cannot populate async user video channels.', err)) const uuid: string = this.route.snapshot.params['uuid'] this.videoService.getVideo(uuid) @@ -116,5 +115,26 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { private hydrateFormFromVideo () { this.form.patchValue(this.video.toJSON()) + + 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-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html index af90e22a1..8c173d6b3 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html @@ -1,7 +1,7 @@
- +
Video not found :'(
diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index 7a64406e6..7c97f0964 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts @@ -211,6 +211,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy { return Account.GET_ACCOUNT_AVATAR_URL(this.video.account) } + getVideoPoster () { + if (!this.video) return '' + + return this.video.previewUrl + } + getVideoTags () { if (!this.video || Array.isArray(this.video.tags) === false) return [] -- cgit v1.2.3