From c6f8ca4d6596572de981162983bd02eb2613791d Mon Sep 17 00:00:00 2001 From: Florian CUNY Date: Tue, 31 May 2022 16:01:11 +0200 Subject: [PATCH] Added "total views" in the my channels list (#5007) * Added "total views" in the my channels list Implements https://github.com/Chocobozzz/PeerTube/issues/4331 * Fix lint * applied suggested change * updated openAPI spec for the use "withStats" when getting video channels * applied code change * removed GROUP BY in query * Fixed test --- .../my-video-channels.component.html | 2 ++ .../video-channel/video-channel.model.ts | 5 +++++ server/models/video/video-channel.ts | 13 +++++++++++++ server/tests/api/videos/video-channels.ts | 19 +++++++++++++++++++ .../videos/channel/video-channel.model.ts | 1 + support/doc/api/openapi.yaml | 2 +- 6 files changed, 41 insertions(+), 1 deletion(-) diff --git a/client/src/app/+my-library/+my-video-channels/my-video-channels.component.html b/client/src/app/+my-library/+my-video-channels/my-video-channels.component.html index e7003f1e4..f17f62bba 100644 --- a/client/src/app/+my-library/+my-video-channels/my-video-channels.component.html +++ b/client/src/app/+my-library/+my-video-channels/my-video-channels.component.html @@ -36,6 +36,8 @@
{videoChannel.videosCount, plural, =0 {No videos} =1 {1 video} other {{{ videoChannel.videosCount }} videos}}
+
{videoChannel.totalViews, plural, =0 {No views} =1 {1 view} other {{{ videoChannel.totalViews }} views}}
+
diff --git a/client/src/app/shared/shared-main/video-channel/video-channel.model.ts b/client/src/app/shared/shared-main/video-channel/video-channel.model.ts index 32376bf62..62bd94349 100644 --- a/client/src/app/shared/shared-main/video-channel/video-channel.model.ts +++ b/client/src/app/shared/shared-main/video-channel/video-channel.model.ts @@ -27,6 +27,7 @@ export class VideoChannel extends Actor implements ServerVideoChannel { videosCount?: number viewsPerDay?: ViewsPerDate[] + totalViews?: number static GET_ACTOR_AVATAR_URL (actor: { avatars: { width: number, url?: string, path: string }[] }, size: number) { return Actor.GET_ACTOR_AVATAR_URL(actor, size) @@ -74,6 +75,10 @@ export class VideoChannel extends Actor implements ServerVideoChannel { this.viewsPerDay = hash.viewsPerDay.map(v => ({ ...v, date: new Date(v.date) })) } + if (hash.totalViews !== null && hash.totalViews !== undefined) { + this.totalViews = hash.totalViews + } + if (hash.ownerAccount) { this.ownerAccount = hash.ownerAccount this.ownerBy = Actor.CREATE_BY_STRING(hash.ownerAccount.name, hash.ownerAccount.host) diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index d6dd1b8bb..91dafbcf1 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts @@ -311,6 +311,16 @@ export type SummaryOptions = { ')' ), 'viewsPerDay' + ], + [ + literal( + '(' + + 'SELECT COALESCE(SUM("video".views), 0) AS totalViews ' + + 'FROM "video" ' + + 'WHERE "video"."channelId" = "VideoChannelModel"."id"' + + ')' + ), + 'totalViews' ] ] } @@ -766,6 +776,8 @@ ON "Account->Actor"."serverId" = "Account->Actor->Server"."id"` }) } + const totalViews = this.get('totalViews') as number + const actor = this.Actor.toFormattedJSON() const videoChannel = { id: this.id, @@ -779,6 +791,7 @@ ON "Account->Actor"."serverId" = "Account->Actor->Server"."id"` videosCount, viewsPerDay, + totalViews, avatars: actor.avatars, diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts index 6f495c42d..42e0cf431 100644 --- a/server/tests/api/videos/video-channels.ts +++ b/server/tests/api/videos/video-channels.ts @@ -478,6 +478,25 @@ describe('Test video channels', function () { } }) + it('Should report correct total views count', async function () { + // check if there's the property + { + const { data } = await servers[0].channels.listByAccount({ accountName, withStats: true }) + + for (const channel of data) { + expect(channel).to.haveOwnProperty('totalViews') + expect(channel.totalViews).to.be.a('number') + } + } + + // Check if the totalViews count can be updated + { + const { data } = await servers[0].channels.listByAccount({ accountName, withStats: true }) + const channelWithView = data.find(channel => channel.id === servers[0].store.channel.id) + expect(channelWithView.totalViews).to.equal(2) + } + }) + it('Should report correct videos count', async function () { const { data } = await servers[0].channels.listByAccount({ accountName, withStats: true }) diff --git a/shared/models/videos/channel/video-channel.model.ts b/shared/models/videos/channel/video-channel.model.ts index 58b60c177..68e2f9c4c 100644 --- a/shared/models/videos/channel/video-channel.model.ts +++ b/shared/models/videos/channel/video-channel.model.ts @@ -18,6 +18,7 @@ export interface VideoChannel extends Actor { videosCount?: number viewsPerDay?: ViewsPerDate[] // chronologically ordered + totalViews?: number banners: ActorImage[] diff --git a/support/doc/api/openapi.yaml b/support/doc/api/openapi.yaml index 294aa50ab..8521f684e 100644 --- a/support/doc/api/openapi.yaml +++ b/support/doc/api/openapi.yaml @@ -3602,7 +3602,7 @@ paths: - $ref: '#/components/parameters/name' - name: withStats in: query - description: include view statistics for the last 30 days (only if authentified as the account user) + description: include daily view statistics for the last 30 days and total views (only if authentified as the account user) schema: type: boolean - $ref: '#/components/parameters/start'