2021-08-26 09:00:08 +02:00
|
|
|
import { ChartData, ChartOptions, TooltipItem, TooltipModel } from 'chart.js'
|
2020-06-23 14:10:17 +02:00
|
|
|
import { max, maxBy, min, minBy } from 'lodash-es'
|
2023-03-01 13:56:15 +01:00
|
|
|
import { Subject } from 'rxjs'
|
2021-05-03 14:33:34 +02:00
|
|
|
import { Component } from '@angular/core'
|
2023-03-01 13:56:15 +01:00
|
|
|
import { AuthService, ComponentPagination, ConfirmService, hasMoreItems, Notifier, ScreenService } from '@app/core'
|
2020-06-23 14:10:17 +02:00
|
|
|
import { VideoChannel, VideoChannelService } from '@app/shared/shared-main'
|
2018-04-26 16:11:38 +02:00
|
|
|
|
|
|
|
@Component({
|
2020-11-12 15:28:54 +01:00
|
|
|
templateUrl: './my-video-channels.component.html',
|
|
|
|
styleUrls: [ './my-video-channels.component.scss' ]
|
2018-04-26 16:11:38 +02:00
|
|
|
})
|
2021-05-03 14:33:34 +02:00
|
|
|
export class MyVideoChannelsComponent {
|
2020-07-23 21:30:04 +02:00
|
|
|
totalItems: number
|
|
|
|
|
2018-04-26 16:11:38 +02:00
|
|
|
videoChannels: VideoChannel[] = []
|
2021-05-03 14:33:34 +02:00
|
|
|
|
2020-03-30 12:06:46 +02:00
|
|
|
videoChannelsChartData: ChartData[]
|
2018-04-26 16:11:38 +02:00
|
|
|
|
2021-08-26 09:00:08 +02:00
|
|
|
chartOptions: ChartOptions
|
2020-11-19 11:12:01 +01:00
|
|
|
|
2021-05-03 14:33:34 +02:00
|
|
|
search: string
|
2018-04-26 16:11:38 +02:00
|
|
|
|
2023-03-01 13:56:15 +01:00
|
|
|
onChannelDataSubject = new Subject<any>()
|
|
|
|
|
|
|
|
pagination: ComponentPagination = {
|
|
|
|
currentPage: 1,
|
|
|
|
itemsPerPage: 10,
|
|
|
|
totalItems: null
|
|
|
|
}
|
|
|
|
|
2018-04-26 16:11:38 +02:00
|
|
|
constructor (
|
|
|
|
private authService: AuthService,
|
2018-12-19 16:04:34 +01:00
|
|
|
private notifier: Notifier,
|
2018-04-26 16:11:38 +02:00
|
|
|
private confirmService: ConfirmService,
|
2018-06-04 16:21:17 +02:00
|
|
|
private videoChannelService: VideoChannelService,
|
2020-08-12 10:40:04 +02:00
|
|
|
private screenService: ScreenService
|
2021-05-03 14:33:34 +02:00
|
|
|
) {}
|
2018-04-26 16:11:38 +02:00
|
|
|
|
2020-03-23 10:14:05 +01:00
|
|
|
get isInSmallView () {
|
|
|
|
return this.screenService.isInSmallView()
|
|
|
|
}
|
|
|
|
|
2021-05-03 14:33:34 +02:00
|
|
|
onSearch (search: string) {
|
|
|
|
this.search = search
|
2023-03-01 13:56:15 +01:00
|
|
|
|
|
|
|
this.pagination.currentPage = 1
|
|
|
|
this.videoChannels = []
|
|
|
|
|
|
|
|
this.authService.userInformationLoaded
|
|
|
|
.subscribe(() => this.loadMoreVideoChannels())
|
2020-07-23 21:30:04 +02:00
|
|
|
}
|
|
|
|
|
2018-04-26 16:11:38 +02:00
|
|
|
async deleteVideoChannel (videoChannel: VideoChannel) {
|
2022-10-07 11:06:28 +02:00
|
|
|
const res = await this.confirmService.confirmWithExpectedInput(
|
2020-08-12 10:40:04 +02:00
|
|
|
$localize`Do you really want to delete ${videoChannel.displayName}?
|
|
|
|
It will delete ${videoChannel.videosCount} videos uploaded in this channel, and you will not be able to create another
|
2023-06-22 14:35:46 +02:00
|
|
|
channel or account with the same name (${videoChannel.name})!`,
|
2020-08-12 10:40:04 +02:00
|
|
|
|
2021-07-20 13:38:26 +02:00
|
|
|
$localize`Please type the name of the video channel (${videoChannel.name}) to confirm`,
|
2020-08-12 10:40:04 +02:00
|
|
|
|
2021-07-20 13:38:26 +02:00
|
|
|
videoChannel.name,
|
2020-11-10 10:52:05 +01:00
|
|
|
|
2020-08-12 10:40:04 +02:00
|
|
|
$localize`Delete`
|
2018-04-26 16:11:38 +02:00
|
|
|
)
|
|
|
|
if (res === false) return
|
|
|
|
|
|
|
|
this.videoChannelService.removeVideoChannel(videoChannel)
|
2021-08-17 11:27:47 +02:00
|
|
|
.subscribe({
|
|
|
|
next: () => {
|
2023-03-01 13:56:15 +01:00
|
|
|
this.videoChannels = this.videoChannels.filter(c => c.id !== videoChannel.id)
|
2020-08-12 10:40:04 +02:00
|
|
|
this.notifier.success($localize`Video channel ${videoChannel.displayName} deleted.`)
|
2018-04-26 16:11:38 +02:00
|
|
|
},
|
|
|
|
|
2021-08-17 11:27:47 +02:00
|
|
|
error: err => this.notifier.error(err.message)
|
|
|
|
})
|
2018-04-26 16:11:38 +02:00
|
|
|
}
|
|
|
|
|
2023-03-01 13:56:15 +01:00
|
|
|
onNearOfBottom () {
|
|
|
|
if (!hasMoreItems(this.pagination)) return
|
|
|
|
|
|
|
|
this.pagination.currentPage += 1
|
2021-05-10 09:31:33 +02:00
|
|
|
|
2023-03-01 13:56:15 +01:00
|
|
|
this.loadMoreVideoChannels()
|
|
|
|
}
|
|
|
|
|
|
|
|
private loadMoreVideoChannels () {
|
|
|
|
const user = this.authService.getUser()
|
|
|
|
const options = {
|
|
|
|
account: user.account,
|
|
|
|
withStats: true,
|
|
|
|
search: this.search,
|
|
|
|
componentPagination: this.pagination,
|
|
|
|
sort: '-updatedAt'
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.videoChannelService.listAccountVideoChannels(options)
|
|
|
|
.subscribe(res => {
|
|
|
|
this.videoChannels = this.videoChannels.concat(res.data)
|
|
|
|
this.totalItems = res.total
|
|
|
|
|
|
|
|
// chart data
|
|
|
|
this.videoChannelsChartData = this.videoChannels.map(v => ({
|
|
|
|
labels: v.viewsPerDay.map(day => day.date.toLocaleDateString()),
|
|
|
|
datasets: [
|
|
|
|
{
|
|
|
|
label: $localize`Views for the day`,
|
|
|
|
data: v.viewsPerDay.map(day => day.views),
|
|
|
|
fill: false,
|
|
|
|
borderColor: '#c6c6c6'
|
|
|
|
}
|
|
|
|
]
|
|
|
|
} as ChartData))
|
|
|
|
|
|
|
|
this.buildChartOptions()
|
|
|
|
|
|
|
|
this.onChannelDataSubject.next(res.data)
|
|
|
|
})
|
2018-04-26 16:11:38 +02:00
|
|
|
}
|
2020-11-19 11:12:01 +01:00
|
|
|
|
|
|
|
private buildChartOptions () {
|
2023-03-01 13:56:15 +01:00
|
|
|
// chart options that depend on chart data:
|
|
|
|
// we don't want to skew values and have min at 0, so we define what the floor/ceiling is here
|
|
|
|
const videoChannelsMinimumDailyViews = min(
|
|
|
|
// compute local minimum daily views for each channel, by their "views" attribute
|
|
|
|
this.videoChannels.map(v => minBy(
|
|
|
|
v.viewsPerDay,
|
|
|
|
day => day.views
|
|
|
|
).views) // the object returned is a ViewPerDate, so we still need to get the views attribute
|
|
|
|
)
|
|
|
|
|
|
|
|
const videoChannelsMaximumDailyViews = max(
|
|
|
|
// compute local maximum daily views for each channel, by their "views" attribute
|
|
|
|
this.videoChannels.map(v => maxBy(
|
|
|
|
v.viewsPerDay,
|
|
|
|
day => day.views
|
|
|
|
).views) // the object returned is a ViewPerDate, so we still need to get the views attribute
|
|
|
|
)
|
|
|
|
|
2020-11-19 11:12:01 +01:00
|
|
|
this.chartOptions = {
|
2021-08-26 09:00:08 +02:00
|
|
|
plugins: {
|
|
|
|
legend: {
|
|
|
|
display: false
|
|
|
|
},
|
|
|
|
tooltip: {
|
|
|
|
mode: 'index',
|
|
|
|
intersect: false,
|
|
|
|
external: function ({ tooltip }: { tooltip: TooltipModel<any> }) {
|
|
|
|
if (!tooltip) return
|
|
|
|
|
|
|
|
// disable displaying the color box
|
|
|
|
tooltip.options.displayColors = false
|
|
|
|
},
|
|
|
|
callbacks: {
|
|
|
|
label: (tooltip: TooltipItem<any>) => `${tooltip.formattedValue} views`
|
|
|
|
}
|
|
|
|
}
|
2020-11-19 11:12:01 +01:00
|
|
|
},
|
|
|
|
scales: {
|
2021-08-26 09:00:08 +02:00
|
|
|
x: {
|
2020-11-19 11:12:01 +01:00
|
|
|
display: false
|
2021-08-26 09:00:08 +02:00
|
|
|
},
|
|
|
|
y: {
|
2020-11-19 11:12:01 +01:00
|
|
|
display: false,
|
2023-03-01 13:56:15 +01:00
|
|
|
min: Math.max(0, videoChannelsMinimumDailyViews - (3 * videoChannelsMaximumDailyViews / 100)),
|
|
|
|
max: Math.max(1, videoChannelsMaximumDailyViews)
|
2021-08-26 09:00:08 +02:00
|
|
|
}
|
2020-11-19 11:12:01 +01:00
|
|
|
},
|
|
|
|
layout: {
|
|
|
|
padding: {
|
|
|
|
left: 15,
|
|
|
|
right: 15,
|
|
|
|
top: 10,
|
|
|
|
bottom: 0
|
|
|
|
}
|
|
|
|
},
|
|
|
|
elements: {
|
|
|
|
point: {
|
|
|
|
radius: 0
|
|
|
|
}
|
|
|
|
},
|
|
|
|
hover: {
|
|
|
|
mode: 'index',
|
|
|
|
intersect: false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-04-26 16:11:38 +02:00
|
|
|
}
|