aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/shared/video/abstract-video-list.ts
blob: cf717cf4cb3a1e75a6424f4affb88cb3af783a5f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { OnDestroy, OnInit } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { NotificationsService } from 'angular2-notifications'
import { Observable } from 'rxjs/Observable'
import { Subscription } from 'rxjs/Subscription'
import { SortField } from './sort-field.type'
import { VideoPagination } from './video-pagination.model'
import { Video } from './video.model'

export abstract class AbstractVideoList implements OnInit, OnDestroy {
  pagination: VideoPagination = {
    currentPage: 1,
    itemsPerPage: 25,
    totalItems: null
  }
  sort: SortField = '-createdAt'
  videos: Video[] = []

  protected notificationsService: NotificationsService
  protected router: Router
  protected route: ActivatedRoute
  protected subActivatedRoute: Subscription

  protected abstract currentRoute: string

  abstract titlePage: string
  private loadedPages: { [ id: number ]: boolean } = {}

  abstract getVideosObservable (): Observable<{ videos: Video[], totalVideos: number}>

  ngOnInit () {
    // Subscribe to route changes
    const routeParams = this.route.snapshot.params
    this.loadRouteParams(routeParams)
    this.loadMoreVideos('after')
  }

  ngOnDestroy () {
    if (this.subActivatedRoute) {
      this.subActivatedRoute.unsubscribe()
    }
  }

  onNearOfTop () {
    if (this.pagination.currentPage > 1) {
      this.previousPage()
    }
  }

  onNearOfBottom () {
    if (this.hasMoreVideos()) {
      this.nextPage()
    }
  }

  loadMoreVideos (where: 'before' | 'after') {
    if (this.loadedPages[this.pagination.currentPage] === true) return

    const observable = this.getVideosObservable()

    observable.subscribe(
      ({ videos, totalVideos }) => {
        this.loadedPages[this.pagination.currentPage] = true
        this.pagination.totalItems = totalVideos

        if (where === 'before') {
          this.videos = videos.concat(this.videos)
        } else {
          this.videos = this.videos.concat(videos)
        }
      },
      error => this.notificationsService.error('Error', error.text)
    )
  }

  protected hasMoreVideos () {
    if (!this.pagination.totalItems) return true

    const maxPage = this.pagination.totalItems / this.pagination.itemsPerPage
    return maxPage > this.pagination.currentPage
  }

  protected previousPage () {
    this.pagination.currentPage--

    this.setNewRouteParams()
    this.loadMoreVideos('before')
  }

  protected nextPage () {
    this.pagination.currentPage++

    this.setNewRouteParams()
    this.loadMoreVideos('after')
  }

  protected buildRouteParams () {
    // There is always a sort and a current page
    const params = {
      sort: this.sort,
      page: this.pagination.currentPage
    }

    return params
  }

  protected loadRouteParams (routeParams: { [ key: string ]: any }) {
    this.sort = routeParams['sort'] as SortField || '-createdAt'

    if (routeParams['page'] !== undefined) {
      this.pagination.currentPage = parseInt(routeParams['page'], 10)
    } else {
      this.pagination.currentPage = 1
    }
  }

  protected setNewRouteParams () {
    const routeParams = this.buildRouteParams()
    this.router.navigate([ this.currentRoute, routeParams ])
  }
}