diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2016-06-10 17:43:40 +0200 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2016-06-10 17:46:29 +0200 |
commit | 00a446454d4721fc49517815655f6b4f8a17b554 (patch) | |
tree | 26f41fc11c059d5b051a98099857db971623b5d9 /client/src/app/videos | |
parent | e822fdaeee90cb7c70d5678f19249198cd7aae8c (diff) | |
download | PeerTube-00a446454d4721fc49517815655f6b4f8a17b554.tar.gz PeerTube-00a446454d4721fc49517815655f6b4f8a17b554.tar.zst PeerTube-00a446454d4721fc49517815655f6b4f8a17b554.zip |
Add tags support to the video list
Diffstat (limited to 'client/src/app/videos')
8 files changed, 79 insertions, 34 deletions
diff --git a/client/src/app/videos/shared/video.model.ts b/client/src/app/videos/shared/video.model.ts index 614403d79..65417f751 100644 --- a/client/src/app/videos/shared/video.model.ts +++ b/client/src/app/videos/shared/video.model.ts | |||
@@ -9,6 +9,7 @@ export class Video { | |||
9 | magnetUri: string; | 9 | magnetUri: string; |
10 | name: string; | 10 | name: string; |
11 | podUrl: string; | 11 | podUrl: string; |
12 | tags: string[]; | ||
12 | thumbnailPath: string; | 13 | thumbnailPath: string; |
13 | 14 | ||
14 | private static createByString(author: string, podUrl: string) { | 15 | private static createByString(author: string, podUrl: string) { |
@@ -42,6 +43,7 @@ export class Video { | |||
42 | magnetUri: string, | 43 | magnetUri: string, |
43 | name: string, | 44 | name: string, |
44 | podUrl: string, | 45 | podUrl: string, |
46 | tags: string[], | ||
45 | thumbnailPath: string | 47 | thumbnailPath: string |
46 | }) { | 48 | }) { |
47 | this.author = hash.author; | 49 | this.author = hash.author; |
@@ -53,6 +55,7 @@ export class Video { | |||
53 | this.magnetUri = hash.magnetUri; | 55 | this.magnetUri = hash.magnetUri; |
54 | this.name = hash.name; | 56 | this.name = hash.name; |
55 | this.podUrl = hash.podUrl; | 57 | this.podUrl = hash.podUrl; |
58 | this.tags = hash.tags; | ||
56 | this.thumbnailPath = hash.thumbnailPath; | 59 | this.thumbnailPath = hash.thumbnailPath; |
57 | 60 | ||
58 | this.by = Video.createByString(hash.author, hash.podUrl); | 61 | this.by = Video.createByString(hash.author, hash.podUrl); |
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 6b2eb9377..bcd78c7cb 100644 --- a/client/src/app/videos/video-add/video-add.component.html +++ b/client/src/app/videos/video-add/video-add.component.html | |||
@@ -21,12 +21,12 @@ | |||
21 | ngControl="tags" #tags="ngForm" [disabled]="isTagsInputDisabled" (keyup)="onTagKeyPress($event)" [(ngModel)]="currentTag" | 21 | ngControl="tags" #tags="ngForm" [disabled]="isTagsInputDisabled" (keyup)="onTagKeyPress($event)" [(ngModel)]="currentTag" |
22 | > | 22 | > |
23 | <div [hidden]="tags.valid || tags.pristine" class="alert alert-warning"> | 23 | <div [hidden]="tags.valid || tags.pristine" class="alert alert-warning"> |
24 | A tag should be between 2 and 10 characters long | 24 | A tag should be between 2 and 10 characters (alphanumeric) long |
25 | </div> | 25 | </div> |
26 | </div> | 26 | </div> |
27 | 27 | ||
28 | <div class="tags"> | 28 | <div class="tags"> |
29 | <div class="label label-info tag" *ngFor="let tag of video.tags"> | 29 | <div class="label label-primary tag" *ngFor="let tag of video.tags"> |
30 | {{ tag }} | 30 | {{ tag }} |
31 | <span class="remove" (click)="removeTag(tag)">x</span> | 31 | <span class="remove" (click)="removeTag(tag)">x</span> |
32 | </div> | 32 | </div> |
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 2b45ea125..7d8fbdc29 100644 --- a/client/src/app/videos/video-add/video-add.component.ts +++ b/client/src/app/videos/video-add/video-add.component.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { Control, ControlGroup, Validators } from '@angular/common'; | 1 | import { Control, ControlGroup, Validators } from '@angular/common'; |
2 | import { Component, ElementRef, OnInit } from '@angular/core'; | 2 | import { Component, ElementRef, OnInit } from '@angular/core'; |
3 | import { Router } from '@angular/router-deprecated'; | 3 | import { Router } from '@angular/router'; |
4 | 4 | ||
5 | import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe'; | 5 | import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe'; |
6 | import { PROGRESSBAR_DIRECTIVES } from 'ng2-bootstrap/components/progressbar'; | 6 | import { PROGRESSBAR_DIRECTIVES } from 'ng2-bootstrap/components/progressbar'; |
diff --git a/client/src/app/videos/video-list/video-list.component.ts b/client/src/app/videos/video-list/video-list.component.ts index 059317383..46263eb65 100644 --- a/client/src/app/videos/video-list/video-list.component.ts +++ b/client/src/app/videos/video-list/video-list.component.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { Component, OnInit } from '@angular/core'; | 1 | import { Component, OnInit } from '@angular/core'; |
2 | import { Router, ROUTER_DIRECTIVES, RouteParams } from '@angular/router-deprecated'; | 2 | import { Router, ROUTER_DIRECTIVES, RouteSegment } from '@angular/router'; |
3 | 3 | ||
4 | import { PAGINATION_DIRECTIVES } from 'ng2-bootstrap/components/pagination'; | 4 | import { PAGINATION_DIRECTIVES } from 'ng2-bootstrap/components/pagination'; |
5 | 5 | ||
@@ -13,6 +13,7 @@ import { | |||
13 | import { AuthService, Search, SearchField, User } from '../../shared'; | 13 | import { AuthService, Search, SearchField, User } from '../../shared'; |
14 | import { VideoMiniatureComponent } from './video-miniature.component'; | 14 | import { VideoMiniatureComponent } from './video-miniature.component'; |
15 | import { VideoSortComponent } from './video-sort.component'; | 15 | import { VideoSortComponent } from './video-sort.component'; |
16 | import { SearchService } from '../../shared'; | ||
16 | 17 | ||
17 | @Component({ | 18 | @Component({ |
18 | selector: 'my-videos-list', | 19 | selector: 'my-videos-list', |
@@ -37,22 +38,26 @@ export class VideoListComponent implements OnInit { | |||
37 | constructor( | 38 | constructor( |
38 | private authService: AuthService, | 39 | private authService: AuthService, |
39 | private router: Router, | 40 | private router: Router, |
40 | private routeParams: RouteParams, | 41 | private routeSegment: RouteSegment, |
41 | private videoService: VideoService | 42 | private videoService: VideoService, |
42 | ) { | 43 | private searchService: SearchService // Temporary |
43 | this.search = { | 44 | ) {} |
44 | value: this.routeParams.get('search'), | ||
45 | field: <SearchField>this.routeParams.get('field') | ||
46 | }; | ||
47 | |||
48 | this.sort = <SortField>this.routeParams.get('sort') || '-createdDate'; | ||
49 | } | ||
50 | 45 | ||
51 | ngOnInit() { | 46 | ngOnInit() { |
52 | if (this.authService.isLoggedIn()) { | 47 | if (this.authService.isLoggedIn()) { |
53 | this.user = User.load(); | 48 | this.user = User.load(); |
54 | } | 49 | } |
55 | 50 | ||
51 | this.search = { | ||
52 | value: this.routeSegment.getParam('search'), | ||
53 | field: <SearchField>this.routeSegment.getParam('field') | ||
54 | }; | ||
55 | |||
56 | // Temporary | ||
57 | this.searchChanged(this.search); | ||
58 | |||
59 | this.sort = <SortField>this.routeSegment.getParam('sort') || '-createdDate'; | ||
60 | |||
56 | this.getVideos(); | 61 | this.getVideos(); |
57 | } | 62 | } |
58 | 63 | ||
@@ -62,7 +67,7 @@ export class VideoListComponent implements OnInit { | |||
62 | 67 | ||
63 | let observable = null; | 68 | let observable = null; |
64 | 69 | ||
65 | if (this.search.value !== null) { | 70 | if (this.search.value) { |
66 | observable = this.videoService.searchVideos(this.search, this.pagination, this.sort); | 71 | observable = this.videoService.searchVideos(this.search, this.pagination, this.sort); |
67 | } else { | 72 | } else { |
68 | observable = this.videoService.getVideos(this.pagination, this.sort); | 73 | observable = this.videoService.getVideos(this.pagination, this.sort); |
@@ -99,7 +104,10 @@ export class VideoListComponent implements OnInit { | |||
99 | params.search = this.search.value; | 104 | params.search = this.search.value; |
100 | } | 105 | } |
101 | 106 | ||
102 | this.router.navigate(['VideosList', params]); | 107 | this.router.navigate(['/videos/list', params]); |
103 | this.getVideos(); | 108 | } |
109 | |||
110 | searchChanged(search: Search) { | ||
111 | this.searchService.searchChanged.next(search); | ||
104 | } | 112 | } |
105 | } | 113 | } |
diff --git a/client/src/app/videos/video-list/video-miniature.component.html b/client/src/app/videos/video-list/video-miniature.component.html index 244254b5a..92e19bb8b 100644 --- a/client/src/app/videos/video-list/video-miniature.component.html +++ b/client/src/app/videos/video-list/video-miniature.component.html | |||
@@ -1,6 +1,6 @@ | |||
1 | <div class="video-miniature col-md-4" (mouseenter)="onHover()" (mouseleave)="onBlur()"> | 1 | <div class="video-miniature col-md-4" (mouseenter)="onHover()" (mouseleave)="onBlur()"> |
2 | <a | 2 | <a |
3 | [routerLink]="['VideosWatch', { id: video.id }]" [attr.title]="video.description" | 3 | [routerLink]="['/videos/watch', video.id]" [attr.title]="video.description" |
4 | class="video-miniature-thumbnail" | 4 | class="video-miniature-thumbnail" |
5 | > | 5 | > |
6 | <img [attr.src]="video.thumbnailPath" alt="video thumbnail" /> | 6 | <img [attr.src]="video.thumbnailPath" alt="video thumbnail" /> |
@@ -12,11 +12,15 @@ | |||
12 | ></span> | 12 | ></span> |
13 | 13 | ||
14 | <div class="video-miniature-informations"> | 14 | <div class="video-miniature-informations"> |
15 | <a [routerLink]="['VideosWatch', { id: video.id }]" class="video-miniature-name"> | 15 | <span class="video-miniature-name-tags"> |
16 | <span>{{ video.name }}</span> | 16 | <a [routerLink]="['/videos/watch', video.id]" class="video-miniature-name">{{ video.name }}</a> |
17 | </a> | ||
18 | 17 | ||
19 | <span class="video-miniature-author">by {{ video.by }}</span> | 18 | <span *ngFor="let tag of video.tags" class="video-miniature-tag"> |
19 | <a [routerLink]="['/videos/list', { field: 'tags', search: tag }]" class="label label-primary">{{ tag }}</a> | ||
20 | </span> | ||
21 | </span> | ||
22 | |||
23 | <a [routerLink]="['/videos/list', { field: 'author', search: video.author }]" class="video-miniature-author">by {{ video.by }}</a> | ||
20 | <span class="video-miniature-created-date">on {{ video.createdDate | date:'short' }}</span> | 24 | <span class="video-miniature-created-date">on {{ video.createdDate | date:'short' }}</span> |
21 | </div> | 25 | </div> |
22 | </div> | 26 | </div> |
diff --git a/client/src/app/videos/video-list/video-miniature.component.scss b/client/src/app/videos/video-list/video-miniature.component.scss index 3aa0ca63b..40d37b83f 100644 --- a/client/src/app/videos/video-list/video-miniature.component.scss +++ b/client/src/app/videos/video-list/video-miniature.component.scss | |||
@@ -1,5 +1,5 @@ | |||
1 | .video-miniature { | 1 | .video-miniature { |
2 | height: 200px; | 2 | margin-top: 30px; |
3 | display: inline-block; | 3 | display: inline-block; |
4 | position: relative; | 4 | position: relative; |
5 | 5 | ||
@@ -35,13 +35,34 @@ | |||
35 | 35 | ||
36 | .video-miniature-informations { | 36 | .video-miniature-informations { |
37 | margin-left: 3px; | 37 | margin-left: 3px; |
38 | width: 200px; | ||
38 | 39 | ||
39 | .video-miniature-name { | 40 | .video-miniature-name-tags { |
40 | display: block; | 41 | display: block; |
41 | font-weight: bold; | ||
42 | 42 | ||
43 | &:hover { | 43 | .video-miniature-name { |
44 | text-decoration: none; | 44 | font-weight: bold; |
45 | |||
46 | &:hover { | ||
47 | text-decoration: none; | ||
48 | } | ||
49 | |||
50 | &::after { | ||
51 | content: '\002022'; | ||
52 | margin-left: 3px; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | .video-miniature-tag { | ||
57 | font-size: 12px; | ||
58 | cursor: pointer; | ||
59 | transition: opacity 0.5s; | ||
60 | position: relative; | ||
61 | top: -2px; | ||
62 | |||
63 | &:hover { | ||
64 | opacity: 0.9; | ||
65 | } | ||
45 | } | 66 | } |
46 | } | 67 | } |
47 | 68 | ||
@@ -49,7 +70,16 @@ | |||
49 | display: block; | 70 | display: block; |
50 | margin-left: 1px; | 71 | margin-left: 1px; |
51 | font-size: 11px; | 72 | font-size: 11px; |
52 | color: rgba(0, 0, 0, 0.5); | 73 | color: rgb(54, 118, 173); |
74 | } | ||
75 | |||
76 | .video-miniature-author { | ||
77 | transition: opacity 0.5s; | ||
78 | |||
79 | &:hover { | ||
80 | text-decoration: none; | ||
81 | opacity: 0.9; | ||
82 | } | ||
53 | } | 83 | } |
54 | } | 84 | } |
55 | } | 85 | } |
diff --git a/client/src/app/videos/video-list/video-miniature.component.ts b/client/src/app/videos/video-list/video-miniature.component.ts index 639339b44..90645d67f 100644 --- a/client/src/app/videos/video-list/video-miniature.component.ts +++ b/client/src/app/videos/video-list/video-miniature.component.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { DatePipe } from '@angular/common'; | 1 | import { DatePipe } from '@angular/common'; |
2 | import { Component, Input, Output, EventEmitter } from '@angular/core'; | 2 | import { Component, Input, Output, EventEmitter } from '@angular/core'; |
3 | import { ROUTER_DIRECTIVES } from '@angular/router-deprecated'; | 3 | import { ROUTER_DIRECTIVES } from '@angular/router'; |
4 | 4 | ||
5 | import { Video, VideoService } from '../shared'; | 5 | import { Video, VideoService } from '../shared'; |
6 | import { User } from '../../shared'; | 6 | import { User } from '../../shared'; |
diff --git a/client/src/app/videos/video-watch/video-watch.component.ts b/client/src/app/videos/video-watch/video-watch.component.ts index 05e844f60..99188bfb3 100644 --- a/client/src/app/videos/video-watch/video-watch.component.ts +++ b/client/src/app/videos/video-watch/video-watch.component.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { Component, ElementRef, OnInit } from '@angular/core'; | 1 | import { Component, ElementRef, OnInit } from '@angular/core'; |
2 | import { CanDeactivate, ComponentInstruction, RouteParams } from '@angular/router-deprecated'; | 2 | import { CanDeactivate, RouteSegment } from '@angular/router'; |
3 | 3 | ||
4 | import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe'; | 4 | import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe'; |
5 | 5 | ||
@@ -30,7 +30,7 @@ export class VideoWatchComponent implements OnInit, CanDeactivate { | |||
30 | 30 | ||
31 | constructor( | 31 | constructor( |
32 | private elementRef: ElementRef, | 32 | private elementRef: ElementRef, |
33 | private routeParams: RouteParams, | 33 | private routeSegment: RouteSegment, |
34 | private videoService: VideoService, | 34 | private videoService: VideoService, |
35 | private webTorrentService: WebTorrentService | 35 | private webTorrentService: WebTorrentService |
36 | ) {} | 36 | ) {} |
@@ -74,7 +74,7 @@ export class VideoWatchComponent implements OnInit, CanDeactivate { | |||
74 | } | 74 | } |
75 | 75 | ||
76 | ngOnInit() { | 76 | ngOnInit() { |
77 | let id = this.routeParams.get('id'); | 77 | let id = this.routeSegment.getParam('id'); |
78 | this.videoService.getVideo(id).subscribe( | 78 | this.videoService.getVideo(id).subscribe( |
79 | video => { | 79 | video => { |
80 | this.video = video; | 80 | this.video = video; |
@@ -84,11 +84,11 @@ export class VideoWatchComponent implements OnInit, CanDeactivate { | |||
84 | ); | 84 | ); |
85 | } | 85 | } |
86 | 86 | ||
87 | routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction) { | 87 | routerCanDeactivate() { |
88 | console.log('Removing video from webtorrent.'); | 88 | console.log('Removing video from webtorrent.'); |
89 | clearInterval(this.torrentInfosInterval); | 89 | clearInterval(this.torrentInfosInterval); |
90 | this.webTorrentService.remove(this.video.magnetUri); | 90 | this.webTorrentService.remove(this.video.magnetUri); |
91 | return true; | 91 | return Promise.resolve(true); |
92 | } | 92 | } |
93 | 93 | ||
94 | private loadTooLong() { | 94 | private loadTooLong() { |