Add ability to update thumbnail and preview on client
This commit is contained in:
parent
b6a4fd6b09
commit
6de3676898
20 changed files with 274 additions and 137 deletions
|
@ -10,6 +10,4 @@
|
||||||
</tabset>
|
</tabset>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
|
|
|
@ -35,6 +35,10 @@ export class ServerService {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
video: {
|
video: {
|
||||||
|
image: {
|
||||||
|
size: { max: 0 },
|
||||||
|
extensions: []
|
||||||
|
},
|
||||||
file: {
|
file: {
|
||||||
extensions: []
|
extensions: []
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,11 @@ export const VIDEO_LANGUAGE = {
|
||||||
MESSAGES: {}
|
MESSAGES: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const VIDEO_IMAGE = {
|
||||||
|
VALIDATORS: [ ],
|
||||||
|
MESSAGES: {}
|
||||||
|
}
|
||||||
|
|
||||||
export const VIDEO_CHANNEL = {
|
export const VIDEO_CHANNEL = {
|
||||||
VALIDATORS: [ Validators.required ],
|
VALIDATORS: [ Validators.required ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
id="description" name="description">
|
id="description" name="description">
|
||||||
</textarea>
|
</textarea>
|
||||||
|
|
||||||
<tabset *ngIf="arePreviewsDisplayed()" #staticTabs class="previews">
|
<tabset *ngIf="arePreviewsDisplayed()" class="previews">
|
||||||
<tab *ngIf="truncate !== undefined" heading="Truncated description preview" [innerHTML]="truncatedDescriptionHTML"></tab>
|
<tab *ngIf="truncate !== undefined" heading="Truncated description preview" [innerHTML]="truncatedDescriptionHTML"></tab>
|
||||||
<tab heading="Complete description preview" [innerHTML]="descriptionHTML"></tab>
|
<tab heading="Complete description preview" [innerHTML]="descriptionHTML"></tab>
|
||||||
</tabset>
|
</tabset>
|
||||||
|
|
|
@ -67,6 +67,27 @@ function isInMobileView () {
|
||||||
return window.innerWidth < 500
|
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 {
|
export {
|
||||||
viewportHeight,
|
viewportHeight,
|
||||||
getParameterByName,
|
getParameterByName,
|
||||||
|
@ -75,5 +96,6 @@ export {
|
||||||
dateToHuman,
|
dateToHuman,
|
||||||
isInSmallView,
|
isInSmallView,
|
||||||
isInMobileView,
|
isInMobileView,
|
||||||
immutableAssign
|
immutableAssign,
|
||||||
|
objectToFormData
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,10 +40,10 @@ import { VideoService } from './video/video.service'
|
||||||
|
|
||||||
BsDropdownModule.forRoot(),
|
BsDropdownModule.forRoot(),
|
||||||
ModalModule.forRoot(),
|
ModalModule.forRoot(),
|
||||||
|
TabsModule.forRoot(),
|
||||||
|
|
||||||
PrimeSharedModule,
|
PrimeSharedModule,
|
||||||
NgPipesModule,
|
NgPipesModule
|
||||||
TabsModule.forRoot()
|
|
||||||
],
|
],
|
||||||
|
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -69,6 +69,7 @@ import { VideoService } from './video/video.service'
|
||||||
|
|
||||||
BsDropdownModule,
|
BsDropdownModule,
|
||||||
ModalModule,
|
ModalModule,
|
||||||
|
TabsModule,
|
||||||
PrimeSharedModule,
|
PrimeSharedModule,
|
||||||
BytesPipe,
|
BytesPipe,
|
||||||
KeysPipe,
|
KeysPipe,
|
||||||
|
|
|
@ -12,6 +12,10 @@ export class VideoEdit {
|
||||||
commentsEnabled: boolean
|
commentsEnabled: boolean
|
||||||
channel: number
|
channel: number
|
||||||
privacy: VideoPrivacy
|
privacy: VideoPrivacy
|
||||||
|
thumbnailfile?: any
|
||||||
|
previewfile?: any
|
||||||
|
thumbnailUrl: string
|
||||||
|
previewUrl: string
|
||||||
uuid?: string
|
uuid?: string
|
||||||
id?: number
|
id?: number
|
||||||
|
|
||||||
|
@ -29,6 +33,8 @@ export class VideoEdit {
|
||||||
this.commentsEnabled = videoDetails.commentsEnabled
|
this.commentsEnabled = videoDetails.commentsEnabled
|
||||||
this.channel = videoDetails.channel.id
|
this.channel = videoDetails.channel.id
|
||||||
this.privacy = videoDetails.privacy
|
this.privacy = videoDetails.privacy
|
||||||
|
this.thumbnailUrl = videoDetails.thumbnailUrl
|
||||||
|
this.previewUrl = videoDetails.previewUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
[routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.name"
|
[routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.name"
|
||||||
class="video-thumbnail"
|
class="video-thumbnail"
|
||||||
>
|
>
|
||||||
<img [attr.src]="getImageUrl()" alt="video thumbnail" [ngClass]="{ 'blur-filter': nsfw }" />
|
<img [attr.src]="getImageUrl()" [ngClass]="{ 'blur-filter': nsfw }" />
|
||||||
|
|
||||||
<div class="video-thumbnail-overlay">
|
<div class="video-thumbnail-overlay">
|
||||||
{{ video.durationLabel }}
|
{{ video.durationLabel }}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { SortField } from './sort-field.type'
|
||||||
import { VideoDetails } from './video-details.model'
|
import { VideoDetails } from './video-details.model'
|
||||||
import { VideoEdit } from './video-edit.model'
|
import { VideoEdit } from './video-edit.model'
|
||||||
import { Video } from './video.model'
|
import { Video } from './video.model'
|
||||||
|
import { objectToFormData } from '@app/shared/misc/utils'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class VideoService {
|
export class VideoService {
|
||||||
|
@ -46,10 +47,10 @@ export class VideoService {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVideo (video: VideoEdit) {
|
updateVideo (video: VideoEdit) {
|
||||||
const language = video.language || null
|
const language = video.language || undefined
|
||||||
const licence = video.licence || null
|
const licence = video.licence || undefined
|
||||||
const category = video.category || null
|
const category = video.category || undefined
|
||||||
const description = video.description || null
|
const description = video.description || undefined
|
||||||
|
|
||||||
const body: VideoUpdate = {
|
const body: VideoUpdate = {
|
||||||
name: video.name,
|
name: video.name,
|
||||||
|
@ -60,10 +61,14 @@ export class VideoService {
|
||||||
privacy: video.privacy,
|
privacy: video.privacy,
|
||||||
tags: video.tags,
|
tags: video.tags,
|
||||||
nsfw: video.nsfw,
|
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)
|
.map(this.restExtractor.extractDataBool)
|
||||||
.catch(this.restExtractor.handleError)
|
.catch(this.restExtractor.handleError)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,109 +1,133 @@
|
||||||
<div class="video-edit row" [formGroup]="form">
|
<div class="video-edit row" [formGroup]="form">
|
||||||
|
<tabset class="root-tabset bootstrap">
|
||||||
|
|
||||||
<div class="col-md-8">
|
<tab heading="Basic info">
|
||||||
<div class="form-group">
|
<div class="col-md-8">
|
||||||
<label for="name">Title</label>
|
<div class="form-group">
|
||||||
<input type="text" id="name" formControlName="name" />
|
<label for="name">Title</label>
|
||||||
<div *ngIf="formErrors.name" class="form-error">
|
<input type="text" id="name" formControlName="name" />
|
||||||
{{ formErrors.name }}
|
<div *ngIf="formErrors.name" class="form-error">
|
||||||
</div>
|
{{ formErrors.name }}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="label-tags">Tags</label> <span>(press Enter to add)</span>
|
<label class="label-tags">Tags</label> <span>(press Enter to add)</span>
|
||||||
<tag-input
|
<tag-input
|
||||||
[ngModel]="tags" [validators]="tagValidators" [errorMessages]="tagValidatorsMessages"
|
[ngModel]="tags" [validators]="tagValidators" [errorMessages]="tagValidatorsMessages"
|
||||||
formControlName="tags" maxItems="5" modelAsStrings="true"
|
formControlName="tags" maxItems="5" modelAsStrings="true"
|
||||||
></tag-input>
|
></tag-input>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="description">Description</label>
|
<label for="description">Description</label>
|
||||||
<my-markdown-textarea truncate="250" formControlName="description"></my-markdown-textarea>
|
<my-markdown-textarea truncate="250" formControlName="description"></my-markdown-textarea>
|
||||||
|
|
||||||
<div *ngIf="formErrors.description" class="form-error">
|
<div *ngIf="formErrors.description" class="form-error">
|
||||||
{{ formErrors.description }}
|
{{ formErrors.description }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Channel</label>
|
|
||||||
<div class="peertube-select-disabled-container">
|
|
||||||
<select formControlName="channelId">
|
|
||||||
<option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="category">Category</label>
|
|
||||||
<div class="peertube-select-container">
|
|
||||||
<select id="category" formControlName="category">
|
|
||||||
<option></option>
|
|
||||||
<option *ngFor="let category of videoCategories" [value]="category.id">{{ category.label }}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="formErrors.category" class="form-error">
|
<div class="col-md-4">
|
||||||
{{ formErrors.category }}
|
<div class="form-group">
|
||||||
|
<label>Channel</label>
|
||||||
|
<div class="peertube-select-disabled-container">
|
||||||
|
<select formControlName="channelId">
|
||||||
|
<option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="category">Category</label>
|
||||||
|
<div class="peertube-select-container">
|
||||||
|
<select id="category" formControlName="category">
|
||||||
|
<option></option>
|
||||||
|
<option *ngFor="let category of videoCategories" [value]="category.id">{{ category.label }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="formErrors.category" class="form-error">
|
||||||
|
{{ formErrors.category }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="licence">Licence</label>
|
||||||
|
<div class="peertube-select-container">
|
||||||
|
<select id="licence" formControlName="licence">
|
||||||
|
<option></option>
|
||||||
|
<option *ngFor="let licence of videoLicences" [value]="licence.id">{{ licence.label }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="formErrors.licence" class="form-error">
|
||||||
|
{{ formErrors.licence }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="language">Language</label>
|
||||||
|
<div class="peertube-select-container">
|
||||||
|
<select id="language" formControlName="language">
|
||||||
|
<option></option>
|
||||||
|
<option *ngFor="let language of videoLanguages" [value]="language.id">{{ language.label }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="formErrors.language" class="form-error">
|
||||||
|
{{ formErrors.language }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="privacy">Privacy</label>
|
||||||
|
<div class="peertube-select-container">
|
||||||
|
<select id="privacy" formControlName="privacy">
|
||||||
|
<option></option>
|
||||||
|
<option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="formErrors.privacy" class="form-error">
|
||||||
|
{{ formErrors.privacy }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group form-group-checkbox">
|
||||||
|
<input type="checkbox" id="nsfw" formControlName="nsfw" />
|
||||||
|
<label for="nsfw"></label>
|
||||||
|
<label for="nsfw">This video contains mature or explicit content</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group form-group-checkbox">
|
||||||
|
<input type="checkbox" id="commentsEnabled" formControlName="commentsEnabled" />
|
||||||
|
<label for="commentsEnabled"></label>
|
||||||
|
<label for="commentsEnabled">Enable video comments</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</tab>
|
||||||
|
|
||||||
<div class="form-group">
|
<tab heading="Advanced settings">
|
||||||
<label for="licence">Licence</label>
|
<div class="col-md-12">
|
||||||
<div class="peertube-select-container">
|
<div class="form-group">
|
||||||
<select id="licence" formControlName="licence">
|
<my-video-image
|
||||||
<option></option>
|
inputLabel="Upload thumbnail" inputName="thumbnailfile" formControlName="thumbnailfile"
|
||||||
<option *ngFor="let licence of videoLicences" [value]="licence.id">{{ licence.label }}</option>
|
previewWidth="200px" previewHeight="110px"
|
||||||
</select>
|
></my-video-image>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<my-video-image
|
||||||
|
inputLabel="Upload preview" inputName="previewfile" formControlName="previewfile"
|
||||||
|
previewWidth="360px" previewHeight="200px"
|
||||||
|
></my-video-image>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</tab>
|
||||||
|
|
||||||
<div *ngIf="formErrors.licence" class="form-error">
|
</tabset>
|
||||||
{{ formErrors.licence }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="language">Language</label>
|
|
||||||
<div class="peertube-select-container">
|
|
||||||
<select id="language" formControlName="language">
|
|
||||||
<option></option>
|
|
||||||
<option *ngFor="let language of videoLanguages" [value]="language.id">{{ language.label }}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div *ngIf="formErrors.language" class="form-error">
|
|
||||||
{{ formErrors.language }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="privacy">Privacy</label>
|
|
||||||
<div class="peertube-select-container">
|
|
||||||
<select id="privacy" formControlName="privacy">
|
|
||||||
<option></option>
|
|
||||||
<option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div *ngIf="formErrors.privacy" class="form-error">
|
|
||||||
{{ formErrors.privacy }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group form-group-checkbox">
|
|
||||||
<input type="checkbox" id="nsfw" formControlName="nsfw" />
|
|
||||||
<label for="nsfw"></label>
|
|
||||||
<label for="nsfw">This video contains mature or explicit content</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group form-group-checkbox">
|
|
||||||
<input type="checkbox" id="commentsEnabled" formControlName="commentsEnabled" />
|
|
||||||
<label for="commentsEnabled"></label>
|
|
||||||
<label for="commentsEnabled">Enable video comments</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -47,6 +47,18 @@
|
||||||
.label-tags + span {
|
.label-tags + span {
|
||||||
font-size: 15px;
|
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 {
|
.submit-container {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Component, Input, OnInit } from '@angular/core'
|
import { Component, Input, OnInit } from '@angular/core'
|
||||||
import { FormBuilder, FormControl, FormGroup } from '@angular/forms'
|
import { FormBuilder, FormControl, FormGroup } from '@angular/forms'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
|
import { VIDEO_IMAGE } from '@app/shared'
|
||||||
import { NotificationsService } from 'angular2-notifications'
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
import 'rxjs/add/observable/forkJoin'
|
import 'rxjs/add/observable/forkJoin'
|
||||||
import { ServerService } from '../../../core/server'
|
import { ServerService } from '../../../core/server'
|
||||||
|
@ -57,6 +58,8 @@ export class VideoEditComponent implements OnInit {
|
||||||
this.formErrors['licence'] = ''
|
this.formErrors['licence'] = ''
|
||||||
this.formErrors['language'] = ''
|
this.formErrors['language'] = ''
|
||||||
this.formErrors['description'] = ''
|
this.formErrors['description'] = ''
|
||||||
|
this.formErrors['thumbnailfile'] = ''
|
||||||
|
this.formErrors['previewfile'] = ''
|
||||||
|
|
||||||
this.validationMessages['name'] = VIDEO_NAME.MESSAGES
|
this.validationMessages['name'] = VIDEO_NAME.MESSAGES
|
||||||
this.validationMessages['privacy'] = VIDEO_PRIVACY.MESSAGES
|
this.validationMessages['privacy'] = VIDEO_PRIVACY.MESSAGES
|
||||||
|
@ -65,6 +68,8 @@ export class VideoEditComponent implements OnInit {
|
||||||
this.validationMessages['licence'] = VIDEO_LICENCE.MESSAGES
|
this.validationMessages['licence'] = VIDEO_LICENCE.MESSAGES
|
||||||
this.validationMessages['language'] = VIDEO_LANGUAGE.MESSAGES
|
this.validationMessages['language'] = VIDEO_LANGUAGE.MESSAGES
|
||||||
this.validationMessages['description'] = VIDEO_DESCRIPTION.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('name', new FormControl('', VIDEO_NAME.VALIDATORS))
|
||||||
this.form.addControl('privacy', new FormControl('', VIDEO_PRIVACY.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('language', new FormControl('', VIDEO_LANGUAGE.VALIDATORS))
|
||||||
this.form.addControl('description', new FormControl('', VIDEO_DESCRIPTION.VALIDATORS))
|
this.form.addControl('description', new FormControl('', VIDEO_DESCRIPTION.VALIDATORS))
|
||||||
this.form.addControl('tags', new FormControl(''))
|
this.form.addControl('tags', new FormControl(''))
|
||||||
|
this.form.addControl('thumbnailfile', new FormControl(''))
|
||||||
|
this.form.addControl('previewfile', new FormControl(''))
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { NgModule } from '@angular/core'
|
import { NgModule } from '@angular/core'
|
||||||
|
import { VideoImageComponent } from '@app/videos/+video-edit/shared/video-image.component'
|
||||||
import { TabsModule } from 'ngx-bootstrap/tabs'
|
import { TabsModule } from 'ngx-bootstrap/tabs'
|
||||||
import { TagInputModule } from 'ngx-chips'
|
import { TagInputModule } from 'ngx-chips'
|
||||||
import { SharedModule } from '../../../shared'
|
import { SharedModule } from '../../../shared'
|
||||||
|
@ -12,7 +13,8 @@ import { VideoEditComponent } from './video-edit.component'
|
||||||
],
|
],
|
||||||
|
|
||||||
declarations: [
|
declarations: [
|
||||||
VideoEditComponent
|
VideoEditComponent,
|
||||||
|
VideoImageComponent
|
||||||
],
|
],
|
||||||
|
|
||||||
exports: [
|
exports: [
|
||||||
|
|
|
@ -48,11 +48,10 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
|
||||||
this.buildForm()
|
this.buildForm()
|
||||||
|
|
||||||
this.serverService.videoPrivaciesLoaded
|
this.serverService.videoPrivaciesLoaded
|
||||||
.subscribe(
|
.subscribe(() => this.videoPrivacies = this.serverService.getVideoPrivacies())
|
||||||
() => this.videoPrivacies = this.serverService.getVideoPrivacies()
|
|
||||||
)
|
|
||||||
|
|
||||||
populateAsyncUserVideoChannels(this.authService, this.userVideoChannels)
|
populateAsyncUserVideoChannels(this.authService, this.userVideoChannels)
|
||||||
|
.catch(err => console.error('Cannot populate async user video channels.', err))
|
||||||
|
|
||||||
const uuid: string = this.route.snapshot.params['uuid']
|
const uuid: string = this.route.snapshot.params['uuid']
|
||||||
this.videoService.getVideo(uuid)
|
this.videoService.getVideo(uuid)
|
||||||
|
@ -116,5 +115,26 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
|
||||||
|
|
||||||
private hydrateFormFromVideo () {
|
private hydrateFormFromVideo () {
|
||||||
this.form.patchValue(this.video.toJSON())
|
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
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- We need the video container for videojs so we just hide it -->
|
<!-- We need the video container for videojs so we just hide it -->
|
||||||
<div [hidden]="videoNotFound" id="video-container">
|
<div [hidden]="videoNotFound" id="video-container">
|
||||||
<video id="video-element" class="video-js vjs-peertube-skin"></video>
|
<video [poster]="getVideoPoster()" id="video-element" class="video-js vjs-peertube-skin"></video>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="videoNotFound" id="video-not-found">Video not found :'(</div>
|
<div *ngIf="videoNotFound" id="video-not-found">Video not found :'(</div>
|
||||||
|
|
|
@ -211,6 +211,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
return Account.GET_ACCOUNT_AVATAR_URL(this.video.account)
|
return Account.GET_ACCOUNT_AVATAR_URL(this.video.account)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getVideoPoster () {
|
||||||
|
if (!this.video) return ''
|
||||||
|
|
||||||
|
return this.video.previewUrl
|
||||||
|
}
|
||||||
|
|
||||||
getVideoTags () {
|
getVideoTags () {
|
||||||
if (!this.video || Array.isArray(this.video.tags) === false) return []
|
if (!this.video || Array.isArray(this.video.tags) === false) return []
|
||||||
|
|
||||||
|
|
|
@ -299,35 +299,46 @@ p-datatable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav {
|
tabset:not(.bootstrap) {
|
||||||
font-size: 16px !important;
|
.nav {
|
||||||
border: none !important;
|
font-size: 16px !important;
|
||||||
|
|
||||||
.nav-item .nav-link {
|
|
||||||
margin-right: 30px;
|
|
||||||
padding: 0;
|
|
||||||
border-radius: 3px;
|
|
||||||
border: none !important;
|
border: none !important;
|
||||||
|
|
||||||
.tab-link {
|
.nav-item .nav-link {
|
||||||
display: flex !important;
|
margin-right: 30px;
|
||||||
align-items: center;
|
padding: 0;
|
||||||
min-height: 30px !important;
|
border-radius: 3px;
|
||||||
padding: 0 15px;
|
border: none !important;
|
||||||
}
|
|
||||||
|
|
||||||
|
.tab-link {
|
||||||
|
display: flex !important;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 30px !important;
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&, & a {
|
||||||
|
color: #000 !important;
|
||||||
|
@include disable-default-a-behaviour;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active, &:hover {
|
||||||
|
background-color: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
font-weight: $font-semibold !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tabset.bootstrap {
|
||||||
|
.nav-item .nav-link {
|
||||||
&, & a {
|
&, & a {
|
||||||
color: #000 !important;
|
color: #000;
|
||||||
@include disable-default-a-behaviour;
|
@include disable-default-a-behaviour;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active, &:hover {
|
|
||||||
background-color: #F0F0F0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
font-weight: $font-semibold !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,12 @@ async function getConfig (req: express.Request, res: express.Response, next: exp
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
video: {
|
video: {
|
||||||
|
image: {
|
||||||
|
extensions: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME,
|
||||||
|
size: {
|
||||||
|
max: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max
|
||||||
|
}
|
||||||
|
},
|
||||||
file: {
|
file: {
|
||||||
extensions: CONSTRAINTS_FIELDS.VIDEOS.EXTNAME
|
extensions: CONSTRAINTS_FIELDS.VIDEOS.EXTNAME
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,12 @@ export interface ServerConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
video: {
|
video: {
|
||||||
|
image: {
|
||||||
|
size: {
|
||||||
|
max: number
|
||||||
|
}
|
||||||
|
extensions: string[]
|
||||||
|
},
|
||||||
file: {
|
file: {
|
||||||
extensions: string[]
|
extensions: string[]
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,4 +11,6 @@ export interface VideoUpdate {
|
||||||
tags?: string[]
|
tags?: string[]
|
||||||
commentsEnabled?: boolean
|
commentsEnabled?: boolean
|
||||||
nsfw?: boolean
|
nsfw?: boolean
|
||||||
|
thumbnailfile?: Blob
|
||||||
|
previewfile?: Blob
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue