-import { ChartData } from 'chart.js'
+import { ChartData, ChartOptions, TooltipItem, TooltipModel } from 'chart.js'
import { max, maxBy, min, minBy } from 'lodash-es'
-import { Subject } from 'rxjs'
-import { debounceTime, mergeMap } from 'rxjs/operators'
-import { Component, OnInit } from '@angular/core'
-import { AuthService, ConfirmService, Notifier, ScreenService, User } from '@app/core'
+import { mergeMap } from 'rxjs/operators'
+import { Component } from '@angular/core'
+import { AuthService, ConfirmService, Notifier, ScreenService } from '@app/core'
import { VideoChannel, VideoChannelService } from '@app/shared/shared-main'
@Component({
templateUrl: './my-video-channels.component.html',
styleUrls: [ './my-video-channels.component.scss' ]
})
-export class MyVideoChannelsComponent implements OnInit {
+export class MyVideoChannelsComponent {
totalItems: number
videoChannels: VideoChannel[] = []
+
videoChannelsChartData: ChartData[]
videoChannelsMinimumDailyViews = 0
videoChannelsMaximumDailyViews: number
- channelsSearch: string
- channelsSearchChanged = new Subject<string>()
+ chartOptions: ChartOptions
- private user: User
+ search: string
constructor (
private authService: AuthService,
private confirmService: ConfirmService,
private videoChannelService: VideoChannelService,
private screenService: ScreenService
- ) {}
-
- ngOnInit () {
- this.user = this.authService.getUser()
-
- this.loadVideoChannels()
-
- this.channelsSearchChanged
- .pipe(debounceTime(500))
- .subscribe(() => {
- this.loadVideoChannels()
- })
- }
+ ) {}
get isInSmallView () {
return this.screenService.isInSmallView()
}
- get chartOptions () {
- return {
- legend: {
- display: false
- },
- scales: {
- xAxes: [{
- display: false
- }],
- yAxes: [{
- display: false,
- ticks: {
- min: Math.max(0, this.videoChannelsMinimumDailyViews - (3 * this.videoChannelsMaximumDailyViews / 100)),
- max: Math.max(1, this.videoChannelsMaximumDailyViews)
- }
- }]
- },
- layout: {
- padding: {
- left: 15,
- right: 15,
- top: 10,
- bottom: 0
- }
- },
- elements: {
- point: {
- radius: 0
- }
- },
- tooltips: {
- mode: 'index',
- intersect: false,
- custom: function (tooltip: any) {
- if (!tooltip) return
- // disable displaying the color box
- tooltip.displayColors = false
- },
- callbacks: {
- label: (tooltip: any, data: any) => `${tooltip.value} views`
- }
- },
- hover: {
- mode: 'index',
- intersect: false
- }
- }
- }
-
- resetSearch () {
- this.channelsSearch = ''
- this.onChannelsSearchChanged()
- }
-
- onChannelsSearchChanged () {
- this.channelsSearchChanged.next()
+ onSearch (search: string) {
+ this.search = search
+ this.loadVideoChannels()
}
async deleteVideoChannel (videoChannel: VideoChannel) {
It will delete ${videoChannel.videosCount} videos uploaded in this channel, and you will not be able to create another
channel with the same name (${videoChannel.name})!`,
- $localize`Please type the display name of the video channel (${videoChannel.displayName}) to confirm`,
+ $localize`Please type the name of the video channel (${videoChannel.name}) to confirm`,
- videoChannel.displayName,
+ videoChannel.name,
$localize`Delete`
)
if (res === false) return
this.videoChannelService.removeVideoChannel(videoChannel)
- .subscribe(
- () => {
+ .subscribe({
+ next: () => {
this.loadVideoChannels()
this.notifier.success($localize`Video channel ${videoChannel.displayName} deleted.`)
},
- error => this.notifier.error(error.message)
- )
+ error: err => this.notifier.error(err.message)
+ })
}
private loadVideoChannels () {
this.authService.userInformationLoaded
- .pipe(mergeMap(() => this.videoChannelService.listAccountVideoChannels(this.user.account, null, true, this.channelsSearch)))
- .subscribe(res => {
+ .pipe(mergeMap(() => {
+ const user = this.authService.getUser()
+ const options = {
+ account: user.account,
+ withStats: true,
+ search: this.search,
+ sort: '-updatedAt'
+ }
+
+ return this.videoChannelService.listAccountVideoChannels(options)
+ })).subscribe(res => {
this.videoChannels = res.data
this.totalItems = res.total
day => day.views
).views) // the object returned is a ViewPerDate, so we still need to get the views attribute
)
+
this.videoChannelsMaximumDailyViews = max(
// compute local maximum daily views for each channel, by their "views" attribute
this.videoChannels.map(v => maxBy(
day => day.views
).views) // the object returned is a ViewPerDate, so we still need to get the views attribute
)
+
+ this.buildChartOptions()
})
}
+
+ private buildChartOptions () {
+ this.chartOptions = {
+ 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`
+ }
+ }
+ },
+ scales: {
+ x: {
+ display: false
+ },
+ y: {
+ display: false,
+ min: Math.max(0, this.videoChannelsMinimumDailyViews - (3 * this.videoChannelsMaximumDailyViews / 100)),
+ max: Math.max(1, this.videoChannelsMaximumDailyViews)
+ }
+ },
+ layout: {
+ padding: {
+ left: 15,
+ right: 15,
+ top: 10,
+ bottom: 0
+ }
+ },
+ elements: {
+ point: {
+ radius: 0
+ }
+ },
+ hover: {
+ mode: 'index',
+ intersect: false
+ }
+ }
+ }
}