Add video comment components
[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 { AuthService } from '../../core/auth'
6 import { ComponentPagination } from '../rest/component-pagination.model'
7 import { SortField } from './sort-field.type'
8 import { Video } from './video.model'
9
10 export abstract class AbstractVideoList implements OnInit {
11   pagination: ComponentPagination = {
12     currentPage: 1,
13     itemsPerPage: 25,
14     totalItems: null
15   }
16   sort: SortField = '-createdAt'
17   defaultSort: SortField = '-createdAt'
18   videos: Video[] = []
19   loadOnInit = true
20
21   protected abstract notificationsService: NotificationsService
22   protected abstract authService: AuthService
23   protected abstract router: Router
24   protected abstract route: ActivatedRoute
25
26   protected abstract currentRoute: string
27
28   abstract titlePage: string
29   private loadedPages: { [ id: number ]: boolean } = {}
30
31   abstract getVideosObservable (): Observable<{ videos: Video[], totalVideos: number}>
32
33   get user () {
34     return this.authService.getUser()
35   }
36
37   ngOnInit () {
38     // Subscribe to route changes
39     const routeParams = this.route.snapshot.params
40     this.loadRouteParams(routeParams)
41
42     if (this.loadOnInit === true) this.loadMoreVideos('after')
43   }
44
45   onNearOfTop () {
46     if (this.pagination.currentPage > 1) {
47       this.previousPage()
48     }
49   }
50
51   onNearOfBottom () {
52     if (this.hasMoreVideos()) {
53       this.nextPage()
54     }
55   }
56
57   reloadVideos () {
58     this.videos = []
59     this.loadedPages = {}
60     this.loadMoreVideos('before')
61   }
62
63   loadMoreVideos (where: 'before' | 'after') {
64     if (this.loadedPages[this.pagination.currentPage] === true) return
65
66     const observable = this.getVideosObservable()
67
68     observable.subscribe(
69       ({ videos, totalVideos }) => {
70         // Paging is too high, return to the first one
71         if (this.pagination.currentPage > 1 && totalVideos <= ((this.pagination.currentPage - 1) * this.pagination.itemsPerPage)) {
72           this.pagination.currentPage = 1
73           this.setNewRouteParams()
74           return this.reloadVideos()
75         }
76
77         this.loadedPages[this.pagination.currentPage] = true
78         this.pagination.totalItems = totalVideos
79
80         if (where === 'before') {
81           this.videos = videos.concat(this.videos)
82         } else {
83           this.videos = this.videos.concat(videos)
84         }
85       },
86       error => this.notificationsService.error('Error', error.text)
87     )
88   }
89
90   protected hasMoreVideos () {
91     // No results
92     if (this.pagination.totalItems === 0) return false
93
94     // Not loaded yet
95     if (!this.pagination.totalItems) return true
96
97     const maxPage = this.pagination.totalItems / this.pagination.itemsPerPage
98     return maxPage > this.pagination.currentPage
99   }
100
101   protected previousPage () {
102     this.pagination.currentPage--
103
104     this.setNewRouteParams()
105     this.loadMoreVideos('before')
106   }
107
108   protected nextPage () {
109     this.pagination.currentPage++
110
111     this.setNewRouteParams()
112     this.loadMoreVideos('after')
113   }
114
115   protected buildRouteParams () {
116     // There is always a sort and a current page
117     const params = {
118       sort: this.sort,
119       page: this.pagination.currentPage
120     }
121
122     return params
123   }
124
125   protected loadRouteParams (routeParams: { [ key: string ]: any }) {
126     this.sort = routeParams['sort'] as SortField || this.defaultSort
127
128     if (routeParams['page'] !== undefined) {
129       this.pagination.currentPage = parseInt(routeParams['page'], 10)
130     } else {
131       this.pagination.currentPage = 1
132     }
133   }
134
135   protected setNewRouteParams () {
136     const routeParams = this.buildRouteParams()
137     this.router.navigate([ this.currentRoute, routeParams ])
138   }
139 }