diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html index 2499b6ed5..bf4fa9396 100644 --- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html +++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html @@ -20,6 +20,8 @@
{videoChannel.followersCount, plural, =1 {1 subscriber} other {{{ videoChannel.followersCount }} subscribers}}
+
{videoChannel.videosCount, plural, =0 {No videos} =1 {1 video} other {{{ videoChannel.videosCount }} videos}}
+
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts index 75d6d8acd..9caefe5b1 100644 --- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts +++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts @@ -96,8 +96,8 @@ export class MyAccountVideoChannelsComponent implements OnInit { const res = await this.confirmService.confirmWithInput( this.i18n( // tslint:disable - 'Do you really want to delete {{channelDisplayName}}? It will delete all videos uploaded in this channel, and you will not be able to create another channel with the same name ({{channelName}})!', - { channelDisplayName: videoChannel.displayName, channelName: videoChannel.name } + '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}})!', + { channelDisplayName: videoChannel.displayName, videosCount: videoChannel.videosCount, channelName: videoChannel.name } ), this.i18n( 'Please type the display name of the video channel ({{displayName}}) to confirm', diff --git a/client/src/app/shared/confirm/confirm.component.scss b/client/src/app/shared/confirm/confirm.component.scss index 93dd7926b..ed226bc09 100644 --- a/client/src/app/shared/confirm/confirm.component.scss +++ b/client/src/app/shared/confirm/confirm.component.scss @@ -1,6 +1,10 @@ @import '_variables'; @import '_mixins'; +.modal-body { + font-size: 15px; +} + .button { padding: 0 13px; } diff --git a/client/src/app/shared/video-channel/video-channel.model.ts b/client/src/app/shared/video-channel/video-channel.model.ts index 617d6d44d..2f4597343 100644 --- a/client/src/app/shared/video-channel/video-channel.model.ts +++ b/client/src/app/shared/video-channel/video-channel.model.ts @@ -9,9 +9,13 @@ export class VideoChannel extends Actor implements ServerVideoChannel { isLocal: boolean nameWithHost: string nameWithHostForced: string + ownerAccount?: Account ownerBy?: string ownerAvatarUrl?: string + + videosCount?: number + viewsPerDay?: ViewsPerDate[] constructor (hash: ServerVideoChannel) { @@ -24,6 +28,8 @@ export class VideoChannel extends Actor implements ServerVideoChannel { this.nameWithHost = Actor.CREATE_BY_STRING(this.name, this.host) this.nameWithHostForced = Actor.CREATE_BY_STRING(this.name, this.host, true) + this.videosCount = hash.videosCount + if (hash.viewsPerDay) { this.viewsPerDay = hash.viewsPerDay.map(v => ({ ...v, date: new Date(v.date) })) } diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index b5bcbdc65..a4231b6b3 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts @@ -172,6 +172,10 @@ export type SummaryOptions = { return { attributes: { include: [ + [ + literal('(SELECT COUNT(*) FROM "video" WHERE "channelId" = "VideoChannelModel"."id")'), + 'videosCount' + ], [ literal( '(' + @@ -544,7 +548,22 @@ export class VideoChannelModel extends Model { } toFormattedJSON (this: MChannelFormattable): VideoChannel { - const viewsPerDay = this.get('viewsPerDay') as string + const viewsPerDayString = this.get('viewsPerDay') as string + const videosCount = this.get('videosCount') as number + + let viewsPerDay: { date: Date, views: number }[] + + if (viewsPerDayString) { + viewsPerDay = viewsPerDayString.split(',') + .map(v => { + const [ dateString, amount ] = v.split('|') + + return { + date: new Date(dateString), + views: +amount + } + }) + } const actor = this.Actor.toFormattedJSON() const videoChannel = { @@ -556,15 +575,8 @@ export class VideoChannelModel extends Model { createdAt: this.createdAt, updatedAt: this.updatedAt, ownerAccount: undefined, - viewsPerDay: viewsPerDay - ? viewsPerDay.split(',').map(v => { - const o = v.split('|') - return { - date: new Date(o[0]), - views: +o[1] - } - }) - : undefined + videosCount, + viewsPerDay } if (this.Account) videoChannel.ownerAccount = this.Account.toFormattedJSON() diff --git a/server/models/video/video.ts b/server/models/video/video.ts index ae2483b2f..1f590c02d 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -500,7 +500,7 @@ export class VideoModel extends Model { @AllowNull(false) @Is('VideoPrivacy', value => throwIfNotValid(value, isVideoPrivacyValid, 'privacy')) @Column - privacy: number + privacy: VideoPrivacy @AllowNull(false) @Is('VideoNSFW', value => throwIfNotValid(value, isBooleanValid, 'NSFW boolean')) diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts index 89026aba7..e7d9238dd 100644 --- a/server/tests/api/videos/video-channels.ts +++ b/server/tests/api/videos/video-channels.ts @@ -365,7 +365,7 @@ describe('Test video channels', function () { } }) - it('Should report correct channel statistics', async function () { + it('Should report correct channel views per days', async function () { this.timeout(10000) { @@ -374,14 +374,18 @@ describe('Test video channels', function () { accountName: userInfo.account.name + '@' + userInfo.account.host, withStats: true }) - res.body.data.forEach((channel: VideoChannel) => { + + const channels: VideoChannel[] = res.body.data + + for (const channel of channels) { expect(channel).to.haveOwnProperty('viewsPerDay') expect(channel.viewsPerDay).to.have.length(30 + 1) // daysPrior + today - channel.viewsPerDay.forEach((v: ViewsPerDate) => { + + for (const v of channel.viewsPerDay) { expect(v.date).to.be.an('string') expect(v.views).to.equal(0) - }) - }) + } + } } { @@ -402,6 +406,21 @@ describe('Test video channels', function () { } }) + it('Should report correct videos count', async function () { + const res = await getAccountVideoChannelsList({ + url: servers[0].url, + accountName: userInfo.account.name + '@' + userInfo.account.host, + withStats: true + }) + const channels: VideoChannel[] = res.body.data + + const totoChannel = channels.find(c => c.name === 'toto_channel') + const rootChannel = channels.find(c => c.name === 'root_channel') + + expect(rootChannel.videosCount).to.equal(1) + expect(totoChannel.videosCount).to.equal(0) + }) + after(async function () { await cleanupTests(servers) }) diff --git a/shared/models/videos/channel/video-channel.model.ts b/shared/models/videos/channel/video-channel.model.ts index 421004e68..32829e92a 100644 --- a/shared/models/videos/channel/video-channel.model.ts +++ b/shared/models/videos/channel/video-channel.model.ts @@ -13,6 +13,8 @@ export interface VideoChannel extends Actor { support: string isLocal: boolean ownerAccount?: Account + + videosCount?: number viewsPerDay?: ViewsPerDate[] // chronologically ordered }