@@ -3,11 +3,7 @@ import Box from "@mui/material/Box"
3
3
import { styled , useTheme } from "@mui/material/styles"
4
4
import { BoxProps } from "@mui/system"
5
5
import { useQuery } from "@tanstack/react-query"
6
- import {
7
- getInsightsTemplate ,
8
- getInsightsUserLatency ,
9
- getTemplateDAUs ,
10
- } from "api/api"
6
+ import { getInsightsTemplate , getInsightsUserLatency } from "api/api"
11
7
import { DAUChart } from "components/DAUChart/DAUChart"
12
8
import { useTemplateLayoutContext } from "components/TemplateLayout/TemplateLayout"
13
9
import {
@@ -22,9 +18,21 @@ import { colors } from "theme/colors"
22
18
import { Helmet } from "react-helmet-async"
23
19
import { getTemplatePageTitle } from "../utils"
24
20
import { Loader } from "components/Loader/Loader"
21
+ import { DAUsResponse , TemplateInsightsResponse } from "api/typesGenerated"
22
+ import { ComponentProps } from "react"
23
+ import subDays from "date-fns/subDays"
25
24
26
25
export default function TemplateInsightsPage ( ) {
27
26
const { template } = useTemplateLayoutContext ( )
27
+ const { data : templateInsights } = useQuery ( {
28
+ queryKey : [ "templates" , template . id , "usage" ] ,
29
+ queryFn : ( ) =>
30
+ getInsightsTemplate ( {
31
+ template_ids : template . id ,
32
+ start_time : toTimeFilter ( sevenDaysAgo ( ) ) ,
33
+ end_time : toTimeFilter ( new Date ( ) ) ,
34
+ } ) ,
35
+ } )
28
36
29
37
return (
30
38
< >
@@ -40,22 +48,28 @@ export default function TemplateInsightsPage() {
40
48
gap : ( theme ) => theme . spacing ( 3 ) ,
41
49
} }
42
50
>
43
- < DailyUsersPanel sx = { { gridColumn : "span 2" } } />
51
+ < DailyUsersPanel
52
+ sx = { { gridColumn : "span 2" } }
53
+ data = { templateInsights ?. interval_reports }
54
+ />
44
55
< UserLatencyPanel />
45
- < TemplateUsagePanel sx = { { gridColumn : "span 3" } } />
56
+ < TemplateUsagePanel
57
+ sx = { { gridColumn : "span 3" } }
58
+ data = { templateInsights ?. report . apps_usage }
59
+ />
46
60
</ Box >
47
61
</ >
48
62
)
49
63
}
50
64
51
- const DailyUsersPanel = ( props : BoxProps ) => {
52
- const { template } = useTemplateLayoutContext ( )
53
- const { data } = useQuery ( {
54
- queryKey : [ "templates" , template . id , "dau" ] ,
55
- queryFn : ( ) => getTemplateDAUs ( template . id ) ,
56
- } )
65
+ const DailyUsersPanel = ( {
66
+ data ,
67
+ ... panelProps
68
+ } : PanelProps & {
69
+ data : TemplateInsightsResponse [ "interval_reports" ] | undefined
70
+ } ) => {
57
71
return (
58
- < Panel { ...props } >
72
+ < Panel { ...panelProps } >
59
73
< PanelHeader sx = { { display : "flex" , alignItems : "center" , gap : 1 } } >
60
74
Active daily users
61
75
< HelpTooltip size = "small" >
@@ -67,21 +81,21 @@ const DailyUsersPanel = (props: BoxProps) => {
67
81
</ PanelHeader >
68
82
< PanelContent >
69
83
{ ! data && < Loader sx = { { height : "100%" } } /> }
70
- { data && data . entries . length === 0 && < NoDataAvailable /> }
71
- { data && data . entries . length > 0 && < DAUChart daus = { data } /> }
84
+ { data && data . length === 0 && < NoDataAvailable /> }
85
+ { data && data . length > 0 && < DAUChart daus = { mapToDAUsResponse ( data ) } /> }
72
86
</ PanelContent >
73
87
</ Panel >
74
88
)
75
89
}
76
90
77
- const UserLatencyPanel = ( props : BoxProps ) => {
91
+ const UserLatencyPanel = ( props : PanelProps ) => {
78
92
const { template } = useTemplateLayoutContext ( )
79
93
const { data } = useQuery ( {
80
94
queryKey : [ "templates" , template . id , "user-latency" ] ,
81
95
queryFn : ( ) =>
82
96
getInsightsUserLatency ( {
83
97
template_ids : template . id ,
84
- start_time : toTimeFilter ( new Date ( template . created_at ) ) ,
98
+ start_time : toTimeFilter ( sevenDaysAgo ( ) ) ,
85
99
end_time : toTimeFilter ( new Date ( ) ) ,
86
100
} ) ,
87
101
} )
@@ -133,37 +147,29 @@ const UserLatencyPanel = (props: BoxProps) => {
133
147
)
134
148
}
135
149
136
- const TemplateUsagePanel = ( props : BoxProps ) => {
137
- const { template } = useTemplateLayoutContext ( )
138
- const { data } = useQuery ( {
139
- queryKey : [ "templates" , template . id , "usage" ] ,
140
- queryFn : ( ) =>
141
- getInsightsTemplate ( {
142
- template_ids : template . id ,
143
- start_time : toTimeFilter ( new Date ( template . created_at ) ) ,
144
- end_time : toTimeFilter ( new Date ( ) ) ,
145
- } ) ,
146
- } )
150
+ const TemplateUsagePanel = ( {
151
+ data,
152
+ ...panelProps
153
+ } : PanelProps & {
154
+ data : TemplateInsightsResponse [ "report" ] [ "apps_usage" ] | undefined
155
+ } ) => {
147
156
const totalInSeconds =
148
- data ?. report . apps_usage . reduce (
149
- ( total , usage ) => total + usage . seconds ,
150
- 0 ,
151
- ) ?? 1
157
+ data ?. reduce ( ( total , usage ) => total + usage . seconds , 0 ) ?? 1
152
158
const usageColors = chroma
153
159
. scale ( [ colors . green [ 8 ] , colors . blue [ 8 ] ] )
154
160
. mode ( "lch" )
155
- . colors ( data ?. report . apps_usage . length ?? 0 )
161
+ . colors ( data ?. length ?? 0 )
156
162
// The API returns a row for each app, even if the user didn't use it.
157
- const hasDataAvailable = data ?. report . apps_usage . some ( ( u ) => u . seconds > 0 )
163
+ const hasDataAvailable = data ?. some ( ( u ) => u . seconds > 0 )
158
164
return (
159
- < Panel { ...props } >
165
+ < Panel { ...panelProps } >
160
166
< PanelHeader > App‘s & IDE usage </ PanelHeader >
161
167
< PanelContent >
162
168
{ ! data && < Loader sx = { { height : 200 } } /> }
163
169
{ data && ! hasDataAvailable && < NoDataAvailable sx = { { height : 200 } } /> }
164
170
{ data && hasDataAvailable && (
165
171
< Box sx = { { display : "flex" , flexDirection : "column" , gap : 3 } } >
166
- { data . report . apps_usage
172
+ { data
167
173
. sort ( ( a , b ) => b . seconds - a . seconds )
168
174
. map ( ( usage , i ) => {
169
175
const percentage = ( usage . seconds / totalInSeconds ) * 100
@@ -237,6 +243,8 @@ const Panel = styled(Box)(({ theme }) => ({
237
243
flexDirection : "column" ,
238
244
} ) )
239
245
246
+ type PanelProps = ComponentProps < typeof Panel >
247
+
240
248
const PanelHeader = styled ( Box ) ( ( { theme } ) => ( {
241
249
fontSize : 14 ,
242
250
fontWeight : 500 ,
@@ -269,6 +277,20 @@ const NoDataAvailable = (props: BoxProps) => {
269
277
)
270
278
}
271
279
280
+ function mapToDAUsResponse (
281
+ data : TemplateInsightsResponse [ "interval_reports" ] ,
282
+ ) : DAUsResponse {
283
+ return {
284
+ tz_hour_offset : 0 ,
285
+ entries : data . map ( ( d ) => {
286
+ return {
287
+ amount : d . active_users ,
288
+ date : d . end_time ,
289
+ }
290
+ } ) ,
291
+ }
292
+ }
293
+
272
294
function toTimeFilter ( date : Date ) {
273
295
date . setHours ( 0 , 0 , 0 , 0 )
274
296
const year = date . getUTCFullYear ( )
@@ -294,3 +316,7 @@ function formatTime(seconds: number): string {
294
316
}
295
317
}
296
318
}
319
+
320
+ function sevenDaysAgo ( ) {
321
+ return subDays ( new Date ( ) , 7 )
322
+ }
0 commit comments