Fix client search
[oweals/peertube.git] / client / src / app / shared / video / abstract-video-list.ts
1 import { OnInit } from '@angular/core'
2 import { ActivatedRoute, Router } from '@angular/router'
3 import { NotificationsService } from 'angular2-notifications'
4 import { Observable } from 'rxjs/Observable'
5 import { SortField } from './sort-field.type'
6 import { VideoPagination } from './video-pagination.model'
7 import { Video } from './video.model'
8
9 export abstract class AbstractVideoList implements OnInit {
10   pagination: VideoPagination = {
11     currentPage: 1,
12     itemsPerPage: 25,
13     totalItems: null
14   }
15   sort: SortField = '-createdAt'
16   defaultSort: SortField = '-createdAt'
17   videos: Video[] = []
18   loadOnInit = true
19
20   protected notificationsService: NotificationsService
21   protected router: Router
22   protected route: ActivatedRoute
23
24   protected abstract currentRoute: string
25
26   abstract titlePage: string
27   private loadedPages: { [ id: number ]: boolean } = {}
28
29   abstract getVideosObservable (): Observable<{ videos: Video[], totalVideos: number}>
30
31   ngOnInit () {
32     // Subscribe to route changes
33     const routeParams = this.route.snapshot.params
34     this.loadRouteParams(routeParams)
35     if (this.loadOnInit === true) this.loadMoreVideos('after')
36   }
37
38   onNearOfTop () {
39     if (this.pagination.currentPage > 1) {
40       this.previousPage()
41     }
42   }
43
44   onNearOfBottom () {
45     if (this.hasMoreVideos()) {
46       this.nextPage()
47     }
48   }
49
50   reloadVideos () {
51     this.videos = []
52     this.loadedPages = {}
53     this.loadMoreVideos('before')
54   }
55
56   loadMoreVideos (where: 'before' | 'after') {
57     if (this.loadedPages[this.pagination.currentPage] === true) return
58
59     const observable = this.getVideosObservable()
60
61     observable.subscribe(
62       ({ videos, totalVideos }) => {
63         this.loadedPages[this.pagination.currentPage] = true
64         this.pagination.totalItems = totalVideos
65
66         if (where === 'before') {
67           this.videos = videos.concat(this.videos)
68         } else {
69           this.videos = this.videos.concat(videos)
70         }
71       },
72       error => this.notificationsService.error('Error', error.text)
73     )
74   }
75
76   protected hasMoreVideos () {
77     if (!this.pagination.totalItems) return true
78
79     const maxPage = this.pagination.totalItems / this.pagination.itemsPerPage
80     return maxPage > this.pagination.currentPage
81   }
82
83   protected previousPage () {
84     this.pagination.currentPage--
85
86     this.setNewRouteParams()
87     this.loadMoreVideos('before')
88   }
89
90   protected nextPage () {
91     this.pagination.currentPage++
92
93     this.setNewRouteParams()
94     this.loadMoreVideos('after')
95   }
96
97   protected buildRouteParams () {
98     // There is always a sort and a current page
99     const params = {
100       sort: this.sort,
101       page: this.pagination.currentPage
102     }
103
104     return params
105   }
106
107   protected loadRouteParams (routeParams: { [ key: string ]: any }) {
108     this.sort = routeParams['sort'] as SortField || this.defaultSort
109
110     if (routeParams['page'] !== undefined) {
111       this.pagination.currentPage = parseInt(routeParams['page'], 10)
112     } else {
113       this.pagination.currentPage = 1
114     }
115   }
116
117   protected setNewRouteParams () {
118     const routeParams = this.buildRouteParams()
119     this.router.navigate([ this.currentRoute, routeParams ])
120   }
121 }