aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/+stats/video/video-stats.component.scss5
-rw-r--r--client/src/app/+stats/video/video-stats.component.ts6
-rw-r--r--server/models/view/local-video-viewer.ts5
-rw-r--r--server/tests/api/views/video-views-overall-stats.ts10
-rw-r--r--shared/models/videos/stats/video-stats-overall.model.ts2
5 files changed, 27 insertions, 1 deletions
diff --git a/client/src/app/+stats/video/video-stats.component.scss b/client/src/app/+stats/video/video-stats.component.scss
index e4c2d899f..5733b3286 100644
--- a/client/src/app/+stats/video/video-stats.component.scss
+++ b/client/src/app/+stats/video/video-stats.component.scss
@@ -23,6 +23,11 @@
23 23
24 .cards { 24 .cards {
25 display: flex; 25 display: flex;
26 flex-wrap: wrap;
27 }
28
29 .date-filter-wrapper {
30 margin-bottom: 10px;
26 } 31 }
27} 32}
28 33
diff --git a/client/src/app/+stats/video/video-stats.component.ts b/client/src/app/+stats/video/video-stats.component.ts
index 51738f8dc..4ce14902d 100644
--- a/client/src/app/+stats/video/video-stats.component.ts
+++ b/client/src/app/+stats/video/video-stats.component.ts
@@ -223,7 +223,7 @@ export class VideoStatsComponent implements OnInit {
223 private buildLiveFilter (session: LiveVideoSession) { 223 private buildLiveFilter (session: LiveVideoSession) {
224 return { 224 return {
225 id: session.startDate + '|' + session.endDate, 225 id: session.startDate + '|' + session.endDate,
226 label: $localize`Of live of ${new Date(session.startDate).toLocaleString()}` 226 label: $localize`Live as of ${new Date(session.startDate).toLocaleString()}`
227 } 227 }
228 } 228 }
229 229
@@ -276,6 +276,10 @@ export class VideoStatsComponent implements OnInit {
276 moreInfo: overallStats.viewersPeak !== 0 276 moreInfo: overallStats.viewersPeak !== 0
277 ? $localize`at ${new Date(overallStats.viewersPeakDate).toLocaleString()}` 277 ? $localize`at ${new Date(overallStats.viewersPeakDate).toLocaleString()}`
278 : undefined 278 : undefined
279 },
280 {
281 label: $localize`Unique viewers`,
282 value: this.numberFormatter.transform(overallStats.totalViewers)
279 } 283 }
280 ] 284 ]
281 285
diff --git a/server/models/view/local-video-viewer.ts b/server/models/view/local-video-viewer.ts
index b8c372040..12350861b 100644
--- a/server/models/view/local-video-viewer.ts
+++ b/server/models/view/local-video-viewer.ts
@@ -125,6 +125,7 @@ export class LocalVideoViewerModel extends Model<Partial<AttributesOnly<LocalVid
125 } 125 }
126 126
127 const watchTimeQuery = `SELECT ` + 127 const watchTimeQuery = `SELECT ` +
128 `COUNT("localVideoViewer"."id") AS "totalViewers", ` +
128 `SUM("localVideoViewer"."watchTime") AS "totalWatchTime", ` + 129 `SUM("localVideoViewer"."watchTime") AS "totalWatchTime", ` +
129 `AVG("localVideoViewer"."watchTime") AS "averageWatchTime" ` + 130 `AVG("localVideoViewer"."watchTime") AS "averageWatchTime" ` +
130 `FROM "localVideoViewer" ` + 131 `FROM "localVideoViewer" ` +
@@ -177,6 +178,10 @@ export class LocalVideoViewerModel extends Model<Partial<AttributesOnly<LocalVid
177 ? Math.round(rowsWatchTime[0].averageWatchTime) || 0 178 ? Math.round(rowsWatchTime[0].averageWatchTime) || 0
178 : 0, 179 : 0,
179 180
181 totalViewers: rowsWatchTime.length !== 0
182 ? Math.round(rowsWatchTime[0].totalViewers) || 0
183 : 0,
184
180 viewersPeak, 185 viewersPeak,
181 viewersPeakDate: rowsWatchPeak.length !== 0 && viewersPeak !== 0 186 viewersPeakDate: rowsWatchPeak.length !== 0 && viewersPeak !== 0
182 ? rowsWatchPeak[0].dateBreakpoint || null 187 ? rowsWatchPeak[0].dateBreakpoint || null
diff --git a/server/tests/api/views/video-views-overall-stats.ts b/server/tests/api/views/video-views-overall-stats.ts
index 02012388d..25e488b91 100644
--- a/server/tests/api/views/video-views-overall-stats.ts
+++ b/server/tests/api/views/video-views-overall-stats.ts
@@ -36,6 +36,7 @@ describe('Test views overall stats', function () {
36 expect(video.views).to.equal(0) 36 expect(video.views).to.equal(0)
37 expect(stats.averageWatchTime).to.equal(0) 37 expect(stats.averageWatchTime).to.equal(0)
38 expect(stats.totalWatchTime).to.equal(0) 38 expect(stats.totalWatchTime).to.equal(0)
39 expect(stats.totalViewers).to.equal(0)
39 } 40 }
40 }) 41 })
41 42
@@ -55,6 +56,7 @@ describe('Test views overall stats', function () {
55 expect(video.views).to.equal(0) 56 expect(video.views).to.equal(0)
56 expect(stats.averageWatchTime).to.equal(1) 57 expect(stats.averageWatchTime).to.equal(1)
57 expect(stats.totalWatchTime).to.equal(1) 58 expect(stats.totalWatchTime).to.equal(1)
59 expect(stats.totalViewers).to.equal(1)
58 } 60 }
59 }) 61 })
60 62
@@ -74,6 +76,7 @@ describe('Test views overall stats', function () {
74 expect(video.views).to.equal(1) 76 expect(video.views).to.equal(1)
75 expect(stats.averageWatchTime).to.equal(2) 77 expect(stats.averageWatchTime).to.equal(2)
76 expect(stats.totalWatchTime).to.equal(4) 78 expect(stats.totalWatchTime).to.equal(4)
79 expect(stats.totalViewers).to.equal(2)
77 } 80 }
78 81
79 { 82 {
@@ -83,6 +86,7 @@ describe('Test views overall stats', function () {
83 expect(video.views).to.equal(1) 86 expect(video.views).to.equal(1)
84 expect(stats.averageWatchTime).to.equal(21) 87 expect(stats.averageWatchTime).to.equal(21)
85 expect(stats.totalWatchTime).to.equal(41) 88 expect(stats.totalWatchTime).to.equal(41)
89 expect(stats.totalViewers).to.equal(2)
86 } 90 }
87 } 91 }
88 }) 92 })
@@ -103,6 +107,7 @@ describe('Test views overall stats', function () {
103 expect(video.views).to.equal(1) 107 expect(video.views).to.equal(1)
104 expect(stats.averageWatchTime).to.equal(2) 108 expect(stats.averageWatchTime).to.equal(2)
105 expect(stats.totalWatchTime).to.equal(6) 109 expect(stats.totalWatchTime).to.equal(6)
110 expect(stats.totalViewers).to.equal(3)
106 } 111 }
107 112
108 { 113 {
@@ -112,6 +117,7 @@ describe('Test views overall stats', function () {
112 expect(video.views).to.equal(1) 117 expect(video.views).to.equal(1)
113 expect(stats.averageWatchTime).to.equal(14) 118 expect(stats.averageWatchTime).to.equal(14)
114 expect(stats.totalWatchTime).to.equal(43) 119 expect(stats.totalWatchTime).to.equal(43)
120 expect(stats.totalViewers).to.equal(3)
115 } 121 }
116 }) 122 })
117 123
@@ -129,6 +135,7 @@ describe('Test views overall stats', function () {
129 expect(video.views).to.equal(2) 135 expect(video.views).to.equal(2)
130 expect(stats.averageWatchTime).to.equal(3) 136 expect(stats.averageWatchTime).to.equal(3)
131 expect(stats.totalWatchTime).to.equal(11) 137 expect(stats.totalWatchTime).to.equal(11)
138 expect(stats.totalViewers).to.equal(4)
132 } 139 }
133 140
134 { 141 {
@@ -138,6 +145,7 @@ describe('Test views overall stats', function () {
138 expect(video.views).to.equal(2) 145 expect(video.views).to.equal(2)
139 expect(stats.averageWatchTime).to.equal(22) 146 expect(stats.averageWatchTime).to.equal(22)
140 expect(stats.totalWatchTime).to.equal(88) 147 expect(stats.totalWatchTime).to.equal(88)
148 expect(stats.totalViewers).to.equal(4)
141 } 149 }
142 }) 150 })
143 151
@@ -153,12 +161,14 @@ describe('Test views overall stats', function () {
153 const stats = await servers[0].videoStats.getOverallStats({ videoId: vodVideoId, startDate: beforeView.toISOString() }) 161 const stats = await servers[0].videoStats.getOverallStats({ videoId: vodVideoId, startDate: beforeView.toISOString() })
154 expect(stats.averageWatchTime).to.equal(3) 162 expect(stats.averageWatchTime).to.equal(3)
155 expect(stats.totalWatchTime).to.equal(3) 163 expect(stats.totalWatchTime).to.equal(3)
164 expect(stats.totalViewers).to.equal(1)
156 } 165 }
157 166
158 { 167 {
159 const stats = await servers[0].videoStats.getOverallStats({ videoId: liveVideoId, endDate: beforeView.toISOString() }) 168 const stats = await servers[0].videoStats.getOverallStats({ videoId: liveVideoId, endDate: beforeView.toISOString() })
160 expect(stats.averageWatchTime).to.equal(22) 169 expect(stats.averageWatchTime).to.equal(22)
161 expect(stats.totalWatchTime).to.equal(88) 170 expect(stats.totalWatchTime).to.equal(88)
171 expect(stats.totalViewers).to.equal(4)
162 } 172 }
163 }) 173 })
164 174
diff --git a/shared/models/videos/stats/video-stats-overall.model.ts b/shared/models/videos/stats/video-stats-overall.model.ts
index c532c8173..54b57798f 100644
--- a/shared/models/videos/stats/video-stats-overall.model.ts
+++ b/shared/models/videos/stats/video-stats-overall.model.ts
@@ -2,6 +2,8 @@ export interface VideoStatsOverall {
2 averageWatchTime: number 2 averageWatchTime: number
3 totalWatchTime: number 3 totalWatchTime: number
4 4
5 totalViewers: number
6
5 viewersPeak: number 7 viewersPeak: number
6 viewersPeakDate: string 8 viewersPeakDate: string
7 9