aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/app/videos/video-list
diff options
context:
space:
mode:
authorChocobozzz <florian.bigard@gmail.com>2016-05-27 16:23:10 +0200
committerChocobozzz <florian.bigard@gmail.com>2016-05-27 16:23:10 +0200
commit41a2aee38cf812510010da09de9bae53590ec119 (patch)
tree79d55d6ae0ef6f66ccb88890cf1ef1946dc65fb4 /client/app/videos/video-list
parent157cb9c9713e08ff70078660a32dd77ecb87eabc (diff)
downloadPeerTube-41a2aee38cf812510010da09de9bae53590ec119.tar.gz
PeerTube-41a2aee38cf812510010da09de9bae53590ec119.tar.zst
PeerTube-41a2aee38cf812510010da09de9bae53590ec119.zip
Follow the angular styleguide for the directories structure
Diffstat (limited to 'client/app/videos/video-list')
-rw-r--r--client/app/videos/video-list/index.ts3
-rw-r--r--client/app/videos/video-list/video-list.component.html18
-rw-r--r--client/app/videos/video-list/video-list.component.scss37
-rw-r--r--client/app/videos/video-list/video-list.component.ts101
-rw-r--r--client/app/videos/video-list/video-miniature.component.html22
-rw-r--r--client/app/videos/video-list/video-miniature.component.scss55
-rw-r--r--client/app/videos/video-list/video-miniature.component.ts46
-rw-r--r--client/app/videos/video-list/video-sort.component.html5
-rw-r--r--client/app/videos/video-list/video-sort.component.ts36
9 files changed, 323 insertions, 0 deletions
diff --git a/client/app/videos/video-list/index.ts b/client/app/videos/video-list/index.ts
new file mode 100644
index 000000000..1f6d6a4e7
--- /dev/null
+++ b/client/app/videos/video-list/index.ts
@@ -0,0 +1,3 @@
1export * from './video-list.component';
2export * from './video-miniature.component';
3export * from './video-sort.component';
diff --git a/client/app/videos/video-list/video-list.component.html b/client/app/videos/video-list/video-list.component.html
new file mode 100644
index 000000000..edbbaf3ae
--- /dev/null
+++ b/client/app/videos/video-list/video-list.component.html
@@ -0,0 +1,18 @@
1<div class="row videos-info">
2 <div class="col-md-9 videos-total-results"> {{ pagination.total }} videos</div>
3 <my-video-sort class="col-md-3" [currentSort]="sort" (sort)="onSort($event)"></my-video-sort>
4</div>
5
6<div class="videos-miniatures">
7 <my-loader [loading]="loading"></my-loader>
8
9 <div class="col-md-12 no-video" *ngIf="!loading && videos.length === 0">There is no video.</div>
10
11 <my-video-miniature *ngFor="let video of videos" [video]="video" [user]="user" (removed)="onRemoved(video)">
12 </my-video-miniature>
13</div>
14
15<pagination
16 [totalItems]="pagination.total" [itemsPerPage]="pagination.itemsPerPage" [(ngModel)]="pagination.currentPage"
17 (ngModelChange)="getVideos()"
18></pagination>
diff --git a/client/app/videos/video-list/video-list.component.scss b/client/app/videos/video-list/video-list.component.scss
new file mode 100644
index 000000000..9441d80c3
--- /dev/null
+++ b/client/app/videos/video-list/video-list.component.scss
@@ -0,0 +1,37 @@
1.videos-info {
2
3 padding-bottom: 20px;
4 margin-bottom: 20px;
5 border-bottom: 1px solid #f1f1f1;
6 height: 40px;
7 line-height: 40px;
8 width: 765px;
9 margin-left: 15px;
10
11 my-video-sort {
12 padding-right: 0;
13 }
14
15 .videos-total-results {
16 font-size: 13px;
17 padding-left: 0;
18 }
19}
20
21.videos-miniatures {
22 min-height: 600px;
23
24 my-videos-miniature {
25 display: inline-block;
26 }
27
28 .no-video {
29 margin-top: 50px;
30 text-align: center;
31 }
32}
33
34pagination {
35 display: block;
36 text-align: center;
37}
diff --git a/client/app/videos/video-list/video-list.component.ts b/client/app/videos/video-list/video-list.component.ts
new file mode 100644
index 000000000..a88fb379a
--- /dev/null
+++ b/client/app/videos/video-list/video-list.component.ts
@@ -0,0 +1,101 @@
1import { Component, OnInit } from '@angular/core';
2import { Router, ROUTER_DIRECTIVES, RouteParams } from '@angular/router-deprecated';
3
4import { PAGINATION_DIRECTIVES } from 'ng2-bootstrap/components/pagination';
5
6import {
7 LoaderComponent,
8 Pagination,
9 SortField,
10 Video,
11 VideoService
12} from '../shared/index';
13import { Search, SearchField } from '../../shared/index';
14import { AuthService, User } from '../../users/index';
15import { VideoMiniatureComponent } from './video-miniature.component';
16import { VideoSortComponent } from './video-sort.component';
17
18@Component({
19 selector: 'my-videos-list',
20 styleUrls: [ 'client/app/videos/video-list/video-list.component.css' ],
21 templateUrl: 'client/app/videos/video-list/video-list.component.html',
22 directives: [ ROUTER_DIRECTIVES, PAGINATION_DIRECTIVES, VideoMiniatureComponent, VideoSortComponent, LoaderComponent ]
23})
24
25export class VideoListComponent implements OnInit {
26 user: User = null;
27 videos: Video[] = [];
28 pagination: Pagination = {
29 currentPage: 1,
30 itemsPerPage: 9,
31 total: 0
32 };
33 sort: SortField;
34 loading: boolean = false;
35
36 private search: Search;
37
38 constructor(
39 private _authService: AuthService,
40 private _videoService: VideoService,
41 private _routeParams: RouteParams,
42 private _router: Router
43 ) {
44 this.search = {
45 value: this._routeParams.get('search'),
46 field: <SearchField>this._routeParams.get('field')
47 };
48
49 this.sort = <SortField>this._routeParams.get('sort') || '-createdDate';
50 }
51
52 ngOnInit() {
53 if (this._authService.isLoggedIn()) {
54 this.user = User.load();
55 }
56
57 this.getVideos();
58 }
59
60 getVideos() {
61 this.loading = true;
62 this.videos = [];
63
64 let observable = null;
65
66 if (this.search.value !== null) {
67 observable = this._videoService.searchVideos(this.search, this.pagination, this.sort);
68 } else {
69 observable = this._videoService.getVideos(this.pagination, this.sort);
70 }
71
72 observable.subscribe(
73 ({ videos, totalVideos }) => {
74 this.videos = videos;
75 this.pagination.total = totalVideos;
76 this.loading = false;
77 },
78 error => alert(error)
79 );
80 }
81
82 onRemoved(video: Video): void {
83 this.videos.splice(this.videos.indexOf(video), 1);
84 }
85
86 onSort(sort: SortField) {
87 this.sort = sort;
88
89 const params: any = {
90 sort: this.sort
91 };
92
93 if (this.search.value) {
94 params.search = this.search.value;
95 params.field = this.search.field;
96 }
97
98 this._router.navigate(['VideosList', params]);
99 this.getVideos();
100 }
101}
diff --git a/client/app/videos/video-list/video-miniature.component.html b/client/app/videos/video-list/video-miniature.component.html
new file mode 100644
index 000000000..244254b5a
--- /dev/null
+++ b/client/app/videos/video-list/video-miniature.component.html
@@ -0,0 +1,22 @@
1<div class="video-miniature col-md-4" (mouseenter)="onHover()" (mouseleave)="onBlur()">
2 <a
3 [routerLink]="['VideosWatch', { id: video.id }]" [attr.title]="video.description"
4 class="video-miniature-thumbnail"
5 >
6 <img [attr.src]="video.thumbnailPath" alt="video thumbnail" />
7 <span class="video-miniature-duration">{{ video.duration }}</span>
8 </a>
9 <span
10 *ngIf="displayRemoveIcon()" (click)="removeVideo(video.id)"
11 class="video-miniature-remove glyphicon glyphicon-remove"
12 ></span>
13
14 <div class="video-miniature-informations">
15 <a [routerLink]="['VideosWatch', { id: video.id }]" class="video-miniature-name">
16 <span>{{ video.name }}</span>
17 </a>
18
19 <span class="video-miniature-author">by {{ video.by }}</span>
20 <span class="video-miniature-created-date">on {{ video.createdDate | date:'short' }}</span>
21 </div>
22</div>
diff --git a/client/app/videos/video-list/video-miniature.component.scss b/client/app/videos/video-list/video-miniature.component.scss
new file mode 100644
index 000000000..4488abe22
--- /dev/null
+++ b/client/app/videos/video-list/video-miniature.component.scss
@@ -0,0 +1,55 @@
1.video-miniature {
2 height: 200px;
3 display: inline-block;
4 position: relative;
5
6 .video-miniature-thumbnail {
7 display: block;
8 position: relative;
9
10 .video-miniature-duration {
11 position: absolute;
12 right: 60px;
13 bottom: 2px;
14 display: inline-block;
15 background-color: rgba(0, 0, 0, 0.8);
16 color: rgba(255, 255, 255, 0.8);
17 padding: 2px;
18 font-size: 11px;
19 }
20 }
21
22 .video-miniature-remove {
23 display: inline-block;
24 position: absolute;
25 left: 16px;
26 background-color: rgba(0, 0, 0, 0.8);
27 color: rgba(255, 255, 255, 0.8);
28 padding: 2px;
29 cursor: pointer;
30
31 &:hover {
32 color: rgba(255, 255, 255, 0.9);
33 }
34 }
35
36 .video-miniature-informations {
37 margin-left: 3px;
38
39 .video-miniature-name {
40 display: block;
41 font-weight: bold;
42
43 &:hover {
44 text-decoration: none;
45 }
46 }
47
48 .video-miniature-author, .video-miniature-created-date {
49 display: block;
50 margin-left: 1px;
51 font-size: 11px;
52 color: rgba(0, 0, 0, 0.5);
53 }
54 }
55}
diff --git a/client/app/videos/video-list/video-miniature.component.ts b/client/app/videos/video-list/video-miniature.component.ts
new file mode 100644
index 000000000..817636768
--- /dev/null
+++ b/client/app/videos/video-list/video-miniature.component.ts
@@ -0,0 +1,46 @@
1import { DatePipe } from '@angular/common';
2import { Component, Input, Output, EventEmitter } from '@angular/core';
3import { ROUTER_DIRECTIVES } from '@angular/router-deprecated';
4
5import { Video, VideoService } from '../shared/index';
6import { User } from '../../users/index';
7
8@Component({
9 selector: 'my-video-miniature',
10 styleUrls: [ 'client/app/videos/video-list/video-miniature.component.css' ],
11 templateUrl: 'client/app/videos/video-list/video-miniature.component.html',
12 directives: [ ROUTER_DIRECTIVES ],
13 pipes: [ DatePipe ]
14})
15
16export class VideoMiniatureComponent {
17 @Output() removed = new EventEmitter<any>();
18
19 @Input() video: Video;
20 @Input() user: User;
21
22 hovering: boolean = false;
23
24 constructor(private _videoService: VideoService) {}
25
26 onHover() {
27 this.hovering = true;
28 }
29
30 onBlur() {
31 this.hovering = false;
32 }
33
34 displayRemoveIcon(): boolean {
35 return this.hovering && this.video.isRemovableBy(this.user);
36 }
37
38 removeVideo(id: string) {
39 if (confirm('Do you really want to remove this video?')) {
40 this._videoService.removeVideo(id).subscribe(
41 status => this.removed.emit(true),
42 error => alert(error)
43 );
44 }
45 }
46}
diff --git a/client/app/videos/video-list/video-sort.component.html b/client/app/videos/video-list/video-sort.component.html
new file mode 100644
index 000000000..3bece0b22
--- /dev/null
+++ b/client/app/videos/video-list/video-sort.component.html
@@ -0,0 +1,5 @@
1<select class="form-control input-sm" [(ngModel)]="currentSort" (ngModelChange)="onSortChange()">
2 <option *ngFor="let choice of choiceKeys" [value]="choice">
3 {{ getStringChoice(choice) }}
4 </option>
5</select>
diff --git a/client/app/videos/video-list/video-sort.component.ts b/client/app/videos/video-list/video-sort.component.ts
new file mode 100644
index 000000000..d00d7ed49
--- /dev/null
+++ b/client/app/videos/video-list/video-sort.component.ts
@@ -0,0 +1,36 @@
1import { Component, EventEmitter, Input, Output } from '@angular/core';
2
3import { SortField } from '../shared/index';
4
5@Component({
6 selector: 'my-video-sort',
7 // styleUrls: [ 'app/angular/videos/components/list/video-sort.component.css' ],
8 templateUrl: 'client/app/videos/video-list/video-sort.component.html'
9})
10
11export class VideoSortComponent {
12 @Output() sort = new EventEmitter<any>();
13
14 @Input() currentSort: SortField;
15
16 sortChoices = {
17 'name': 'Name - Asc',
18 '-name': 'Name - Desc',
19 'duration': 'Duration - Asc',
20 '-duration': 'Duration - Desc',
21 'createdDate': 'Created Date - Asc',
22 '-createdDate': 'Created Date - Desc'
23 };
24
25 get choiceKeys() {
26 return Object.keys(this.sortChoices);
27 }
28
29 getStringChoice(choiceKey: SortField): string {
30 return this.sortChoices[choiceKey];
31 }
32
33 onSortChange() {
34 this.sort.emit(this.currentSort);
35 }
36}