1 import { ChartData, ChartOptions, TooltipItem, TooltipModel } from 'chart.js'
2 import { max, maxBy, min, minBy } from 'lodash-es'
3 import { Subject } from 'rxjs'
4 import { Component } from '@angular/core'
5 import { AuthService, ComponentPagination, ConfirmService, hasMoreItems, Notifier, ScreenService } from '@app/core'
6 import { VideoChannel, VideoChannelService } from '@app/shared/shared-main'
9 templateUrl: './my-video-channels.component.html',
10 styleUrls: [ './my-video-channels.component.scss' ]
12 export class MyVideoChannelsComponent {
15 videoChannels: VideoChannel[] = []
17 videoChannelsChartData: ChartData[]
19 chartOptions: ChartOptions
23 onChannelDataSubject = new Subject<any>()
25 pagination: ComponentPagination = {
32 private authService: AuthService,
33 private notifier: Notifier,
34 private confirmService: ConfirmService,
35 private videoChannelService: VideoChannelService,
36 private screenService: ScreenService
39 get isInSmallView () {
40 return this.screenService.isInSmallView()
43 onSearch (search: string) {
46 this.pagination.currentPage = 1
47 this.videoChannels = []
49 this.authService.userInformationLoaded
50 .subscribe(() => this.loadMoreVideoChannels())
53 async deleteVideoChannel (videoChannel: VideoChannel) {
54 const res = await this.confirmService.confirmWithExpectedInput(
55 $localize`Do you really want to delete ${videoChannel.displayName}?
56 It will delete ${videoChannel.videosCount} videos uploaded in this channel, and you will not be able to create another
57 channel with the same name (${videoChannel.name})!`,
59 $localize`Please type the name of the video channel (${videoChannel.name}) to confirm`,
65 if (res === false) return
67 this.videoChannelService.removeVideoChannel(videoChannel)
70 this.videoChannels = this.videoChannels.filter(c => c.id !== videoChannel.id)
71 this.notifier.success($localize`Video channel ${videoChannel.displayName} deleted.`)
74 error: err => this.notifier.error(err.message)
79 if (!hasMoreItems(this.pagination)) return
81 this.pagination.currentPage += 1
83 this.loadMoreVideoChannels()
86 private loadMoreVideoChannels () {
87 const user = this.authService.getUser()
89 account: user.account,
92 componentPagination: this.pagination,
96 return this.videoChannelService.listAccountVideoChannels(options)
98 this.videoChannels = this.videoChannels.concat(res.data)
99 this.totalItems = res.total
102 this.videoChannelsChartData = this.videoChannels.map(v => ({
103 labels: v.viewsPerDay.map(day => day.date.toLocaleDateString()),
106 label: $localize`Views for the day`,
107 data: v.viewsPerDay.map(day => day.views),
109 borderColor: '#c6c6c6'
114 this.buildChartOptions()
116 this.onChannelDataSubject.next(res.data)
120 private buildChartOptions () {
121 // chart options that depend on chart data:
122 // we don't want to skew values and have min at 0, so we define what the floor/ceiling is here
123 const videoChannelsMinimumDailyViews = min(
124 // compute local minimum daily views for each channel, by their "views" attribute
125 this.videoChannels.map(v => minBy(
128 ).views) // the object returned is a ViewPerDate, so we still need to get the views attribute
131 const videoChannelsMaximumDailyViews = max(
132 // compute local maximum daily views for each channel, by their "views" attribute
133 this.videoChannels.map(v => maxBy(
136 ).views) // the object returned is a ViewPerDate, so we still need to get the views attribute
139 this.chartOptions = {
147 external: function ({ tooltip }: { tooltip: TooltipModel<any> }) {
150 // disable displaying the color box
151 tooltip.options.displayColors = false
154 label: (tooltip: TooltipItem<any>) => `${tooltip.formattedValue} views`
164 min: Math.max(0, videoChannelsMinimumDailyViews - (3 * videoChannelsMaximumDailyViews / 100)),
165 max: Math.max(1, videoChannelsMaximumDailyViews)