aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/videos/+video-edit
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/videos/+video-edit')
-rw-r--r--client/src/app/videos/+video-edit/shared/video-description.component.html9
-rw-r--r--client/src/app/videos/+video-edit/shared/video-description.component.scss41
-rw-r--r--client/src/app/videos/+video-edit/shared/video-description.component.ts66
-rw-r--r--client/src/app/videos/+video-edit/shared/video-edit.component.scss9
-rw-r--r--client/src/app/videos/+video-edit/shared/video-edit.module.ts3
-rw-r--r--client/src/app/videos/+video-edit/video-add.component.html16
-rw-r--r--client/src/app/videos/+video-edit/video-add.component.scss19
-rw-r--r--client/src/app/videos/+video-edit/video-add.component.ts30
-rw-r--r--client/src/app/videos/+video-edit/video-update.component.html4
9 files changed, 176 insertions, 21 deletions
diff --git a/client/src/app/videos/+video-edit/shared/video-description.component.html b/client/src/app/videos/+video-edit/shared/video-description.component.html
new file mode 100644
index 000000000..da66a9753
--- /dev/null
+++ b/client/src/app/videos/+video-edit/shared/video-description.component.html
@@ -0,0 +1,9 @@
1<textarea
2 [(ngModel)]="description" (ngModelChange)="onModelChange()"
3 id="description" placeholder="My super video">
4</textarea>
5
6<tabset #staticTabs class="previews">
7 <tab heading="Truncated description preview" [innerHTML]="truncatedDescriptionHTML"></tab>
8 <tab heading="Complete description preview" [innerHTML]="descriptionHTML"></tab>
9</tabset>
diff --git a/client/src/app/videos/+video-edit/shared/video-description.component.scss b/client/src/app/videos/+video-edit/shared/video-description.component.scss
new file mode 100644
index 000000000..38506bb46
--- /dev/null
+++ b/client/src/app/videos/+video-edit/shared/video-description.component.scss
@@ -0,0 +1,41 @@
1textarea {
2 @include peertube-input-text(100%);
3
4 padding: 5px 15px;
5 font-size: 15px;
6 height: 150px;
7}
8
9.previews /deep/ {
10 font-size: 15px !important;
11
12 .nav {
13 margin-top: 10px;
14 font-size: 16px !important;
15 border: none !important;
16
17 .nav-item .nav-link {
18 color: #000 !important;
19 height: 30px !important;
20 margin-right: 30px;
21 padding: 0 15px;
22 display: flex;
23 align-items: center;
24 border-radius: 3px;
25 border: none !important;
26
27 &.active, &:hover {
28 background-color: #F0F0F0;
29 }
30
31 &.active {
32 font-weight: $font-semibold !important;
33 }
34 }
35 }
36
37 .tab-content {
38 min-height: 75px;
39 padding: 15px;
40 }
41}
diff --git a/client/src/app/videos/+video-edit/shared/video-description.component.ts b/client/src/app/videos/+video-edit/shared/video-description.component.ts
new file mode 100644
index 000000000..8dfb74b2a
--- /dev/null
+++ b/client/src/app/videos/+video-edit/shared/video-description.component.ts
@@ -0,0 +1,66 @@
1import { Component, forwardRef, Input, OnInit } from '@angular/core'
2import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
3import { truncate } from 'lodash'
4import 'rxjs/add/operator/debounceTime'
5import 'rxjs/add/operator/distinctUntilChanged'
6import { Subject } from 'rxjs/Subject'
7import { MarkdownService } from '../../shared'
8
9@Component({
10 selector: 'my-video-description',
11 templateUrl: './video-description.component.html',
12 styleUrls: [ './video-description.component.scss' ],
13 providers: [
14 {
15 provide: NG_VALUE_ACCESSOR,
16 useExisting: forwardRef(() => VideoDescriptionComponent),
17 multi: true
18 }
19 ]
20})
21
22export class VideoDescriptionComponent implements ControlValueAccessor, OnInit {
23 @Input() description = ''
24 truncatedDescriptionHTML = ''
25 descriptionHTML = ''
26
27 private descriptionChanged = new Subject<string>()
28
29 constructor (private markdownService: MarkdownService) {}
30
31 ngOnInit () {
32 this.descriptionChanged
33 .debounceTime(150)
34 .distinctUntilChanged()
35 .subscribe(() => this.updateDescriptionPreviews())
36
37 this.descriptionChanged.next(this.description)
38 }
39
40 propagateChange = (_: any) => { /* empty */ }
41
42 writeValue (description: string) {
43 this.description = description
44
45 this.descriptionChanged.next(this.description)
46 }
47
48 registerOnChange (fn: (_: any) => void) {
49 this.propagateChange = fn
50 }
51
52 registerOnTouched () {
53 // Unused
54 }
55
56 onModelChange () {
57 this.propagateChange(this.description)
58
59 this.descriptionChanged.next(this.description)
60 }
61
62 private updateDescriptionPreviews () {
63 this.truncatedDescriptionHTML = this.markdownService.markdownToHTML(truncate(this.description, { length: 250 }))
64 this.descriptionHTML = this.markdownService.markdownToHTML(this.description)
65 }
66}
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 2d0bfc36e..d363499ce 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
@@ -43,6 +43,14 @@
43 position: relative; 43 position: relative;
44 bottom: $button-height; 44 bottom: $button-height;
45 45
46 .message-submit {
47 display: inline-block;
48 margin-right: 25px;
49
50 color: #585858;
51 font-size: 15px;
52 }
53
46 .submit-button { 54 .submit-button {
47 @include peertube-button; 55 @include peertube-button;
48 @include orange-button; 56 @include orange-button;
@@ -54,6 +62,7 @@
54 background-color: inherit; 62 background-color: inherit;
55 border: none; 63 border: none;
56 padding: 0; 64 padding: 0;
65 outline: 0;
57 } 66 }
58 67
59 .icon.icon-validate { 68 .icon.icon-validate {
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 c7ed8c351..ce106d82f 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
@@ -3,8 +3,9 @@ import { NgModule } from '@angular/core'
3import { TagInputModule } from 'ngx-chips' 3import { TagInputModule } from 'ngx-chips'
4import { TabsModule } from 'ngx-bootstrap/tabs' 4import { TabsModule } from 'ngx-bootstrap/tabs'
5 5
6import { MarkdownService, VideoDescriptionComponent } from '../../shared' 6import { MarkdownService } from '../../shared'
7import { SharedModule } from '../../../shared' 7import { SharedModule } from '../../../shared'
8import { VideoDescriptionComponent } from './video-description.component'
8import { VideoEditComponent } from './video-edit.component' 9import { VideoEditComponent } from './video-edit.component'
9 10
10@NgModule({ 11@NgModule({
diff --git a/client/src/app/videos/+video-edit/video-add.component.html b/client/src/app/videos/+video-edit/video-add.component.html
index 6883f8280..a6f2bf6f2 100644
--- a/client/src/app/videos/+video-edit/video-add.component.html
+++ b/client/src/app/videos/+video-edit/video-add.component.html
@@ -15,20 +15,23 @@
15 </div> 15 </div>
16 16
17 <div class="form-group"> 17 <div class="form-group">
18 <select [(ngModel)]="firstStepPrivacy"> 18 <select [(ngModel)]="firstStepPrivacyId">
19 <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option> 19 <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option>
20 </select> 20 </select>
21 </div> 21 </div>
22 22
23 <div class="form-group"> 23 <div class="form-group">
24 <select [(ngModel)]="firstStepChannel"> 24 <select [(ngModel)]="firstStepChannelId">
25 <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option> 25 <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option>
26 </select> 26 </select>
27 </div> 27 </div>
28 </div> 28 </div>
29 </div> 29 </div>
30 30
31 <p-progressBar *ngIf="isUploadingVideo" [value]="videoUploadPercents"></p-progressBar> 31 <p-progressBar
32 *ngIf="isUploadingVideo" [value]="videoUploadPercents"
33 [ngClass]="{ processing: videoUploadPercents === 100 && videoUploaded === false }"
34 ></p-progressBar>
32 35
33 <!-- Hidden because we need to load the component --> 36 <!-- Hidden because we need to load the component -->
34 <form [hidden]="!isUploadingVideo" novalidate [formGroup]="form"> 37 <form [hidden]="!isUploadingVideo" novalidate [formGroup]="form">
@@ -37,10 +40,13 @@
37 [validationMessages]="validationMessages" [videoPrivacies]="videoPrivacies" 40 [validationMessages]="validationMessages" [videoPrivacies]="videoPrivacies"
38 ></my-video-edit> 41 ></my-video-edit>
39 42
43
40 <div class="submit-container"> 44 <div class="submit-container">
41 <div class="submit-button" [ngClass]="{ disabled: !form.valid }"> 45 <div *ngIf="videoUploaded === false" class="message-submit">Publish will be available when upload is finished</div>
46
47 <div class="submit-button" (click)="updateSecondStep()" [ngClass]="{ disabled: !form.valid || videoUploaded !== true }">
42 <span class="icon icon-validate"></span> 48 <span class="icon icon-validate"></span>
43 <input type="button" value="Publish" (click)="upload()" /> 49 <input type="button" value="Publish" />
44 </div> 50 </div>
45 </div> 51 </div>
46 </form> 52 </form>
diff --git a/client/src/app/videos/+video-edit/video-add.component.scss b/client/src/app/videos/+video-edit/video-add.component.scss
index dfdf7ff73..39673b4b7 100644
--- a/client/src/app/videos/+video-edit/video-add.component.scss
+++ b/client/src/app/videos/+video-edit/video-add.component.scss
@@ -18,6 +18,7 @@
18 .icon.icon-upload { 18 .icon.icon-upload {
19 @include icon(90px); 19 @include icon(90px);
20 margin-bottom: 25px; 20 margin-bottom: 25px;
21 cursor: default;
21 22
22 background-image: url('../../../assets/images/video/upload.svg'); 23 background-image: url('../../../assets/images/video/upload.svg');
23 } 24 }
@@ -58,10 +59,9 @@
58} 59}
59 60
60p-progressBar { 61p-progressBar {
61 margin-top: 50px;
62 margin-bottom: 40px;
63
64 /deep/ .ui-progressbar { 62 /deep/ .ui-progressbar {
63 margin-top: 25px !important;
64 margin-bottom: 40px !important;
65 font-size: 15px !important; 65 font-size: 15px !important;
66 color: #fff !important; 66 color: #fff !important;
67 height: 30px !important; 67 height: 30px !important;
@@ -76,6 +76,19 @@ p-progressBar {
76 .ui-progressbar-label { 76 .ui-progressbar-label {
77 text-align: left; 77 text-align: left;
78 padding-left: 18px; 78 padding-left: 18px;
79 margin-top: 0 !important;
80 }
81 }
82
83 &.processing {
84 /deep/ .ui-progressbar-label {
85 // Same color as background to hide "100%"
86 color: rgba(11, 204, 41, 0.16) !important;
87
88 &::before {
89 content: 'Processing...';
90 color: #fff;
91 }
79 } 92 }
80 } 93 }
81} 94}
diff --git a/client/src/app/videos/+video-edit/video-add.component.ts b/client/src/app/videos/+video-edit/video-add.component.ts
index 2409acfda..2bbc3de17 100644
--- a/client/src/app/videos/+video-edit/video-add.component.ts
+++ b/client/src/app/videos/+video-edit/video-add.component.ts
@@ -5,6 +5,7 @@ import { Router } from '@angular/router'
5import { NotificationsService } from 'angular2-notifications' 5import { NotificationsService } from 'angular2-notifications'
6import { VideoService } from 'app/shared/video/video.service' 6import { VideoService } from 'app/shared/video/video.service'
7import { VideoCreate } from '../../../../../shared' 7import { VideoCreate } from '../../../../../shared'
8import { VideoPrivacy } from '../../../../../shared/models/videos'
8import { AuthService, ServerService } from '../../core' 9import { AuthService, ServerService } from '../../core'
9import { FormReactive } from '../../shared' 10import { FormReactive } from '../../shared'
10import { ValidatorMessage } from '../../shared/forms/form-validators' 11import { ValidatorMessage } from '../../shared/forms/form-validators'
@@ -25,6 +26,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
25 isUploadingVideo = false 26 isUploadingVideo = false
26 videoUploaded = false 27 videoUploaded = false
27 videoUploadPercents = 0 28 videoUploadPercents = 0
29 videoUploadedId = 0
28 30
29 error: string = null 31 error: string = null
30 form: FormGroup 32 form: FormGroup
@@ -33,8 +35,8 @@ export class VideoAddComponent extends FormReactive implements OnInit {
33 35
34 userVideoChannels = [] 36 userVideoChannels = []
35 videoPrivacies = [] 37 videoPrivacies = []
36 firstStepPrivacy = 0 38 firstStepPrivacyId = 0
37 firstStepChannel = 0 39 firstStepChannelId = 0
38 40
39 constructor ( 41 constructor (
40 private formBuilder: FormBuilder, 42 private formBuilder: FormBuilder,
@@ -59,7 +61,9 @@ export class VideoAddComponent extends FormReactive implements OnInit {
59 .subscribe( 61 .subscribe(
60 () => { 62 () => {
61 this.videoPrivacies = this.serverService.getVideoPrivacies() 63 this.videoPrivacies = this.serverService.getVideoPrivacies()
62 this.firstStepPrivacy = this.videoPrivacies[0].id 64
65 // Public by default
66 this.firstStepPrivacyId = VideoPrivacy.PUBLIC
63 }) 67 })
64 68
65 this.authService.userInformationLoaded 69 this.authService.userInformationLoaded
@@ -72,7 +76,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
72 if (Array.isArray(videoChannels) === false) return 76 if (Array.isArray(videoChannels) === false) return
73 77
74 this.userVideoChannels = videoChannels.map(v => ({ id: v.id, label: v.name })) 78 this.userVideoChannels = videoChannels.map(v => ({ id: v.id, label: v.name }))
75 this.firstStepChannel = this.userVideoChannels[0].id 79 this.firstStepChannelId = this.userVideoChannels[0].id
76 } 80 }
77 ) 81 )
78 } 82 }
@@ -89,14 +93,15 @@ export class VideoAddComponent extends FormReactive implements OnInit {
89 93
90 uploadFirstStep () { 94 uploadFirstStep () {
91 const videofile = this.videofileInput.nativeElement.files[0] 95 const videofile = this.videofileInput.nativeElement.files[0]
92 const name = videofile.name 96 const name = videofile.name.replace(/\.[^/.]+$/, '')
93 const privacy = this.firstStepPrivacy.toString() 97 const privacy = this.firstStepPrivacyId.toString()
94 const nsfw = false 98 const nsfw = false
95 const channelId = this.firstStepChannel.toString() 99 const channelId = this.firstStepChannelId.toString()
96 100
97 const formData = new FormData() 101 const formData = new FormData()
98 formData.append('name', name) 102 formData.append('name', name)
99 formData.append('privacy', privacy.toString()) 103 // Put the video "private" -> we wait he validates the second step
104 formData.append('privacy', VideoPrivacy.PRIVATE.toString())
100 formData.append('nsfw', '' + nsfw) 105 formData.append('nsfw', '' + nsfw)
101 formData.append('channelId', '' + channelId) 106 formData.append('channelId', '' + channelId)
102 formData.append('videofile', videofile) 107 formData.append('videofile', videofile)
@@ -117,6 +122,8 @@ export class VideoAddComponent extends FormReactive implements OnInit {
117 console.log('Video uploaded.') 122 console.log('Video uploaded.')
118 123
119 this.videoUploaded = true 124 this.videoUploaded = true
125
126 this.videoUploadedId = event.body.video.id
120 } 127 }
121 }, 128 },
122 129
@@ -133,13 +140,16 @@ export class VideoAddComponent extends FormReactive implements OnInit {
133 return 140 return
134 } 141 }
135 142
136 const video = new VideoEdit(this.form.value) 143 const video = new VideoEdit()
144 video.patch(this.form.value)
145 video.channel = this.firstStepChannelId
146 video.id = this.videoUploadedId
137 147
138 this.videoService.updateVideo(video) 148 this.videoService.updateVideo(video)
139 .subscribe( 149 .subscribe(
140 () => { 150 () => {
141 this.notificationsService.success('Success', 'Video published.') 151 this.notificationsService.success('Success', 'Video published.')
142 this.router.navigate([ '/videos/watch', video.uuid ]) 152 this.router.navigate([ '/videos/watch', video.id ])
143 }, 153 },
144 154
145 err => { 155 err => {
diff --git a/client/src/app/videos/+video-edit/video-update.component.html b/client/src/app/videos/+video-edit/video-update.component.html
index 3163495bf..261b8a130 100644
--- a/client/src/app/videos/+video-edit/video-update.component.html
+++ b/client/src/app/videos/+video-edit/video-update.component.html
@@ -11,9 +11,9 @@
11 ></my-video-edit> 11 ></my-video-edit>
12 12
13 <div class="submit-container"> 13 <div class="submit-container">
14 <div class="submit-button" [ngClass]="{ disabled: !form.valid }"> 14 <div class="submit-button" (click)="update()" [ngClass]="{ disabled: !form.valid }">
15 <span class="icon icon-validate"></span> 15 <span class="icon icon-validate"></span>
16 <input type="button" value="Update" (click)="update()" /> 16 <input type="button" value="Update" />
17 </div> 17 </div>
18 </div> 18 </div>
19 </form> 19 </form>