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