2024-03-27 14:00:40 +01:00
import { NgFor , NgIf } from '@angular/common'
2021-05-03 14:33:34 +02:00
import { Component } from '@angular/core'
2024-03-27 14:00:40 +01:00
import { RouterLink } from '@angular/router'
import { AuthService , ComponentPagination , ConfirmService , Notifier , ScreenService , hasMoreItems } from '@app/core'
2023-08-18 14:12:32 +02:00
import { formatICU } from '@app/helpers'
2024-03-27 14:00:40 +01:00
import { VideoChannel } from '@app/shared/shared-main/video-channel/video-channel.model'
import { VideoChannelService } from '@app/shared/shared-main/video-channel/video-channel.service'
import { maxBy , minBy } from '@peertube/peertube-core-utils'
import { ChartData , ChartOptions , TooltipItem , TooltipModel } from 'chart.js'
2024-03-04 10:01:52 +01:00
import { ChartModule } from 'primeng/chart'
2024-03-27 14:00:40 +01:00
import { Subject , first , map , switchMap } from 'rxjs'
import { ActorAvatarComponent } from '../../shared/shared-actor-image/actor-avatar.component'
import { AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component'
import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component'
2024-03-04 10:01:52 +01:00
import { DeferLoadingDirective } from '../../shared/shared-main/angular/defer-loading.directive'
2024-03-27 14:00:40 +01:00
import { InfiniteScrollerDirective } from '../../shared/shared-main/angular/infinite-scroller.directive'
import { NumberFormatterPipe } from '../../shared/shared-main/angular/number-formatter.pipe'
2024-03-04 10:01:52 +01:00
import { DeleteButtonComponent } from '../../shared/shared-main/buttons/delete-button.component'
import { EditButtonComponent } from '../../shared/shared-main/buttons/edit-button.component'
import { ChannelsSetupMessageComponent } from '../../shared/shared-main/misc/channels-setup-message.component'
2018-04-26 16:11:38 +02:00
@Component ( {
2020-11-12 15:28:54 +01:00
templateUrl : './my-video-channels.component.html' ,
2024-03-04 10:01:52 +01:00
styleUrls : [ './my-video-channels.component.scss' ] ,
standalone : true ,
imports : [
GlobalIconComponent ,
NgIf ,
RouterLink ,
ChannelsSetupMessageComponent ,
AdvancedInputFilterComponent ,
InfiniteScrollerDirective ,
NgFor ,
ActorAvatarComponent ,
EditButtonComponent ,
DeleteButtonComponent ,
DeferLoadingDirective ,
ChartModule ,
NumberFormatterPipe
]
2018-04-26 16:11:38 +02:00
} )
2021-05-03 14:33:34 +02:00
export class MyVideoChannelsComponent {
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
}
2024-01-11 10:08:10 +01:00
private pagesDone = new Set < number > ( )
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 = [ ]
2024-01-11 10:08:10 +01:00
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 (
2023-08-18 14:12:32 +02:00
$localize ` Do you really want to delete ${ videoChannel . displayName } ? ` +
` <br /> ` +
formatICU (
// eslint-disable-next-line max-len
$localize ` It will delete {count, plural, =1 {1 video} other {{count} videos}} uploaded in this channel, and you will not be able to create another channel or account with the same name ( ${ videoChannel . name } )! ` ,
{ count : videoChannel.videosCount }
) ,
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 ( ) {
2024-01-11 10:08:10 +01:00
if ( this . pagesDone . has ( this . pagination . currentPage ) ) return
this . pagesDone . add ( this . pagination . currentPage )
return this . authService . userInformationLoaded
. pipe (
first ( ) ,
map ( ( ) = > ( {
account : this.authService.getUser ( ) . account ,
withStats : true ,
search : this.search ,
componentPagination : this.pagination ,
sort : '-updatedAt'
} ) ) ,
switchMap ( options = > this . videoChannelService . listAccountVideoChannels ( options ) )
)
2023-03-01 13:56:15 +01:00
. subscribe ( res = > {
this . videoChannels = this . videoChannels . concat ( res . data )
2024-01-11 10:08:10 +01:00
this . pagination . totalItems = res . total
2023-03-01 13:56:15 +01:00
// 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 ( ) {
2024-03-27 14:00:40 +01:00
const channelsMinimumDailyViews = Math . min ( . . . this . videoChannels . map ( v = > minBy ( v . viewsPerDay , 'views' ) . views ) )
const channelsMaximumDailyViews = Math . max ( . . . this . videoChannels . map ( v = > maxBy ( v . viewsPerDay , 'views' ) . views ) )
2023-03-01 13:56:15 +01:00
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 ,
2024-03-27 14:00:40 +01:00
min : Math.max ( 0 , channelsMinimumDailyViews - ( 3 * channelsMaximumDailyViews / 100 ) ) ,
max : Math.max ( 1 , channelsMaximumDailyViews )
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
}