Design second video upload step
This commit is contained in:
parent
c182778e26
commit
cadb46d832
|
@ -194,7 +194,6 @@ export class AuthService {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mergeUserInformation(obj)
|
this.mergeUserInformation(obj)
|
||||||
.do(() => this.userInformationLoaded.next(true))
|
|
||||||
.subscribe(
|
.subscribe(
|
||||||
res => {
|
res => {
|
||||||
this.user.displayNSFW = res.displayNSFW
|
this.user.displayNSFW = res.displayNSFW
|
||||||
|
@ -203,6 +202,8 @@ export class AuthService {
|
||||||
this.user.account = res.account
|
this.user.account = res.account
|
||||||
|
|
||||||
this.user.save()
|
this.user.save()
|
||||||
|
|
||||||
|
this.userInformationLoaded.next(true)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,6 @@ export class ServerService {
|
||||||
notifier: ReplaySubject<boolean>
|
notifier: ReplaySubject<boolean>
|
||||||
) {
|
) {
|
||||||
return this.http.get(ServerService.BASE_VIDEO_URL + attributeName)
|
return this.http.get(ServerService.BASE_VIDEO_URL + attributeName)
|
||||||
.do(() => notifier.next(true))
|
|
||||||
.subscribe(data => {
|
.subscribe(data => {
|
||||||
Object.keys(data)
|
Object.keys(data)
|
||||||
.forEach(dataKey => {
|
.forEach(dataKey => {
|
||||||
|
@ -86,6 +85,8 @@ export class ServerService {
|
||||||
label: data[dataKey]
|
label: data[dataKey]
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
notifier.next(true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,10 @@ menu {
|
||||||
.logged-in-email {
|
.logged-in-email {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #C6C6C6;
|
color: #C6C6C6;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-width: 140px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,17 +23,13 @@ export const VIDEO_PRIVACY = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const VIDEO_CATEGORY = {
|
export const VIDEO_CATEGORY = {
|
||||||
VALIDATORS: [ Validators.required ],
|
VALIDATORS: [ ],
|
||||||
MESSAGES: {
|
MESSAGES: {}
|
||||||
'required': 'Video category is required.'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const VIDEO_LICENCE = {
|
export const VIDEO_LICENCE = {
|
||||||
VALIDATORS: [ Validators.required ],
|
VALIDATORS: [ ],
|
||||||
MESSAGES: {
|
MESSAGES: {}
|
||||||
'required': 'Video licence is required.'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const VIDEO_LANGUAGE = {
|
export const VIDEO_LANGUAGE = {
|
||||||
|
@ -49,9 +45,8 @@ export const VIDEO_CHANNEL = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const VIDEO_DESCRIPTION = {
|
export const VIDEO_DESCRIPTION = {
|
||||||
VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(3000) ],
|
VALIDATORS: [ Validators.minLength(3), Validators.maxLength(3000) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': 'Video description is required.',
|
|
||||||
'minlength': 'Video description must be at least 3 characters long.',
|
'minlength': 'Video description must be at least 3 characters long.',
|
||||||
'maxlength': 'Video description cannot be more than 3000 characters long.'
|
'maxlength': 'Video description cannot be more than 3000 characters long.'
|
||||||
}
|
}
|
||||||
|
@ -64,10 +59,3 @@ export const VIDEO_TAGS = {
|
||||||
'maxlength': 'A tag should be less than 30 characters long.'
|
'maxlength': 'A tag should be less than 30 characters long.'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const VIDEO_FILE = {
|
|
||||||
VALIDATORS: [ Validators.required ],
|
|
||||||
MESSAGES: {
|
|
||||||
'required': 'Video file is required.'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,18 +14,20 @@ export class VideoEdit {
|
||||||
uuid?: string
|
uuid?: string
|
||||||
id?: number
|
id?: number
|
||||||
|
|
||||||
constructor (videoDetails: VideoDetails) {
|
constructor (videoDetails?: VideoDetails) {
|
||||||
this.id = videoDetails.id
|
if (videoDetails) {
|
||||||
this.uuid = videoDetails.uuid
|
this.id = videoDetails.id
|
||||||
this.category = videoDetails.category
|
this.uuid = videoDetails.uuid
|
||||||
this.licence = videoDetails.licence
|
this.category = videoDetails.category
|
||||||
this.language = videoDetails.language
|
this.licence = videoDetails.licence
|
||||||
this.description = videoDetails.description
|
this.language = videoDetails.language
|
||||||
this.name = videoDetails.name
|
this.description = videoDetails.description
|
||||||
this.tags = videoDetails.tags
|
this.name = videoDetails.name
|
||||||
this.nsfw = videoDetails.nsfw
|
this.tags = videoDetails.tags
|
||||||
this.channel = videoDetails.channel.id
|
this.nsfw = videoDetails.nsfw
|
||||||
this.privacy = videoDetails.privacy
|
this.channel = videoDetails.channel.id
|
||||||
|
this.privacy = videoDetails.privacy
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
patch (values: Object) {
|
patch (values: Object) {
|
||||||
|
|
|
@ -42,14 +42,17 @@ export class VideoService {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVideo (video: VideoEdit) {
|
updateVideo (video: VideoEdit) {
|
||||||
const language = video.language ? video.language : null
|
const language = video.language || undefined
|
||||||
|
const licence = video.licence || undefined
|
||||||
|
const category = video.category || undefined
|
||||||
|
const description = video.description || undefined
|
||||||
|
|
||||||
const body: VideoUpdate = {
|
const body: VideoUpdate = {
|
||||||
name: video.name,
|
name: video.name,
|
||||||
category: video.category,
|
category,
|
||||||
licence: video.licence,
|
licence,
|
||||||
language,
|
language,
|
||||||
description: video.description,
|
description,
|
||||||
privacy: video.privacy,
|
privacy: video.privacy,
|
||||||
tags: video.tags,
|
tags: video.tags,
|
||||||
nsfw: video.nsfw
|
nsfw: video.nsfw
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
textarea {
|
||||||
|
@include peertube-input-text(100%);
|
||||||
|
|
||||||
|
padding: 5px 15px;
|
||||||
|
font-size: 15px;
|
||||||
|
height: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.previews /deep/ {
|
||||||
|
font-size: 15px !important;
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 16px !important;
|
||||||
|
border: none !important;
|
||||||
|
|
||||||
|
.nav-item .nav-link {
|
||||||
|
color: #000 !important;
|
||||||
|
height: 30px !important;
|
||||||
|
margin-right: 30px;
|
||||||
|
padding: 0 15px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: none !important;
|
||||||
|
|
||||||
|
&.active, &:hover {
|
||||||
|
background-color: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
font-weight: $font-semibold !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
min-height: 75px;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,10 @@
|
||||||
import { Component, forwardRef, Input, OnInit } from '@angular/core'
|
import { Component, forwardRef, Input, OnInit } from '@angular/core'
|
||||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
|
||||||
import { Subject } from 'rxjs/Subject'
|
import { truncate } from 'lodash'
|
||||||
import 'rxjs/add/operator/debounceTime'
|
import 'rxjs/add/operator/debounceTime'
|
||||||
import 'rxjs/add/operator/distinctUntilChanged'
|
import 'rxjs/add/operator/distinctUntilChanged'
|
||||||
|
import { Subject } from 'rxjs/Subject'
|
||||||
import { truncate } from 'lodash'
|
import { MarkdownService } from '../../shared'
|
||||||
|
|
||||||
import { MarkdownService } from './markdown.service'
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-video-description',
|
selector: 'my-video-description',
|
|
@ -43,6 +43,14 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
bottom: $button-height;
|
bottom: $button-height;
|
||||||
|
|
||||||
|
.message-submit {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 25px;
|
||||||
|
|
||||||
|
color: #585858;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.submit-button {
|
.submit-button {
|
||||||
@include peertube-button;
|
@include peertube-button;
|
||||||
@include orange-button;
|
@include orange-button;
|
||||||
|
@ -54,6 +62,7 @@
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
outline: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon.icon-validate {
|
.icon.icon-validate {
|
||||||
|
|
|
@ -3,8 +3,9 @@ import { NgModule } from '@angular/core'
|
||||||
import { TagInputModule } from 'ngx-chips'
|
import { TagInputModule } from 'ngx-chips'
|
||||||
import { TabsModule } from 'ngx-bootstrap/tabs'
|
import { TabsModule } from 'ngx-bootstrap/tabs'
|
||||||
|
|
||||||
import { MarkdownService, VideoDescriptionComponent } from '../../shared'
|
import { MarkdownService } from '../../shared'
|
||||||
import { SharedModule } from '../../../shared'
|
import { SharedModule } from '../../../shared'
|
||||||
|
import { VideoDescriptionComponent } from './video-description.component'
|
||||||
import { VideoEditComponent } from './video-edit.component'
|
import { VideoEditComponent } from './video-edit.component'
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
|
@ -15,20 +15,23 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<select [(ngModel)]="firstStepPrivacy">
|
<select [(ngModel)]="firstStepPrivacyId">
|
||||||
<option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option>
|
<option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<select [(ngModel)]="firstStepChannel">
|
<select [(ngModel)]="firstStepChannelId">
|
||||||
<option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option>
|
<option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p-progressBar *ngIf="isUploadingVideo" [value]="videoUploadPercents"></p-progressBar>
|
<p-progressBar
|
||||||
|
*ngIf="isUploadingVideo" [value]="videoUploadPercents"
|
||||||
|
[ngClass]="{ processing: videoUploadPercents === 100 && videoUploaded === false }"
|
||||||
|
></p-progressBar>
|
||||||
|
|
||||||
<!-- Hidden because we need to load the component -->
|
<!-- Hidden because we need to load the component -->
|
||||||
<form [hidden]="!isUploadingVideo" novalidate [formGroup]="form">
|
<form [hidden]="!isUploadingVideo" novalidate [formGroup]="form">
|
||||||
|
@ -37,10 +40,13 @@
|
||||||
[validationMessages]="validationMessages" [videoPrivacies]="videoPrivacies"
|
[validationMessages]="validationMessages" [videoPrivacies]="videoPrivacies"
|
||||||
></my-video-edit>
|
></my-video-edit>
|
||||||
|
|
||||||
|
|
||||||
<div class="submit-container">
|
<div class="submit-container">
|
||||||
<div class="submit-button" [ngClass]="{ disabled: !form.valid }">
|
<div *ngIf="videoUploaded === false" class="message-submit">Publish will be available when upload is finished</div>
|
||||||
|
|
||||||
|
<div class="submit-button" (click)="updateSecondStep()" [ngClass]="{ disabled: !form.valid || videoUploaded !== true }">
|
||||||
<span class="icon icon-validate"></span>
|
<span class="icon icon-validate"></span>
|
||||||
<input type="button" value="Publish" (click)="upload()" />
|
<input type="button" value="Publish" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
.icon.icon-upload {
|
.icon.icon-upload {
|
||||||
@include icon(90px);
|
@include icon(90px);
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
|
cursor: default;
|
||||||
|
|
||||||
background-image: url('../../../assets/images/video/upload.svg');
|
background-image: url('../../../assets/images/video/upload.svg');
|
||||||
}
|
}
|
||||||
|
@ -58,10 +59,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
p-progressBar {
|
p-progressBar {
|
||||||
margin-top: 50px;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
|
|
||||||
/deep/ .ui-progressbar {
|
/deep/ .ui-progressbar {
|
||||||
|
margin-top: 25px !important;
|
||||||
|
margin-bottom: 40px !important;
|
||||||
font-size: 15px !important;
|
font-size: 15px !important;
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
height: 30px !important;
|
height: 30px !important;
|
||||||
|
@ -76,6 +76,19 @@ p-progressBar {
|
||||||
.ui-progressbar-label {
|
.ui-progressbar-label {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding-left: 18px;
|
padding-left: 18px;
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.processing {
|
||||||
|
/deep/ .ui-progressbar-label {
|
||||||
|
// Same color as background to hide "100%"
|
||||||
|
color: rgba(11, 204, 41, 0.16) !important;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: 'Processing...';
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { Router } from '@angular/router'
|
||||||
import { NotificationsService } from 'angular2-notifications'
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
import { VideoService } from 'app/shared/video/video.service'
|
import { VideoService } from 'app/shared/video/video.service'
|
||||||
import { VideoCreate } from '../../../../../shared'
|
import { VideoCreate } from '../../../../../shared'
|
||||||
|
import { VideoPrivacy } from '../../../../../shared/models/videos'
|
||||||
import { AuthService, ServerService } from '../../core'
|
import { AuthService, ServerService } from '../../core'
|
||||||
import { FormReactive } from '../../shared'
|
import { FormReactive } from '../../shared'
|
||||||
import { ValidatorMessage } from '../../shared/forms/form-validators'
|
import { ValidatorMessage } from '../../shared/forms/form-validators'
|
||||||
|
@ -25,6 +26,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
|
||||||
isUploadingVideo = false
|
isUploadingVideo = false
|
||||||
videoUploaded = false
|
videoUploaded = false
|
||||||
videoUploadPercents = 0
|
videoUploadPercents = 0
|
||||||
|
videoUploadedId = 0
|
||||||
|
|
||||||
error: string = null
|
error: string = null
|
||||||
form: FormGroup
|
form: FormGroup
|
||||||
|
@ -33,8 +35,8 @@ export class VideoAddComponent extends FormReactive implements OnInit {
|
||||||
|
|
||||||
userVideoChannels = []
|
userVideoChannels = []
|
||||||
videoPrivacies = []
|
videoPrivacies = []
|
||||||
firstStepPrivacy = 0
|
firstStepPrivacyId = 0
|
||||||
firstStepChannel = 0
|
firstStepChannelId = 0
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
|
@ -59,7 +61,9 @@ export class VideoAddComponent extends FormReactive implements OnInit {
|
||||||
.subscribe(
|
.subscribe(
|
||||||
() => {
|
() => {
|
||||||
this.videoPrivacies = this.serverService.getVideoPrivacies()
|
this.videoPrivacies = this.serverService.getVideoPrivacies()
|
||||||
this.firstStepPrivacy = this.videoPrivacies[0].id
|
|
||||||
|
// Public by default
|
||||||
|
this.firstStepPrivacyId = VideoPrivacy.PUBLIC
|
||||||
})
|
})
|
||||||
|
|
||||||
this.authService.userInformationLoaded
|
this.authService.userInformationLoaded
|
||||||
|
@ -72,7 +76,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
|
||||||
if (Array.isArray(videoChannels) === false) return
|
if (Array.isArray(videoChannels) === false) return
|
||||||
|
|
||||||
this.userVideoChannels = videoChannels.map(v => ({ id: v.id, label: v.name }))
|
this.userVideoChannels = videoChannels.map(v => ({ id: v.id, label: v.name }))
|
||||||
this.firstStepChannel = this.userVideoChannels[0].id
|
this.firstStepChannelId = this.userVideoChannels[0].id
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -89,14 +93,15 @@ export class VideoAddComponent extends FormReactive implements OnInit {
|
||||||
|
|
||||||
uploadFirstStep () {
|
uploadFirstStep () {
|
||||||
const videofile = this.videofileInput.nativeElement.files[0]
|
const videofile = this.videofileInput.nativeElement.files[0]
|
||||||
const name = videofile.name
|
const name = videofile.name.replace(/\.[^/.]+$/, '')
|
||||||
const privacy = this.firstStepPrivacy.toString()
|
const privacy = this.firstStepPrivacyId.toString()
|
||||||
const nsfw = false
|
const nsfw = false
|
||||||
const channelId = this.firstStepChannel.toString()
|
const channelId = this.firstStepChannelId.toString()
|
||||||
|
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('name', name)
|
formData.append('name', name)
|
||||||
formData.append('privacy', privacy.toString())
|
// Put the video "private" -> we wait he validates the second step
|
||||||
|
formData.append('privacy', VideoPrivacy.PRIVATE.toString())
|
||||||
formData.append('nsfw', '' + nsfw)
|
formData.append('nsfw', '' + nsfw)
|
||||||
formData.append('channelId', '' + channelId)
|
formData.append('channelId', '' + channelId)
|
||||||
formData.append('videofile', videofile)
|
formData.append('videofile', videofile)
|
||||||
|
@ -117,6 +122,8 @@ export class VideoAddComponent extends FormReactive implements OnInit {
|
||||||
console.log('Video uploaded.')
|
console.log('Video uploaded.')
|
||||||
|
|
||||||
this.videoUploaded = true
|
this.videoUploaded = true
|
||||||
|
|
||||||
|
this.videoUploadedId = event.body.video.id
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -133,13 +140,16 @@ export class VideoAddComponent extends FormReactive implements OnInit {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const video = new VideoEdit(this.form.value)
|
const video = new VideoEdit()
|
||||||
|
video.patch(this.form.value)
|
||||||
|
video.channel = this.firstStepChannelId
|
||||||
|
video.id = this.videoUploadedId
|
||||||
|
|
||||||
this.videoService.updateVideo(video)
|
this.videoService.updateVideo(video)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
() => {
|
() => {
|
||||||
this.notificationsService.success('Success', 'Video published.')
|
this.notificationsService.success('Success', 'Video published.')
|
||||||
this.router.navigate([ '/videos/watch', video.uuid ])
|
this.router.navigate([ '/videos/watch', video.id ])
|
||||||
},
|
},
|
||||||
|
|
||||||
err => {
|
err => {
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
></my-video-edit>
|
></my-video-edit>
|
||||||
|
|
||||||
<div class="submit-container">
|
<div class="submit-container">
|
||||||
<div class="submit-button" [ngClass]="{ disabled: !form.valid }">
|
<div class="submit-button" (click)="update()" [ngClass]="{ disabled: !form.valid }">
|
||||||
<span class="icon icon-validate"></span>
|
<span class="icon icon-validate"></span>
|
||||||
<input type="button" value="Update" (click)="update()" />
|
<input type="button" value="Update" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -78,7 +78,7 @@
|
||||||
<div class="video-info-description">
|
<div class="video-info-description">
|
||||||
<div class="video-info-description-html" [innerHTML]="videoHTMLDescription"></div>
|
<div class="video-info-description-html" [innerHTML]="videoHTMLDescription"></div>
|
||||||
|
|
||||||
<div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description.length === 250" (click)="showMoreDescription()">
|
<div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length === 250" (click)="showMoreDescription()">
|
||||||
Show more
|
Show more
|
||||||
<span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-down"></span>
|
<span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-down"></span>
|
||||||
<my-loader class="description-loading" [loading]="descriptionLoading"></my-loader>
|
<my-loader class="description-loading" [loading]="descriptionLoading"></my-loader>
|
||||||
|
|
|
@ -219,6 +219,11 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
private setVideoDescriptionHTML () {
|
private setVideoDescriptionHTML () {
|
||||||
|
if (!this.video.description) {
|
||||||
|
this.videoHTMLDescription = ''
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.videoHTMLDescription = this.markdownService.markdownToHTML(this.video.description)
|
this.videoHTMLDescription = this.markdownService.markdownToHTML(this.video.description)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
export * from './markdown.service'
|
export * from './markdown.service'
|
||||||
export * from './video-description.component'
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
textarea {
|
|
||||||
@include peertube-input-text(100%);
|
|
||||||
|
|
||||||
font-size: 15px;
|
|
||||||
height: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.previews /deep/ {
|
|
||||||
font-size: 15px !important;
|
|
||||||
|
|
||||||
.nav {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-content {
|
|
||||||
min-height: 75px;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
@mixin disable-default-a-behaviour {
|
@mixin disable-default-a-behaviour {
|
||||||
&:hover, &:focus {
|
&:hover, &:focus, &:active {
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
}
|
}
|
||||||
|
@ -23,13 +23,15 @@
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: $orange-color;
|
background-color: $orange-color;
|
||||||
|
|
||||||
&:hover, &:active, &:focus, &[disabled], &.disabled {
|
&:hover, &:active, &:focus {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: $orange-hoover-color;
|
background-color: $orange-hoover-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
&[disabled], &.disabled {
|
&[disabled], &.disabled {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #C6C6C6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,10 @@ label {
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover, &:active, &:focus {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// On small screen, menu is absolute and displayed over the page
|
// On small screen, menu is absolute and displayed over the page
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { getServerAccount } from '../../../helpers/utils'
|
||||||
import { CONFIG, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_MIMETYPE_EXT, VIDEO_PRIVACIES } from '../../../initializers'
|
import { CONFIG, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_MIMETYPE_EXT, VIDEO_PRIVACIES } from '../../../initializers'
|
||||||
import { database as db } from '../../../initializers/database'
|
import { database as db } from '../../../initializers/database'
|
||||||
import { sendAddVideo } from '../../../lib/activitypub/send/send-add'
|
import { sendAddVideo } from '../../../lib/activitypub/send/send-add'
|
||||||
|
import { sendCreateViewToOrigin } from '../../../lib/activitypub/send/send-create'
|
||||||
import { sendUpdateVideo } from '../../../lib/activitypub/send/send-update'
|
import { sendUpdateVideo } from '../../../lib/activitypub/send/send-update'
|
||||||
import { shareVideoByServer } from '../../../lib/activitypub/share'
|
import { shareVideoByServer } from '../../../lib/activitypub/share'
|
||||||
import { getVideoActivityPubUrl } from '../../../lib/activitypub/url'
|
import { getVideoActivityPubUrl } from '../../../lib/activitypub/url'
|
||||||
|
@ -39,7 +40,6 @@ import { abuseVideoRouter } from './abuse'
|
||||||
import { blacklistRouter } from './blacklist'
|
import { blacklistRouter } from './blacklist'
|
||||||
import { videoChannelRouter } from './channel'
|
import { videoChannelRouter } from './channel'
|
||||||
import { rateVideoRouter } from './rate'
|
import { rateVideoRouter } from './rate'
|
||||||
import { sendCreateViewToOrigin } from '../../../lib/activitypub/send/send-create'
|
|
||||||
|
|
||||||
const videosRouter = express.Router()
|
const videosRouter = express.Router()
|
||||||
|
|
||||||
|
@ -154,17 +154,20 @@ async function addVideoRetryWrapper (req: express.Request, res: express.Response
|
||||||
errorMessage: 'Cannot insert the video with many retries.'
|
errorMessage: 'Cannot insert the video with many retries.'
|
||||||
}
|
}
|
||||||
|
|
||||||
await retryTransactionWrapper(addVideo, options)
|
const video = await retryTransactionWrapper(addVideo, options)
|
||||||
|
|
||||||
// TODO : include Location of the new video -> 201
|
res.json({
|
||||||
res.type('json').status(204).end()
|
video: {
|
||||||
|
id: video.id,
|
||||||
|
uuid: video.uuid
|
||||||
|
}
|
||||||
|
}).end()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addVideo (req: express.Request, res: express.Response, videoPhysicalFile: Express.Multer.File) {
|
function addVideo (req: express.Request, res: express.Response, videoPhysicalFile: Express.Multer.File) {
|
||||||
const videoInfo: VideoCreate = req.body
|
const videoInfo: VideoCreate = req.body
|
||||||
let videoUUID = ''
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async t => {
|
return db.sequelize.transaction(async t => {
|
||||||
const sequelizeOptions = { transaction: t }
|
const sequelizeOptions = { transaction: t }
|
||||||
|
|
||||||
const videoData = {
|
const videoData = {
|
||||||
|
@ -223,7 +226,6 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi
|
||||||
const videoCreated = await video.save(sequelizeOptions)
|
const videoCreated = await video.save(sequelizeOptions)
|
||||||
// Do not forget to add video channel information to the created video
|
// Do not forget to add video channel information to the created video
|
||||||
videoCreated.VideoChannel = res.locals.videoChannel
|
videoCreated.VideoChannel = res.locals.videoChannel
|
||||||
videoUUID = videoCreated.uuid
|
|
||||||
|
|
||||||
videoFile.videoId = video.id
|
videoFile.videoId = video.id
|
||||||
|
|
||||||
|
@ -238,15 +240,17 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let transcoding job send the video to friends because the video file extension might change
|
// Let transcoding job send the video to friends because the video file extension might change
|
||||||
if (CONFIG.TRANSCODING.ENABLED === true) return undefined
|
if (CONFIG.TRANSCODING.ENABLED === true) return videoCreated
|
||||||
// Don't send video to remote servers, it is private
|
// Don't send video to remote servers, it is private
|
||||||
if (video.privacy === VideoPrivacy.PRIVATE) return undefined
|
if (video.privacy === VideoPrivacy.PRIVATE) return videoCreated
|
||||||
|
|
||||||
await sendAddVideo(video, t)
|
await sendAddVideo(video, t)
|
||||||
await shareVideoByServer(video, t)
|
await shareVideoByServer(video, t)
|
||||||
})
|
|
||||||
|
|
||||||
logger.info('Video with name %s and uuid %s created.', videoInfo.name, videoUUID)
|
logger.info('Video with name %s and uuid %s created.', videoInfo.name, videoCreated.uuid)
|
||||||
|
|
||||||
|
return videoCreated
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
|
async function updateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
|
|
|
@ -104,7 +104,10 @@ describe('Test a single server', function () {
|
||||||
licence: 6,
|
licence: 6,
|
||||||
tags: [ 'tag1', 'tag2', 'tag3' ]
|
tags: [ 'tag1', 'tag2', 'tag3' ]
|
||||||
}
|
}
|
||||||
await uploadVideo(server.url, server.accessToken, videoAttributes)
|
const res = await uploadVideo(server.url, server.accessToken, videoAttributes)
|
||||||
|
expect(res.body.video).to.not.be.undefined
|
||||||
|
expect(res.body.video.id).to.equal(1)
|
||||||
|
expect(res.body.video.uuid).to.have.length.above(5)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should seed the uploaded video', async function () {
|
it('Should seed the uploaded video', async function () {
|
||||||
|
|
|
@ -201,7 +201,7 @@ async function testVideoImage (url: string, imageName: string, imagePath: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 204) {
|
async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 201) {
|
||||||
const path = '/api/v1/videos/upload'
|
const path = '/api/v1/videos/upload'
|
||||||
let defaultChannelId = '1'
|
let defaultChannelId = '1'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue