mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-02-25 18:55:32 -06:00
Design second video upload step
This commit is contained in:
@@ -194,7 +194,6 @@ export class AuthService {
|
||||
}
|
||||
|
||||
this.mergeUserInformation(obj)
|
||||
.do(() => this.userInformationLoaded.next(true))
|
||||
.subscribe(
|
||||
res => {
|
||||
this.user.displayNSFW = res.displayNSFW
|
||||
@@ -203,6 +202,8 @@ export class AuthService {
|
||||
this.user.account = res.account
|
||||
|
||||
this.user.save()
|
||||
|
||||
this.userInformationLoaded.next(true)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -77,7 +77,6 @@ export class ServerService {
|
||||
notifier: ReplaySubject<boolean>
|
||||
) {
|
||||
return this.http.get(ServerService.BASE_VIDEO_URL + attributeName)
|
||||
.do(() => notifier.next(true))
|
||||
.subscribe(data => {
|
||||
Object.keys(data)
|
||||
.forEach(dataKey => {
|
||||
@@ -86,6 +85,8 @@ export class ServerService {
|
||||
label: data[dataKey]
|
||||
})
|
||||
})
|
||||
|
||||
notifier.next(true)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,10 @@ menu {
|
||||
.logged-in-email {
|
||||
font-size: 13px;
|
||||
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 = {
|
||||
VALIDATORS: [ Validators.required ],
|
||||
MESSAGES: {
|
||||
'required': 'Video category is required.'
|
||||
}
|
||||
VALIDATORS: [ ],
|
||||
MESSAGES: {}
|
||||
}
|
||||
|
||||
export const VIDEO_LICENCE = {
|
||||
VALIDATORS: [ Validators.required ],
|
||||
MESSAGES: {
|
||||
'required': 'Video licence is required.'
|
||||
}
|
||||
VALIDATORS: [ ],
|
||||
MESSAGES: {}
|
||||
}
|
||||
|
||||
export const VIDEO_LANGUAGE = {
|
||||
@@ -49,9 +45,8 @@ export const VIDEO_CHANNEL = {
|
||||
}
|
||||
|
||||
export const VIDEO_DESCRIPTION = {
|
||||
VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(3000) ],
|
||||
VALIDATORS: [ Validators.minLength(3), Validators.maxLength(3000) ],
|
||||
MESSAGES: {
|
||||
'required': 'Video description is required.',
|
||||
'minlength': 'Video description must be at least 3 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.'
|
||||
}
|
||||
}
|
||||
|
||||
export const VIDEO_FILE = {
|
||||
VALIDATORS: [ Validators.required ],
|
||||
MESSAGES: {
|
||||
'required': 'Video file is required.'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,18 +14,20 @@ export class VideoEdit {
|
||||
uuid?: string
|
||||
id?: number
|
||||
|
||||
constructor (videoDetails: VideoDetails) {
|
||||
this.id = videoDetails.id
|
||||
this.uuid = videoDetails.uuid
|
||||
this.category = videoDetails.category
|
||||
this.licence = videoDetails.licence
|
||||
this.language = videoDetails.language
|
||||
this.description = videoDetails.description
|
||||
this.name = videoDetails.name
|
||||
this.tags = videoDetails.tags
|
||||
this.nsfw = videoDetails.nsfw
|
||||
this.channel = videoDetails.channel.id
|
||||
this.privacy = videoDetails.privacy
|
||||
constructor (videoDetails?: VideoDetails) {
|
||||
if (videoDetails) {
|
||||
this.id = videoDetails.id
|
||||
this.uuid = videoDetails.uuid
|
||||
this.category = videoDetails.category
|
||||
this.licence = videoDetails.licence
|
||||
this.language = videoDetails.language
|
||||
this.description = videoDetails.description
|
||||
this.name = videoDetails.name
|
||||
this.tags = videoDetails.tags
|
||||
this.nsfw = videoDetails.nsfw
|
||||
this.channel = videoDetails.channel.id
|
||||
this.privacy = videoDetails.privacy
|
||||
}
|
||||
}
|
||||
|
||||
patch (values: Object) {
|
||||
|
||||
@@ -42,14 +42,17 @@ export class VideoService {
|
||||
}
|
||||
|
||||
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 = {
|
||||
name: video.name,
|
||||
category: video.category,
|
||||
licence: video.licence,
|
||||
category,
|
||||
licence,
|
||||
language,
|
||||
description: video.description,
|
||||
description,
|
||||
privacy: video.privacy,
|
||||
tags: video.tags,
|
||||
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 { 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/distinctUntilChanged'
|
||||
|
||||
import { truncate } from 'lodash'
|
||||
|
||||
import { MarkdownService } from './markdown.service'
|
||||
import { Subject } from 'rxjs/Subject'
|
||||
import { MarkdownService } from '../../shared'
|
||||
|
||||
@Component({
|
||||
selector: 'my-video-description',
|
||||
@@ -43,6 +43,14 @@
|
||||
position: relative;
|
||||
bottom: $button-height;
|
||||
|
||||
.message-submit {
|
||||
display: inline-block;
|
||||
margin-right: 25px;
|
||||
|
||||
color: #585858;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
@include peertube-button;
|
||||
@include orange-button;
|
||||
@@ -54,6 +62,7 @@
|
||||
background-color: inherit;
|
||||
border: none;
|
||||
padding: 0;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.icon.icon-validate {
|
||||
|
||||
@@ -3,8 +3,9 @@ import { NgModule } from '@angular/core'
|
||||
import { TagInputModule } from 'ngx-chips'
|
||||
import { TabsModule } from 'ngx-bootstrap/tabs'
|
||||
|
||||
import { MarkdownService, VideoDescriptionComponent } from '../../shared'
|
||||
import { MarkdownService } from '../../shared'
|
||||
import { SharedModule } from '../../../shared'
|
||||
import { VideoDescriptionComponent } from './video-description.component'
|
||||
import { VideoEditComponent } from './video-edit.component'
|
||||
|
||||
@NgModule({
|
||||
|
||||
@@ -15,20 +15,23 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<select [(ngModel)]="firstStepPrivacy">
|
||||
<select [(ngModel)]="firstStepPrivacyId">
|
||||
<option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<select [(ngModel)]="firstStepChannel">
|
||||
<select [(ngModel)]="firstStepChannelId">
|
||||
<option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option>
|
||||
</select>
|
||||
</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 -->
|
||||
<form [hidden]="!isUploadingVideo" novalidate [formGroup]="form">
|
||||
@@ -37,10 +40,13 @@
|
||||
[validationMessages]="validationMessages" [videoPrivacies]="videoPrivacies"
|
||||
></my-video-edit>
|
||||
|
||||
|
||||
<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>
|
||||
<input type="button" value="Publish" (click)="upload()" />
|
||||
<input type="button" value="Publish" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
.icon.icon-upload {
|
||||
@include icon(90px);
|
||||
margin-bottom: 25px;
|
||||
cursor: default;
|
||||
|
||||
background-image: url('../../../assets/images/video/upload.svg');
|
||||
}
|
||||
@@ -58,10 +59,9 @@
|
||||
}
|
||||
|
||||
p-progressBar {
|
||||
margin-top: 50px;
|
||||
margin-bottom: 40px;
|
||||
|
||||
/deep/ .ui-progressbar {
|
||||
margin-top: 25px !important;
|
||||
margin-bottom: 40px !important;
|
||||
font-size: 15px !important;
|
||||
color: #fff !important;
|
||||
height: 30px !important;
|
||||
@@ -76,6 +76,19 @@ p-progressBar {
|
||||
.ui-progressbar-label {
|
||||
text-align: left;
|
||||
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 { VideoService } from 'app/shared/video/video.service'
|
||||
import { VideoCreate } from '../../../../../shared'
|
||||
import { VideoPrivacy } from '../../../../../shared/models/videos'
|
||||
import { AuthService, ServerService } from '../../core'
|
||||
import { FormReactive } from '../../shared'
|
||||
import { ValidatorMessage } from '../../shared/forms/form-validators'
|
||||
@@ -25,6 +26,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
|
||||
isUploadingVideo = false
|
||||
videoUploaded = false
|
||||
videoUploadPercents = 0
|
||||
videoUploadedId = 0
|
||||
|
||||
error: string = null
|
||||
form: FormGroup
|
||||
@@ -33,8 +35,8 @@ export class VideoAddComponent extends FormReactive implements OnInit {
|
||||
|
||||
userVideoChannels = []
|
||||
videoPrivacies = []
|
||||
firstStepPrivacy = 0
|
||||
firstStepChannel = 0
|
||||
firstStepPrivacyId = 0
|
||||
firstStepChannelId = 0
|
||||
|
||||
constructor (
|
||||
private formBuilder: FormBuilder,
|
||||
@@ -59,7 +61,9 @@ export class VideoAddComponent extends FormReactive implements OnInit {
|
||||
.subscribe(
|
||||
() => {
|
||||
this.videoPrivacies = this.serverService.getVideoPrivacies()
|
||||
this.firstStepPrivacy = this.videoPrivacies[0].id
|
||||
|
||||
// Public by default
|
||||
this.firstStepPrivacyId = VideoPrivacy.PUBLIC
|
||||
})
|
||||
|
||||
this.authService.userInformationLoaded
|
||||
@@ -72,7 +76,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
|
||||
if (Array.isArray(videoChannels) === false) return
|
||||
|
||||
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 () {
|
||||
const videofile = this.videofileInput.nativeElement.files[0]
|
||||
const name = videofile.name
|
||||
const privacy = this.firstStepPrivacy.toString()
|
||||
const name = videofile.name.replace(/\.[^/.]+$/, '')
|
||||
const privacy = this.firstStepPrivacyId.toString()
|
||||
const nsfw = false
|
||||
const channelId = this.firstStepChannel.toString()
|
||||
const channelId = this.firstStepChannelId.toString()
|
||||
|
||||
const formData = new FormData()
|
||||
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('channelId', '' + channelId)
|
||||
formData.append('videofile', videofile)
|
||||
@@ -117,6 +122,8 @@ export class VideoAddComponent extends FormReactive implements OnInit {
|
||||
console.log('Video uploaded.')
|
||||
|
||||
this.videoUploaded = true
|
||||
|
||||
this.videoUploadedId = event.body.video.id
|
||||
}
|
||||
},
|
||||
|
||||
@@ -133,13 +140,16 @@ export class VideoAddComponent extends FormReactive implements OnInit {
|
||||
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)
|
||||
.subscribe(
|
||||
() => {
|
||||
this.notificationsService.success('Success', 'Video published.')
|
||||
this.router.navigate([ '/videos/watch', video.uuid ])
|
||||
this.router.navigate([ '/videos/watch', video.id ])
|
||||
},
|
||||
|
||||
err => {
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
></my-video-edit>
|
||||
|
||||
<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>
|
||||
<input type="button" value="Update" (click)="update()" />
|
||||
<input type="button" value="Update" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
<div class="video-info-description">
|
||||
<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
|
||||
<span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-down"></span>
|
||||
<my-loader class="description-loading" [loading]="descriptionLoading"></my-loader>
|
||||
|
||||
@@ -219,6 +219,11 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private setVideoDescriptionHTML () {
|
||||
if (!this.video.description) {
|
||||
this.videoHTMLDescription = ''
|
||||
return
|
||||
}
|
||||
|
||||
this.videoHTMLDescription = this.markdownService.markdownToHTML(this.video.description)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
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 {
|
||||
&:hover, &:focus {
|
||||
&:hover, &:focus, &:active {
|
||||
text-decoration: none !important;
|
||||
outline: none !important;
|
||||
}
|
||||
@@ -23,13 +23,15 @@
|
||||
color: #fff;
|
||||
background-color: $orange-color;
|
||||
|
||||
&:hover, &:active, &:focus, &[disabled], &.disabled {
|
||||
&:hover, &:active, &:focus {
|
||||
color: #fff;
|
||||
background-color: $orange-hoover-color;
|
||||
}
|
||||
|
||||
&[disabled], &.disabled {
|
||||
cursor: default;
|
||||
color: #fff;
|
||||
background-color: #C6C6C6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,10 @@ label {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
&:hover, &:active, &:focus {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
// On small screen, menu is absolute and displayed over the page
|
||||
|
||||
Reference in New Issue
Block a user