aboutsummaryrefslogtreecommitdiffhomepage
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/src/app/videos/+video-edit/shared/video-edit.component.html1
-rw-r--r--client/src/app/videos/+video-edit/shared/video-edit.component.scss35
-rw-r--r--client/src/app/videos/+video-edit/video-add.component.html142
-rw-r--r--client/src/app/videos/+video-edit/video-add.component.scss60
-rw-r--r--client/src/app/videos/+video-edit/video-add.component.ts126
-rw-r--r--client/src/assets/images/video/upload.svg16
6 files changed, 145 insertions, 235 deletions
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 a6b753166..8c071ce12 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
@@ -67,6 +67,7 @@
67 <div class="form-group"> 67 <div class="form-group">
68 <label for="privacy">Privacy</label> 68 <label for="privacy">Privacy</label>
69 <select id="privacy" formControlName="privacy"> 69 <select id="privacy" formControlName="privacy">
70
70 <option></option> 71 <option></option>
71 <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option> 72 <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option>
72 </select> 73 </select>
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 0af48fabe..2d0bfc36e 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
@@ -115,42 +115,7 @@
115 } 115 }
116} 116}
117 117
118
119.btn-file {
120 position: relative;
121 overflow: hidden;
122 display: block;
123}
124
125.btn-file input[type=file] {
126 position: absolute;
127 top: 0;
128 right: 0;
129 min-width: 100%;
130 min-height: 100%;
131 font-size: 100px;
132 text-align: right;
133 filter: alpha(opacity=0);
134 opacity: 0;
135 outline: none;
136 background: white;
137 cursor: inherit;
138 display: block;
139}
140
141div.file-to-upload {
142 height: 40px;
143
144 .glyphicon-remove {
145 cursor: pointer;
146 }
147}
148
149.little-information { 118.little-information {
150 font-size: 0.8em; 119 font-size: 0.8em;
151 font-style: italic; 120 font-style: italic;
152} 121}
153
154.label-tags {
155 margin-bottom: 0;
156}
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 b4e0f9f7c..f8355f3db 100644
--- a/client/src/app/videos/+video-edit/video-add.component.html
+++ b/client/src/app/videos/+video-edit/video-add.component.html
@@ -1,141 +1,45 @@
1<div class="row"> 1<div class="margin-content">
2 <div class="content-padding"> 2 <div class="title-page title-page-single">
3 Upload your video
4 </div>
3 5
4 <h3>Upload a video</h3> 6 <div *ngIf="error" class="alert alert-danger">{{ error }}</div>
5 7
6 <div *ngIf="error !== undefined" class="alert alert-danger">{{ error }}</div> 8 <div class="upload-video-container">
9 <div class="upload-video">
10 <div class="icon icon-upload"></div>
7 11
8 <form novalidate [formGroup]="form"> 12 <div class="button-file">
9 <div class="form-group"> 13 <span>Select the file to upload</span>
10 <label for="name">Name</label> 14 <input #videofileInput type="file" name="videofile" id="videofile" (change)="fileChange($event)" />
11 <input
12 type="text" class="form-control" id="name"
13 formControlName="name"
14 >
15 <div *ngIf="formErrors.name" class="alert alert-danger">
16 {{ formErrors.name }}
17 </div>
18 </div> 15 </div>
19 16
20 <div class="form-group"> 17 <div class="form-group">
21 <label for="privacy">Privacy</label> 18 <select [(ngModel)]="firstStepPrivacy">
22 <select class="form-control" id="privacy" formControlName="privacy">
23 <option></option>
24 <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>
25 </select> 20 </select>
26
27 <div *ngIf="formErrors.privacy" class="alert alert-danger">
28 {{ formErrors.privacy }}
29 </div>
30 </div>
31
32 <div class="form-group">
33 <input
34 type="checkbox" id="nsfw"
35 formControlName="nsfw"
36 >
37 <label for="nsfw">This video contains mature or explicit content</label>
38 </div> 21 </div>
39 22
40 <div class="form-group"> 23 <div class="form-group">
41 <label for="category">Channel</label> 24 <select [(ngModel)]="firstStepChannel">
42 <select class="form-control" id="channelId" formControlName="channelId">
43 <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>
44 </select> 26 </select>
45
46 <div *ngIf="formErrors.channelId" class="alert alert-danger">
47 {{ formErrors.channelId }}
48 </div>
49 </div> 27 </div>
28 </div>
50 29
51 <div class="form-group">
52 <label for="category">Category</label>
53 <select class="form-control" id="category" formControlName="category">
54 <option></option>
55 <option *ngFor="let category of videoCategories" [value]="category.id">{{ category.label }}</option>
56 </select>
57 30
58 <div *ngIf="formErrors.category" class="alert alert-danger"> 31 <form *ngIf="isUploadingVideo" novalidate [formGroup]="form">
59 {{ formErrors.category }} 32 <my-video-edit
60 </div> 33 [form]="form" [formErrors]="formErrors"
61 </div> 34 [validationMessages]="validationMessages" [videoPrivacies]="videoPrivacies"
62 35 ></my-video-edit>
63 <div class="form-group">
64 <label for="licence">Licence</label>
65 <select class="form-control" id="licence" formControlName="licence">
66 <option></option>
67 <option *ngFor="let licence of videoLicences" [value]="licence.id">{{ licence.label }}</option>
68 </select>
69
70 <div *ngIf="formErrors.licence" class="alert alert-danger">
71 {{ formErrors.licence }}
72 </div>
73 </div>
74
75 <div class="form-group">
76 <label for="language">Language</label>
77 <select class="form-control" id="language" formControlName="language">
78 <option></option>
79 <option *ngFor="let language of videoLanguages" [value]="language.id">{{ language.label }}</option>
80 </select>
81 36
82 <div *ngIf="formErrors.language" class="alert alert-danger"> 37 <div class="submit-container">
83 {{ formErrors.language }} 38 <div class="submit-button" [ngClass]="{ disabled: !form.valid }">
39 <span class="icon icon-validate"></span>
40 <input type="button" value="Publish" (click)="upload()" />
84 </div> 41 </div>
85 </div> 42 </div>
86
87 <div class="form-group">
88 <label class="label-tags">Tags</label> <span class="little-information">(press enter to add the tag)</span>
89 <tag-input
90 [ngModel]="tags" [validators]="tagValidators" [errorMessages]="tagValidatorsMessages"
91 formControlName="tags" maxItems="5" modelAsStrings="true"
92 ></tag-input>
93 </div>
94
95 <div class="form-group">
96 <label for="videofile">File</label>
97 <div class="btn btn-default btn-file">
98 <span>Select the video...</span>
99 <input #videofileInput type="file" name="videofile" id="videofile" (change)="fileChange($event)" />
100 <input type="hidden" name="videofileHidden" formControlName="videofile"/>
101 </div>
102 </div>
103
104 <div class="file-to-upload">
105 <div class="file" *ngIf="filename">
106 <span class="filename">{{ filename }}</span>
107 <span class="glyphicon glyphicon-remove" (click)="removeFile()"></span>
108 </div>
109 </div>
110
111 <div *ngIf="formErrors.videofile" class="alert alert-danger">
112 {{ formErrors.videofile }}
113 </div>
114
115 <div class="form-group">
116 <label for="description">Description</label>
117 <my-video-description formControlName="description"></my-video-description>
118
119 <div *ngIf="formErrors.description" class="alert alert-danger">
120 {{ formErrors.description }}
121 </div>
122 </div>
123
124 <div class="progress">
125 <progressbar [value]="progressPercent" max="100">
126 <ng-template [ngIf]="progressPercent === 100">
127 <span class="glyphicon glyphicon-refresh glyphicon-refresh-animate"></span>
128 Server is processing the video
129 </ng-template>
130 </progressbar>
131 </div>
132
133 <div class="form-group">
134 <input
135 type="button" value="Upload" class="btn btn-default form-control"
136 (click)="upload()"
137 >
138 </div>
139 </form> 43 </form>
140 </div> 44 </div>
141</div> 45</div>
diff --git a/client/src/app/videos/+video-edit/video-add.component.scss b/client/src/app/videos/+video-edit/video-add.component.scss
new file mode 100644
index 000000000..25dfd40d2
--- /dev/null
+++ b/client/src/app/videos/+video-edit/video-add.component.scss
@@ -0,0 +1,60 @@
1.upload-video-container {
2 border-radius: 3px;
3 background-color: #F7F7F7;
4 border: 3px solid #EAEAEA;
5 width: 100%;
6 height: 440px;
7 text-align: center;
8 margin-top: 40px;
9 display: flex;
10 justify-content: center;
11 align-items: center;
12
13 .upload-video {
14 display: flex;
15 flex-direction: column;
16 align-items: center;
17
18 .icon.icon-upload {
19 @include icon(90px);
20 margin-bottom: 25px;
21
22 background-image: url('../../../assets/images/video/upload.svg');
23 }
24
25 .button-file {
26 position: relative;
27 overflow: hidden;
28 display: inline-block;
29 margin-bottom: 70px;
30
31 @include peertube-button;
32 @include orange-button;
33
34 input[type=file] {
35 position: absolute;
36 top: 0;
37 right: 0;
38 min-width: 100%;
39 min-height: 100%;
40 font-size: 100px;
41 text-align: right;
42 filter: alpha(opacity=0);
43 opacity: 0;
44 outline: none;
45 background: white;
46 cursor: inherit;
47 display: block;
48 }
49 }
50
51 select {
52 @include peertube-select(auto);
53
54 display: inline-block;
55 font-size: 15px
56 }
57 }
58}
59
60
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 989addbd7..071f9a28b 100644
--- a/client/src/app/videos/+video-edit/video-add.component.ts
+++ b/client/src/app/videos/+video-edit/video-add.component.ts
@@ -6,61 +6,33 @@ import { 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 { AuthService, ServerService } from '../../core' 8import { AuthService, ServerService } from '../../core'
9import { 9import { FormReactive } from '../../shared'
10 FormReactive, 10import { ValidatorMessage } from '../../shared/forms/form-validators'
11 VIDEO_CATEGORY, 11import { VideoEdit } from '../../shared/video/video-edit.model'
12 VIDEO_CHANNEL,
13 VIDEO_DESCRIPTION,
14 VIDEO_FILE,
15 VIDEO_LANGUAGE,
16 VIDEO_LICENCE,
17 VIDEO_NAME,
18 VIDEO_PRIVACY,
19 VIDEO_TAGS
20} from '../../shared'
21 12
22@Component({ 13@Component({
23 selector: 'my-videos-add', 14 selector: 'my-videos-add',
24 styleUrls: [ './shared/video-edit.component.scss' ], 15 templateUrl: './video-add.component.html',
25 templateUrl: './video-add.component.html' 16 styleUrls: [
17 './shared/video-edit.component.scss',
18 './video-add.component.scss'
19 ]
26}) 20})
27 21
28export class VideoAddComponent extends FormReactive implements OnInit { 22export class VideoAddComponent extends FormReactive implements OnInit {
29 @ViewChild('videofileInput') videofileInput 23 @ViewChild('videofileInput') videofileInput
30 24
25 isUploadingVideo = false
31 progressPercent = 0 26 progressPercent = 0
32 tags: string[] = []
33 videoCategories = []
34 videoLicences = []
35 videoLanguages = []
36 videoPrivacies = []
37 userVideoChannels = []
38
39 tagValidators = VIDEO_TAGS.VALIDATORS
40 tagValidatorsMessages = VIDEO_TAGS.MESSAGES
41 27
42 error: string 28 error: string = null
43 form: FormGroup 29 form: FormGroup
44 formErrors = { 30 formErrors: { [ id: string ]: string } = {}
45 name: '', 31 validationMessages: ValidatorMessage = {}
46 privacy: '', 32 userVideoChannels = []
47 category: '', 33 videoPrivacies = []
48 licence: '', 34 firstStepPrivacy = 0
49 language: '', 35 firstStepChannel = 0
50 channelId: '',
51 description: '',
52 videofile: ''
53 }
54 validationMessages = {
55 name: VIDEO_NAME.MESSAGES,
56 privacy: VIDEO_PRIVACY.MESSAGES,
57 category: VIDEO_CATEGORY.MESSAGES,
58 licence: VIDEO_LICENCE.MESSAGES,
59 language: VIDEO_LANGUAGE.MESSAGES,
60 channelId: VIDEO_CHANNEL.MESSAGES,
61 description: VIDEO_DESCRIPTION.MESSAGES,
62 videofile: VIDEO_FILE.MESSAGES
63 }
64 36
65 constructor ( 37 constructor (
66 private formBuilder: FormBuilder, 38 private formBuilder: FormBuilder,
@@ -73,35 +45,17 @@ export class VideoAddComponent extends FormReactive implements OnInit {
73 super() 45 super()
74 } 46 }
75 47
76 get filename () {
77 return this.form.value['videofile']
78 }
79
80 buildForm () { 48 buildForm () {
81 this.form = this.formBuilder.group({ 49 this.form = this.formBuilder.group({})
82 name: [ '', VIDEO_NAME.VALIDATORS ],
83 nsfw: [ false ],
84 privacy: [ '', VIDEO_PRIVACY.VALIDATORS ],
85 category: [ '', VIDEO_CATEGORY.VALIDATORS ],
86 licence: [ '', VIDEO_LICENCE.VALIDATORS ],
87 language: [ '', VIDEO_LANGUAGE.VALIDATORS ],
88 channelId: [ '', VIDEO_CHANNEL.VALIDATORS ],
89 description: [ '', VIDEO_DESCRIPTION.VALIDATORS ],
90 videofile: [ '', VIDEO_FILE.VALIDATORS ],
91 tags: [ '' ]
92 })
93
94 this.form.valueChanges.subscribe(data => this.onValueChanged(data)) 50 this.form.valueChanges.subscribe(data => this.onValueChanged(data))
95 } 51 }
96 52
97 ngOnInit () { 53 ngOnInit () {
98 this.videoCategories = this.serverService.getVideoCategories()
99 this.videoLicences = this.serverService.getVideoLicences()
100 this.videoLanguages = this.serverService.getVideoLanguages()
101 this.videoPrivacies = this.serverService.getVideoPrivacies()
102
103 this.buildForm() 54 this.buildForm()
104 55
56 this.videoPrivacies = this.serverService.getVideoPrivacies()
57 this.firstStepPrivacy = this.videoPrivacies[0].id
58
105 this.authService.userInformationLoaded 59 this.authService.userInformationLoaded
106 .subscribe( 60 .subscribe(
107 () => { 61 () => {
@@ -112,21 +66,13 @@ export class VideoAddComponent extends FormReactive implements OnInit {
112 if (Array.isArray(videoChannels) === false) return 66 if (Array.isArray(videoChannels) === false) return
113 67
114 this.userVideoChannels = videoChannels.map(v => ({ id: v.id, label: v.name })) 68 this.userVideoChannels = videoChannels.map(v => ({ id: v.id, label: v.name }))
115 69 this.firstStepChannel = this.userVideoChannels[0].id
116 this.form.patchValue({ channelId: this.userVideoChannels[0].id })
117 } 70 }
118 ) 71 )
119 } 72 }
120 73
121 // The goal is to keep reactive form validation (required field)
122 // https://stackoverflow.com/a/44238894
123 fileChange ($event) { 74 fileChange ($event) {
124 this.form.controls['videofile'].setValue($event.target.files[0].name) 75 console.log('uploading file ?')
125 }
126
127 removeFile () {
128 this.videofileInput.nativeElement.value = ''
129 this.form.controls['videofile'].setValue('')
130 } 76 }
131 77
132 checkForm () { 78 checkForm () {
@@ -135,11 +81,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
135 return this.form.valid 81 return this.form.valid
136 } 82 }
137 83
138 upload () { 84 uploadFirstStep () {
139 if (this.checkForm() === false) {
140 return
141 }
142
143 const formValue: VideoCreate = this.form.value 85 const formValue: VideoCreate = this.form.value
144 86
145 const name = formValue.name 87 const name = formValue.name
@@ -193,4 +135,26 @@ export class VideoAddComponent extends FormReactive implements OnInit {
193 } 135 }
194 ) 136 )
195 } 137 }
138
139 updateSecondStep () {
140 if (this.checkForm() === false) {
141 return
142 }
143
144 const video = new VideoEdit(this.form.value)
145
146 this.videoService.updateVideo(video)
147 .subscribe(
148 () => {
149 this.notificationsService.success('Success', 'Video published.')
150 this.router.navigate([ '/videos/watch', video.uuid ])
151 },
152
153 err => {
154 this.error = 'Cannot update the video.'
155 console.error(err)
156 }
157 )
158
159 }
196} 160}
diff --git a/client/src/assets/images/video/upload.svg b/client/src/assets/images/video/upload.svg
new file mode 100644
index 000000000..c5b7cb443
--- /dev/null
+++ b/client/src/assets/images/video/upload.svg
@@ -0,0 +1,16 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
4 <title>cloud-upload</title>
5 <desc>Created with Sketch.</desc>
6 <defs></defs>
7 <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
8 <g id="Artboard-4" transform="translate(-312.000000, -775.000000)" stroke="#C6C6C6" stroke-width="2">
9 <g id="307" transform="translate(312.000000, 775.000000)">
10 <path d="M8,18 L5,18 L5,18 C2.790861,18 1,16.209139 1,14 C1,11.790861 2.790861,10 5,10 C5.35840468,10 5.70579988,10.0471371 6.03632437,10.1355501 C6.01233106,9.92702603 6,9.71495305 6,9.5 C6,6.46243388 8.46243388,4 11.5,4 C14.0673313,4 16.2238156,5.7590449 16.8299648,8.1376465 C17.2052921,8.04765874 17.5970804,8 18,8 C20.7614237,8 23,10.2385763 23,13 C23,15.7614237 20.7614237,18 18,18 L16,18" id="Combined-Shape" stroke-linejoin="round"></path>
11 <path d="M12,13 L12,21" id="Path-58"></path>
12 <polyline id="Path-59" stroke-linejoin="round" transform="translate(12.000000, 12.500000) scale(1, -1) translate(-12.000000, -12.500000) " points="15 11 12 14 9 11"></polyline>
13 </g>
14 </g>
15 </g>
16</svg>