mirror of https://github.com/Chocobozzz/PeerTube
Add videos count in channels list
parent
af75e2d8df
commit
1ba471c55f
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
<div i18n class="video-channel-followers">{videoChannel.followersCount, plural, =1 {1 subscriber} other {{{ videoChannel.followersCount }} subscribers}}</div>
|
<div i18n class="video-channel-followers">{videoChannel.followersCount, plural, =1 {1 subscriber} other {{{ videoChannel.followersCount }} subscribers}}</div>
|
||||||
|
|
||||||
|
<div i18n class="video-channel-videos">{videoChannel.videosCount, plural, =0 {No videos} =1 {1 video} other {{{ videoChannel.videosCount }} videos}}</div>
|
||||||
|
|
||||||
<div class="video-channel-buttons">
|
<div class="video-channel-buttons">
|
||||||
<my-edit-button [routerLink]="[ 'update', videoChannel.nameWithHost ]"></my-edit-button>
|
<my-edit-button [routerLink]="[ 'update', videoChannel.nameWithHost ]"></my-edit-button>
|
||||||
<my-delete-button (click)="deleteVideoChannel(videoChannel)"></my-delete-button>
|
<my-delete-button (click)="deleteVideoChannel(videoChannel)"></my-delete-button>
|
||||||
|
|
|
@ -96,8 +96,8 @@ export class MyAccountVideoChannelsComponent implements OnInit {
|
||||||
const res = await this.confirmService.confirmWithInput(
|
const res = await this.confirmService.confirmWithInput(
|
||||||
this.i18n(
|
this.i18n(
|
||||||
// tslint:disable
|
// 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}})!',
|
'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, channelName: videoChannel.name }
|
{ channelDisplayName: videoChannel.displayName, videosCount: videoChannel.videosCount, channelName: videoChannel.name }
|
||||||
),
|
),
|
||||||
this.i18n(
|
this.i18n(
|
||||||
'Please type the display name of the video channel ({{displayName}}) to confirm',
|
'Please type the display name of the video channel ({{displayName}}) to confirm',
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
@import '_variables';
|
@import '_variables';
|
||||||
@import '_mixins';
|
@import '_mixins';
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
padding: 0 13px;
|
padding: 0 13px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,13 @@ export class VideoChannel extends Actor implements ServerVideoChannel {
|
||||||
isLocal: boolean
|
isLocal: boolean
|
||||||
nameWithHost: string
|
nameWithHost: string
|
||||||
nameWithHostForced: string
|
nameWithHostForced: string
|
||||||
|
|
||||||
ownerAccount?: Account
|
ownerAccount?: Account
|
||||||
ownerBy?: string
|
ownerBy?: string
|
||||||
ownerAvatarUrl?: string
|
ownerAvatarUrl?: string
|
||||||
|
|
||||||
|
videosCount?: number
|
||||||
|
|
||||||
viewsPerDay?: ViewsPerDate[]
|
viewsPerDay?: ViewsPerDate[]
|
||||||
|
|
||||||
constructor (hash: ServerVideoChannel) {
|
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.nameWithHost = Actor.CREATE_BY_STRING(this.name, this.host)
|
||||||
this.nameWithHostForced = Actor.CREATE_BY_STRING(this.name, this.host, true)
|
this.nameWithHostForced = Actor.CREATE_BY_STRING(this.name, this.host, true)
|
||||||
|
|
||||||
|
this.videosCount = hash.videosCount
|
||||||
|
|
||||||
if (hash.viewsPerDay) {
|
if (hash.viewsPerDay) {
|
||||||
this.viewsPerDay = hash.viewsPerDay.map(v => ({ ...v, date: new Date(v.date) }))
|
this.viewsPerDay = hash.viewsPerDay.map(v => ({ ...v, date: new Date(v.date) }))
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,6 +172,10 @@ export type SummaryOptions = {
|
||||||
return {
|
return {
|
||||||
attributes: {
|
attributes: {
|
||||||
include: [
|
include: [
|
||||||
|
[
|
||||||
|
literal('(SELECT COUNT(*) FROM "video" WHERE "channelId" = "VideoChannelModel"."id")'),
|
||||||
|
'videosCount'
|
||||||
|
],
|
||||||
[
|
[
|
||||||
literal(
|
literal(
|
||||||
'(' +
|
'(' +
|
||||||
|
@ -544,7 +548,22 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
toFormattedJSON (this: MChannelFormattable): VideoChannel {
|
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 actor = this.Actor.toFormattedJSON()
|
||||||
const videoChannel = {
|
const videoChannel = {
|
||||||
|
@ -556,15 +575,8 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
|
||||||
createdAt: this.createdAt,
|
createdAt: this.createdAt,
|
||||||
updatedAt: this.updatedAt,
|
updatedAt: this.updatedAt,
|
||||||
ownerAccount: undefined,
|
ownerAccount: undefined,
|
||||||
viewsPerDay: viewsPerDay
|
videosCount,
|
||||||
? viewsPerDay.split(',').map(v => {
|
viewsPerDay
|
||||||
const o = v.split('|')
|
|
||||||
return {
|
|
||||||
date: new Date(o[0]),
|
|
||||||
views: +o[1]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
: undefined
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.Account) videoChannel.ownerAccount = this.Account.toFormattedJSON()
|
if (this.Account) videoChannel.ownerAccount = this.Account.toFormattedJSON()
|
||||||
|
|
|
@ -500,7 +500,7 @@ export class VideoModel extends Model<VideoModel> {
|
||||||
@AllowNull(false)
|
@AllowNull(false)
|
||||||
@Is('VideoPrivacy', value => throwIfNotValid(value, isVideoPrivacyValid, 'privacy'))
|
@Is('VideoPrivacy', value => throwIfNotValid(value, isVideoPrivacyValid, 'privacy'))
|
||||||
@Column
|
@Column
|
||||||
privacy: number
|
privacy: VideoPrivacy
|
||||||
|
|
||||||
@AllowNull(false)
|
@AllowNull(false)
|
||||||
@Is('VideoNSFW', value => throwIfNotValid(value, isBooleanValid, 'NSFW boolean'))
|
@Is('VideoNSFW', value => throwIfNotValid(value, isBooleanValid, 'NSFW boolean'))
|
||||||
|
|
|
@ -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)
|
this.timeout(10000)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -374,14 +374,18 @@ describe('Test video channels', function () {
|
||||||
accountName: userInfo.account.name + '@' + userInfo.account.host,
|
accountName: userInfo.account.name + '@' + userInfo.account.host,
|
||||||
withStats: true
|
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).to.haveOwnProperty('viewsPerDay')
|
||||||
expect(channel.viewsPerDay).to.have.length(30 + 1) // daysPrior + today
|
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.date).to.be.an('string')
|
||||||
expect(v.views).to.equal(0)
|
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 () {
|
after(async function () {
|
||||||
await cleanupTests(servers)
|
await cleanupTests(servers)
|
||||||
})
|
})
|
||||||
|
|
|
@ -13,6 +13,8 @@ export interface VideoChannel extends Actor {
|
||||||
support: string
|
support: string
|
||||||
isLocal: boolean
|
isLocal: boolean
|
||||||
ownerAccount?: Account
|
ownerAccount?: Account
|
||||||
|
|
||||||
|
videosCount?: number
|
||||||
viewsPerDay?: ViewsPerDate[] // chronologically ordered
|
viewsPerDay?: ViewsPerDate[] // chronologically ordered
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue