]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/+my-library/+my-video-channels/my-video-channels.component.ts
register: hide channel step if upload quota is 0
[github/Chocobozzz/PeerTube.git] / client / src / app / +my-library / +my-video-channels / my-video-channels.component.ts
CommitLineData
67ed6552
C
1import { ChartData } from 'chart.js'
2import { max, maxBy, min, minBy } from 'lodash-es'
66357162
C
3import { Subject } from 'rxjs'
4import { debounceTime, mergeMap } from 'rxjs/operators'
67ed6552
C
5import { Component, OnInit } from '@angular/core'
6import { AuthService, ConfirmService, Notifier, ScreenService, User } from '@app/core'
7import { VideoChannel, VideoChannelService } from '@app/shared/shared-main'
08c1efbe
C
8
9@Component({
17119e4a
C
10 templateUrl: './my-video-channels.component.html',
11 styleUrls: [ './my-video-channels.component.scss' ]
08c1efbe 12})
17119e4a 13export class MyVideoChannelsComponent implements OnInit {
4f5d0459
RK
14 totalItems: number
15
08c1efbe 16 videoChannels: VideoChannel[] = []
3d527ba1 17 videoChannelsChartData: ChartData[]
8165d00a
RK
18 videoChannelsMinimumDailyViews = 0
19 videoChannelsMaximumDailyViews: number
08c1efbe 20
4f5d0459
RK
21 channelsSearch: string
22 channelsSearchChanged = new Subject<string>()
23
4f926722
C
24 chartOptions: any
25
08c1efbe
C
26 private user: User
27
28 constructor (
29 private authService: AuthService,
f8b2c1b4 30 private notifier: Notifier,
08c1efbe 31 private confirmService: ConfirmService,
b1d40cff 32 private videoChannelService: VideoChannelService,
66357162
C
33 private screenService: ScreenService
34 ) {}
08c1efbe
C
35
36 ngOnInit () {
37 this.user = this.authService.getUser()
38
39 this.loadVideoChannels()
4f5d0459
RK
40
41 this.channelsSearchChanged
42 .pipe(debounceTime(500))
43 .subscribe(() => {
44 this.loadVideoChannels()
45 })
08c1efbe
C
46 }
47
8165d00a
RK
48 get isInSmallView () {
49 return this.screenService.isInSmallView()
50 }
51
225a7682 52 resetSearch () {
4f5d0459
RK
53 this.channelsSearch = ''
54 this.onChannelsSearchChanged()
55 }
56
57 onChannelsSearchChanged () {
58 this.channelsSearchChanged.next()
59 }
60
08c1efbe
C
61 async deleteVideoChannel (videoChannel: VideoChannel) {
62 const res = await this.confirmService.confirmWithInput(
66357162
C
63 $localize`Do you really want to delete ${videoChannel.displayName}?
64It will delete ${videoChannel.videosCount} videos uploaded in this channel, and you will not be able to create another
65channel with the same name (${videoChannel.name})!`,
66
67 $localize`Please type the display name of the video channel (${videoChannel.displayName}) to confirm`,
68
d88c490d
C
69 videoChannel.displayName,
70
66357162 71 $localize`Delete`
08c1efbe
C
72 )
73 if (res === false) return
74
75 this.videoChannelService.removeVideoChannel(videoChannel)
76 .subscribe(
f8b2c1b4 77 () => {
08c1efbe 78 this.loadVideoChannels()
66357162 79 this.notifier.success($localize`Video channel ${videoChannel.displayName} deleted.`)
08c1efbe
C
80 },
81
f8b2c1b4 82 error => this.notifier.error(error.message)
08c1efbe
C
83 )
84 }
85
86 private loadVideoChannels () {
87 this.authService.userInformationLoaded
66357162 88 .pipe(mergeMap(() => this.videoChannelService.listAccountVideoChannels(this.user.account, null, true, this.channelsSearch)))
8165d00a
RK
89 .subscribe(res => {
90 this.videoChannels = res.data
4f5d0459 91 this.totalItems = res.total
3d527ba1
RK
92
93 // chart data
94 this.videoChannelsChartData = this.videoChannels.map(v => ({
8165d00a
RK
95 labels: v.viewsPerDay.map(day => day.date.toLocaleDateString()),
96 datasets: [
97 {
66357162
C
98 label: $localize`Views for the day`,
99 data: v.viewsPerDay.map(day => day.views),
100 fill: false,
101 borderColor: '#c6c6c6'
8165d00a
RK
102 }
103 ]
3d527ba1
RK
104 } as ChartData))
105
106 // chart options that depend on chart data:
107 // we don't want to skew values and have min at 0, so we define what the floor/ceiling is here
108 this.videoChannelsMinimumDailyViews = min(
66357162
C
109 // compute local minimum daily views for each channel, by their "views" attribute
110 this.videoChannels.map(v => minBy(
3d527ba1
RK
111 v.viewsPerDay,
112 day => day.views
113 ).views) // the object returned is a ViewPerDate, so we still need to get the views attribute
114 )
4f926722 115
3d527ba1 116 this.videoChannelsMaximumDailyViews = max(
66357162
C
117 // compute local maximum daily views for each channel, by their "views" attribute
118 this.videoChannels.map(v => maxBy(
3d527ba1
RK
119 v.viewsPerDay,
120 day => day.views
121 ).views) // the object returned is a ViewPerDate, so we still need to get the views attribute
122 )
4f926722
C
123
124 this.buildChartOptions()
8165d00a 125 })
08c1efbe 126 }
4f926722
C
127
128 private buildChartOptions () {
129 this.chartOptions = {
130 legend: {
131 display: false
132 },
133 scales: {
134 xAxes: [{
135 display: false
136 }],
137 yAxes: [{
138 display: false,
139 ticks: {
140 min: Math.max(0, this.videoChannelsMinimumDailyViews - (3 * this.videoChannelsMaximumDailyViews / 100)),
141 max: Math.max(1, this.videoChannelsMaximumDailyViews)
142 }
143 }]
144 },
145 layout: {
146 padding: {
147 left: 15,
148 right: 15,
149 top: 10,
150 bottom: 0
151 }
152 },
153 elements: {
154 point: {
155 radius: 0
156 }
157 },
158 tooltips: {
159 mode: 'index',
160 intersect: false,
161 custom: function (tooltip: any) {
162 if (!tooltip) return
163 // disable displaying the color box
164 tooltip.displayColors = false
165 },
166 callbacks: {
167 label: (tooltip: any, data: any) => `${tooltip.value} views`
168 }
169 },
170 hover: {
171 mode: 'index',
172 intersect: false
173 }
174 }
175 }
08c1efbe 176}