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