diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2017-03-22 21:15:55 +0100 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2017-03-22 21:25:24 +0100 |
commit | 6e07c3de88791a0b342e0cc319590048117f9c2d (patch) | |
tree | 049f88d3f6d3ec0aeea09702a583deb86d6ef78f /client | |
parent | 2d7653dc8726185615bab66353c4e3fb8fbb5a5f (diff) | |
download | PeerTube-6e07c3de88791a0b342e0cc319590048117f9c2d.tar.gz PeerTube-6e07c3de88791a0b342e0cc319590048117f9c2d.tar.zst PeerTube-6e07c3de88791a0b342e0cc319590048117f9c2d.zip |
Add video category support
Diffstat (limited to 'client')
8 files changed, 74 insertions, 3 deletions
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts index 8b4b4118b..c7310690f 100644 --- a/client/src/app/app.component.ts +++ b/client/src/app/app.component.ts | |||
@@ -2,6 +2,7 @@ import { Component, OnInit, ViewContainerRef } from '@angular/core'; | |||
2 | import { Router } from '@angular/router'; | 2 | import { Router } from '@angular/router'; |
3 | 3 | ||
4 | import { AuthService } from './core'; | 4 | import { AuthService } from './core'; |
5 | import { VideoService } from './videos'; | ||
5 | import { UserService } from './shared'; | 6 | import { UserService } from './shared'; |
6 | 7 | ||
7 | @Component({ | 8 | @Component({ |
@@ -27,6 +28,7 @@ export class AppComponent implements OnInit { | |||
27 | private router: Router, | 28 | private router: Router, |
28 | private authService: AuthService, | 29 | private authService: AuthService, |
29 | private userService: UserService, | 30 | private userService: UserService, |
31 | private videoService: VideoService, | ||
30 | viewContainerRef: ViewContainerRef | 32 | viewContainerRef: ViewContainerRef |
31 | ) {} | 33 | ) {} |
32 | 34 | ||
@@ -35,6 +37,8 @@ export class AppComponent implements OnInit { | |||
35 | // The service will automatically redirect to the login page if the token is not valid anymore | 37 | // The service will automatically redirect to the login page if the token is not valid anymore |
36 | this.userService.checkTokenValidity(); | 38 | this.userService.checkTokenValidity(); |
37 | } | 39 | } |
40 | |||
41 | this.videoService.loadVideoCategories(); | ||
38 | } | 42 | } |
39 | 43 | ||
40 | isInAdmin() { | 44 | isInAdmin() { |
diff --git a/client/src/app/shared/forms/form-validators/video.ts b/client/src/app/shared/forms/form-validators/video.ts index b2e612c62..d972ee44b 100644 --- a/client/src/app/shared/forms/form-validators/video.ts +++ b/client/src/app/shared/forms/form-validators/video.ts | |||
@@ -8,6 +8,12 @@ export const VIDEO_NAME = { | |||
8 | 'maxlength': 'Video name cannot be more than 50 characters long.' | 8 | 'maxlength': 'Video name cannot be more than 50 characters long.' |
9 | } | 9 | } |
10 | }; | 10 | }; |
11 | export const VIDEO_CATEGORY = { | ||
12 | VALIDATORS: [ Validators.required ], | ||
13 | MESSAGES: { | ||
14 | 'required': 'Video category is required.' | ||
15 | } | ||
16 | }; | ||
11 | export const VIDEO_DESCRIPTION = { | 17 | export const VIDEO_DESCRIPTION = { |
12 | VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(250) ], | 18 | VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(250) ], |
13 | MESSAGES: { | 19 | MESSAGES: { |
diff --git a/client/src/app/videos/shared/video.model.ts b/client/src/app/videos/shared/video.model.ts index 3eef936eb..b5d96f63a 100644 --- a/client/src/app/videos/shared/video.model.ts +++ b/client/src/app/videos/shared/video.model.ts | |||
@@ -2,6 +2,7 @@ export class Video { | |||
2 | author: string; | 2 | author: string; |
3 | by: string; | 3 | by: string; |
4 | createdAt: Date; | 4 | createdAt: Date; |
5 | categoryLabel: string; | ||
5 | description: string; | 6 | description: string; |
6 | duration: string; | 7 | duration: string; |
7 | id: string; | 8 | id: string; |
@@ -31,6 +32,7 @@ export class Video { | |||
31 | constructor(hash: { | 32 | constructor(hash: { |
32 | author: string, | 33 | author: string, |
33 | createdAt: string, | 34 | createdAt: string, |
35 | categoryLabel: string, | ||
34 | description: string, | 36 | description: string, |
35 | duration: number; | 37 | duration: number; |
36 | id: string, | 38 | id: string, |
@@ -46,6 +48,7 @@ export class Video { | |||
46 | }) { | 48 | }) { |
47 | this.author = hash.author; | 49 | this.author = hash.author; |
48 | this.createdAt = new Date(hash.createdAt); | 50 | this.createdAt = new Date(hash.createdAt); |
51 | this.categoryLabel = hash.categoryLabel; | ||
49 | this.description = hash.description; | 52 | this.description = hash.description; |
50 | this.duration = Video.createDurationString(hash.duration); | 53 | this.duration = Video.createDurationString(hash.duration); |
51 | this.id = hash.id; | 54 | this.id = hash.id; |
diff --git a/client/src/app/videos/shared/video.service.ts b/client/src/app/videos/shared/video.service.ts index 8bb5a2933..debc114aa 100644 --- a/client/src/app/videos/shared/video.service.ts +++ b/client/src/app/videos/shared/video.service.ts | |||
@@ -22,6 +22,8 @@ import { Video } from './video.model'; | |||
22 | export class VideoService { | 22 | export class VideoService { |
23 | private static BASE_VIDEO_URL = '/api/v1/videos/'; | 23 | private static BASE_VIDEO_URL = '/api/v1/videos/'; |
24 | 24 | ||
25 | videoCategories: Array<{ id: number, label: string }> = []; | ||
26 | |||
25 | constructor( | 27 | constructor( |
26 | private authService: AuthService, | 28 | private authService: AuthService, |
27 | private authHttp: AuthHttp, | 29 | private authHttp: AuthHttp, |
@@ -30,6 +32,19 @@ export class VideoService { | |||
30 | private restService: RestService | 32 | private restService: RestService |
31 | ) {} | 33 | ) {} |
32 | 34 | ||
35 | loadVideoCategories() { | ||
36 | return this.http.get(VideoService.BASE_VIDEO_URL + 'categories') | ||
37 | .map(this.restExtractor.extractDataGet) | ||
38 | .subscribe(data => { | ||
39 | Object.keys(data).forEach(categoryKey => { | ||
40 | this.videoCategories.push({ | ||
41 | id: parseInt(categoryKey), | ||
42 | label: data[categoryKey] | ||
43 | }); | ||
44 | }); | ||
45 | }); | ||
46 | } | ||
47 | |||
33 | getVideo(id: string): Observable<Video> { | 48 | getVideo(id: string): Observable<Video> { |
34 | return this.http.get(VideoService.BASE_VIDEO_URL + id) | 49 | return this.http.get(VideoService.BASE_VIDEO_URL + id) |
35 | .map(this.restExtractor.extractDataGet) | 50 | .map(this.restExtractor.extractDataGet) |
diff --git a/client/src/app/videos/video-add/video-add.component.html b/client/src/app/videos/video-add/video-add.component.html index b6be0d782..c6692b21d 100644 --- a/client/src/app/videos/video-add/video-add.component.html +++ b/client/src/app/videos/video-add/video-add.component.html | |||
@@ -15,6 +15,18 @@ | |||
15 | </div> | 15 | </div> |
16 | 16 | ||
17 | <div class="form-group"> | 17 | <div class="form-group"> |
18 | <label for="category">Category</label> | ||
19 | <select class="form-control" id="category" formControlName="category"> | ||
20 | <option></option> | ||
21 | <option *ngFor="let category of videoCategories" [value]="category.id">{{ category.label }}</option> | ||
22 | </select> | ||
23 | |||
24 | <div *ngIf="formErrors.category" class="alert alert-danger"> | ||
25 | {{ formErrors.category }} | ||
26 | </div> | ||
27 | </div> | ||
28 | |||
29 | <div class="form-group"> | ||
18 | <label for="tags">Tags</label> <span class="little-information">(press enter to add the tag)</span> | 30 | <label for="tags">Tags</label> <span class="little-information">(press enter to add the tag)</span> |
19 | <input | 31 | <input |
20 | type="text" class="form-control" id="currentTag" | 32 | type="text" class="form-control" id="currentTag" |
diff --git a/client/src/app/videos/video-add/video-add.component.ts b/client/src/app/videos/video-add/video-add.component.ts index cd6bb9989..2ef666e17 100644 --- a/client/src/app/videos/video-add/video-add.component.ts +++ b/client/src/app/videos/video-add/video-add.component.ts | |||
@@ -6,7 +6,14 @@ import { FileUploader } from 'ng2-file-upload/ng2-file-upload'; | |||
6 | import { NotificationsService } from 'angular2-notifications'; | 6 | import { NotificationsService } from 'angular2-notifications'; |
7 | 7 | ||
8 | import { AuthService } from '../../core'; | 8 | import { AuthService } from '../../core'; |
9 | import { FormReactive, VIDEO_NAME, VIDEO_DESCRIPTION, VIDEO_TAGS } from '../../shared'; | 9 | import { |
10 | FormReactive, | ||
11 | VIDEO_NAME, | ||
12 | VIDEO_CATEGORY, | ||
13 | VIDEO_DESCRIPTION, | ||
14 | VIDEO_TAGS | ||
15 | } from '../../shared'; | ||
16 | import { VideoService } from '../shared'; | ||
10 | 17 | ||
11 | @Component({ | 18 | @Component({ |
12 | selector: 'my-videos-add', | 19 | selector: 'my-videos-add', |
@@ -17,16 +24,19 @@ import { FormReactive, VIDEO_NAME, VIDEO_DESCRIPTION, VIDEO_TAGS } from '../../s | |||
17 | export class VideoAddComponent extends FormReactive implements OnInit { | 24 | export class VideoAddComponent extends FormReactive implements OnInit { |
18 | tags: string[] = []; | 25 | tags: string[] = []; |
19 | uploader: FileUploader; | 26 | uploader: FileUploader; |
27 | videoCategories = []; | ||
20 | 28 | ||
21 | error: string = null; | 29 | error: string = null; |
22 | form: FormGroup; | 30 | form: FormGroup; |
23 | formErrors = { | 31 | formErrors = { |
24 | name: '', | 32 | name: '', |
33 | category: '', | ||
25 | description: '', | 34 | description: '', |
26 | currentTag: '' | 35 | currentTag: '' |
27 | }; | 36 | }; |
28 | validationMessages = { | 37 | validationMessages = { |
29 | name: VIDEO_NAME.MESSAGES, | 38 | name: VIDEO_NAME.MESSAGES, |
39 | category: VIDEO_CATEGORY.MESSAGES, | ||
30 | description: VIDEO_DESCRIPTION.MESSAGES, | 40 | description: VIDEO_DESCRIPTION.MESSAGES, |
31 | currentTag: VIDEO_TAGS.MESSAGES | 41 | currentTag: VIDEO_TAGS.MESSAGES |
32 | }; | 42 | }; |
@@ -40,7 +50,8 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
40 | private elementRef: ElementRef, | 50 | private elementRef: ElementRef, |
41 | private formBuilder: FormBuilder, | 51 | private formBuilder: FormBuilder, |
42 | private router: Router, | 52 | private router: Router, |
43 | private notificationsService: NotificationsService | 53 | private notificationsService: NotificationsService, |
54 | private videoService: VideoService | ||
44 | ) { | 55 | ) { |
45 | super(); | 56 | super(); |
46 | } | 57 | } |
@@ -56,6 +67,7 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
56 | buildForm() { | 67 | buildForm() { |
57 | this.form = this.formBuilder.group({ | 68 | this.form = this.formBuilder.group({ |
58 | name: [ '', VIDEO_NAME.VALIDATORS ], | 69 | name: [ '', VIDEO_NAME.VALIDATORS ], |
70 | category: [ '', VIDEO_CATEGORY.VALIDATORS ], | ||
59 | description: [ '', VIDEO_DESCRIPTION.VALIDATORS ], | 71 | description: [ '', VIDEO_DESCRIPTION.VALIDATORS ], |
60 | currentTag: [ '', VIDEO_TAGS.VALIDATORS ] | 72 | currentTag: [ '', VIDEO_TAGS.VALIDATORS ] |
61 | }); | 73 | }); |
@@ -64,6 +76,8 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
64 | } | 76 | } |
65 | 77 | ||
66 | ngOnInit() { | 78 | ngOnInit() { |
79 | this.videoCategories = this.videoService.videoCategories; | ||
80 | |||
67 | this.uploader = new FileUploader({ | 81 | this.uploader = new FileUploader({ |
68 | authToken: this.authService.getRequestHeaderValue(), | 82 | authToken: this.authService.getRequestHeaderValue(), |
69 | queueLimit: 1, | 83 | queueLimit: 1, |
@@ -73,9 +87,11 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
73 | 87 | ||
74 | this.uploader.onBuildItemForm = (item, form) => { | 88 | this.uploader.onBuildItemForm = (item, form) => { |
75 | const name = this.form.value['name']; | 89 | const name = this.form.value['name']; |
90 | const category = this.form.value['category']; | ||
76 | const description = this.form.value['description']; | 91 | const description = this.form.value['description']; |
77 | 92 | ||
78 | form.append('name', name); | 93 | form.append('name', name); |
94 | form.append('category', category); | ||
79 | form.append('description', description); | 95 | form.append('description', description); |
80 | 96 | ||
81 | for (let i = 0; i < this.tags.length; i++) { | 97 | for (let i = 0; i < this.tags.length; i++) { |
diff --git a/client/src/app/videos/video-watch/video-watch.component.html b/client/src/app/videos/video-watch/video-watch.component.html index 67094359e..e754d69e5 100644 --- a/client/src/app/videos/video-watch/video-watch.component.html +++ b/client/src/app/videos/video-watch/video-watch.component.html | |||
@@ -107,6 +107,13 @@ | |||
107 | </div> | 107 | </div> |
108 | </div> | 108 | </div> |
109 | 109 | ||
110 | <div id="video-category" class="row"> | ||
111 | <div class="col-md-12"> | ||
112 | <span id="category-label">Category:</span> | ||
113 | {{ video.categoryLabel }} | ||
114 | </div> | ||
115 | </div> | ||
116 | |||
110 | <div id="video-description" class="row"> | 117 | <div id="video-description" class="row"> |
111 | <div class="col-md-12"> | 118 | <div class="col-md-12"> |
112 | <div id="description-label">Description</div> | 119 | <div id="description-label">Description</div> |
diff --git a/client/src/app/videos/video-watch/video-watch.component.scss b/client/src/app/videos/video-watch/video-watch.component.scss index 5f322a194..799e37b5d 100644 --- a/client/src/app/videos/video-watch/video-watch.component.scss +++ b/client/src/app/videos/video-watch/video-watch.component.scss | |||
@@ -111,8 +111,16 @@ | |||
111 | } | 111 | } |
112 | } | 112 | } |
113 | 113 | ||
114 | #video-category { | ||
115 | margin-top: 10px; | ||
116 | |||
117 | #category-label { | ||
118 | font-weight: bold; | ||
119 | } | ||
120 | } | ||
121 | |||
114 | #video-description { | 122 | #video-description { |
115 | margin-top: 15px; | 123 | margin-top: 10px; |
116 | 124 | ||
117 | #description-label { | 125 | #description-label { |
118 | font-weight: bold; | 126 | font-weight: bold; |