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