Factorize rest-table and fix/simplify SQL
[oweals/peertube.git] / client / src / app / +admin / follows / video-redundancies-list / video-redundancies-list.component.ts
1 import { Component, OnInit } from '@angular/core'
2 import { Notifier, ServerService } from '@app/core'
3 import { SortMeta } from 'primeng/api'
4 import { ConfirmService } from '../../../core/confirm/confirm.service'
5 import { RestPagination, RestTable } from '../../../shared'
6 import { I18n } from '@ngx-translate/i18n-polyfill'
7 import { VideoRedundanciesTarget, VideoRedundancy } from '@shared/models'
8 import { peertubeLocalStorage } from '@app/shared/misc/peertube-web-storage'
9 import { VideosRedundancyStats } from '@shared/models/server'
10 import { BytesPipe } from 'ngx-pipes'
11 import { RedundancyService } from '@app/shared/video/redundancy.service'
12
13 @Component({
14   selector: 'my-video-redundancies-list',
15   templateUrl: './video-redundancies-list.component.html',
16   styleUrls: [ '../follows.component.scss', './video-redundancies-list.component.scss' ]
17 })
18 export class VideoRedundanciesListComponent extends RestTable implements OnInit {
19   private static LOCAL_STORAGE_DISPLAY_TYPE = 'video-redundancies-list-display-type'
20
21   videoRedundancies: VideoRedundancy[] = []
22   totalRecords = 0
23
24   sort: SortMeta = { field: 'name', order: 1 }
25   pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
26   displayType: VideoRedundanciesTarget = 'my-videos'
27
28   redundanciesGraphsData: { stats: VideosRedundancyStats, graphData: object, options: object }[] = []
29
30   noRedundancies = false
31
32   private bytesPipe: BytesPipe
33
34   constructor (
35     private notifier: Notifier,
36     private confirmService: ConfirmService,
37     private redundancyService: RedundancyService,
38     private serverService: ServerService,
39     private i18n: I18n
40   ) {
41     super()
42
43     this.bytesPipe = new BytesPipe()
44   }
45
46   getIdentifier () {
47     return 'VideoRedundanciesListComponent'
48   }
49
50   ngOnInit () {
51     this.loadSelectLocalStorage()
52
53     this.initialize()
54
55     this.serverService.getServerStats()
56         .subscribe(res => {
57           const redundancies = res.videosRedundancy
58
59           if (redundancies.length === 0) this.noRedundancies = true
60
61           for (const r of redundancies) {
62             this.buildPieData(r)
63           }
64         })
65   }
66
67   getColspan () {
68     if (this.isDisplayingRemoteVideos()) return 5
69
70     return 4
71   }
72
73   isDisplayingRemoteVideos () {
74     return this.displayType === 'remote-videos'
75   }
76
77   getTotalSize (redundancy: VideoRedundancy) {
78     return redundancy.redundancies.files.reduce((a, b) => a + b.size, 0) +
79       redundancy.redundancies.streamingPlaylists.reduce((a, b) => a + b.size, 0)
80   }
81
82   onDisplayTypeChanged () {
83     this.pagination.start = 0
84     this.saveSelectLocalStorage()
85
86     this.loadData()
87   }
88
89   getRedundancyStrategy (redundancy: VideoRedundancy) {
90     if (redundancy.redundancies.files.length !== 0) return redundancy.redundancies.files[0].strategy
91     if (redundancy.redundancies.streamingPlaylists.length !== 0) return redundancy.redundancies.streamingPlaylists[0].strategy
92
93     return ''
94   }
95
96   buildPieData (stats: VideosRedundancyStats) {
97     const totalSize = stats.totalSize
98       ? stats.totalSize - stats.totalUsed
99       : stats.totalUsed
100
101     if (totalSize === 0) return
102
103     this.redundanciesGraphsData.push({
104       stats,
105       graphData: {
106         labels: [ this.i18n('Used'), this.i18n('Available') ],
107         datasets: [
108           {
109             data: [ stats.totalUsed, totalSize ],
110             backgroundColor: [
111               '#FF6384',
112               '#36A2EB'
113             ],
114             hoverBackgroundColor: [
115               '#FF6384',
116               '#36A2EB'
117             ]
118           }
119         ]
120       },
121       options: {
122         title: {
123           display: true,
124           text: stats.strategy
125         },
126
127         tooltips: {
128           callbacks: {
129             label: (tooltipItem: any, data: any) => {
130               const dataset = data.datasets[tooltipItem.datasetIndex]
131               let label = data.labels[tooltipItem.index]
132               if (label) label += ': '
133               else label = ''
134
135               label += this.bytesPipe.transform(dataset.data[tooltipItem.index], 1)
136               return label
137             }
138           }
139         }
140       }
141     })
142   }
143
144   async removeRedundancy (redundancy: VideoRedundancy) {
145     const message = this.i18n('Do you really want to remove this video redundancy?')
146     const res = await this.confirmService.confirm(message, this.i18n('Remove redundancy'))
147     if (res === false) return
148
149     this.redundancyService.removeVideoRedundancies(redundancy)
150       .subscribe(
151         () => {
152           this.notifier.success(this.i18n('Video redundancies removed!'))
153           this.loadData()
154         },
155
156         err => this.notifier.error(err.message)
157       )
158
159   }
160
161   protected loadData () {
162     const options = {
163       pagination: this.pagination,
164       sort: this.sort,
165       target: this.displayType
166     }
167
168     this.redundancyService.listVideoRedundancies(options)
169                       .subscribe(
170                         resultList => {
171                           this.videoRedundancies = resultList.data
172                           this.totalRecords = resultList.total
173                         },
174
175                         err => this.notifier.error(err.message)
176                       )
177   }
178
179   private loadSelectLocalStorage () {
180     const displayType = peertubeLocalStorage.getItem(VideoRedundanciesListComponent.LOCAL_STORAGE_DISPLAY_TYPE)
181     if (displayType) this.displayType = displayType as VideoRedundanciesTarget
182   }
183
184   private saveSelectLocalStorage () {
185     peertubeLocalStorage.setItem(VideoRedundanciesListComponent.LOCAL_STORAGE_DISPLAY_TYPE, this.displayType)
186   }
187 }