Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(site): add template insights page #8722

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1f7120f
Add insights page
BrunoQuaresma Jul 24, 2023
ed5784e
Add experiment
BrunoQuaresma Jul 24, 2023
c5efc1e
fix(site): fix error 'Reduce of empty array with no initial value'
BrunoQuaresma Jul 24, 2023
a1a9952
Merge branch 'bq/fix-js-error' into bq/insights-page
BrunoQuaresma Jul 24, 2023
fdcf23f
Show or not insights page
BrunoQuaresma Jul 24, 2023
dfd2f03
Set basic grid for the panels
BrunoQuaresma Jul 24, 2023
b40bdae
Add DAU panel
BrunoQuaresma Jul 24, 2023
6679ae3
Add avatar url into user latency insihgts
BrunoQuaresma Jul 24, 2023
e35a3b5
List latency by user
BrunoQuaresma Jul 24, 2023
544590d
Add user avatar to the list
BrunoQuaresma Jul 24, 2023
fb32677
Merge branch 'main' into bq/insights-page
BrunoQuaresma Jul 25, 2023
1a32402
Use avatar url
BrunoQuaresma Jul 25, 2023
5274733
Fix icon url
BrunoQuaresma Jul 25, 2023
864c6dd
Add apps and IDE usage
BrunoQuaresma Jul 25, 2023
7ea9a26
Fix title
BrunoQuaresma Jul 25, 2023
2aafcee
Add load and empty states
BrunoQuaresma Jul 25, 2023
941671b
Update date range
BrunoQuaresma Jul 25, 2023
37da9b1
Fix loading and not available data
BrunoQuaresma Jul 25, 2023
b8ce94a
Fix data empty
BrunoQuaresma Jul 25, 2023
06178c9
feat(site): add terminal icon
BrunoQuaresma Jul 25, 2023
117aa82
Merge branch 'main' into bq/insights-page
BrunoQuaresma Jul 25, 2023
e91ca19
Merge branch 'bq/add-terminal-icon' into bq/insights-page
BrunoQuaresma Jul 25, 2023
8be0e42
Consume DAUs from insights
BrunoQuaresma Jul 25, 2023
e2768e3
Apply minor improvements
BrunoQuaresma Jul 25, 2023
9236240
Minor improvements
BrunoQuaresma Jul 25, 2023
f147a4d
Fix deps
BrunoQuaresma Jul 25, 2023
03cb386
Merge branch 'main' into bq/insights-page
BrunoQuaresma Jul 25, 2023
8ed5ca3
Add storybook
BrunoQuaresma Jul 25, 2023
3bc6e6b
Fix deploy settings page
BrunoQuaresma Jul 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Consume DAUs from insights
  • Loading branch information
BrunoQuaresma committed Jul 25, 2023
commit 8be0e42516f05ed5d8486f2be9a73824a176aa0f
5 changes: 4 additions & 1 deletion site/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1386,7 +1386,10 @@ export const getInsightsUserLatency = async (
export const getInsightsTemplate = async (
filters: InsightsFilter,
): Promise<TypesGen.TemplateInsightsResponse> => {
const params = new URLSearchParams(filters)
const params = new URLSearchParams({
...filters,
interval: "day",
})
const response = await axios.get(`/api/v2/insights/templates?${params}`)
return response.data
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ import Box from "@mui/material/Box"
import { styled, useTheme } from "@mui/material/styles"
import { BoxProps } from "@mui/system"
import { useQuery } from "@tanstack/react-query"
import {
getInsightsTemplate,
getInsightsUserLatency,
getTemplateDAUs,
} from "api/api"
import { getInsightsTemplate, getInsightsUserLatency } from "api/api"
import { DAUChart } from "components/DAUChart/DAUChart"
import { useTemplateLayoutContext } from "components/TemplateLayout/TemplateLayout"
import {
Expand All @@ -22,9 +18,21 @@ import { colors } from "theme/colors"
import { Helmet } from "react-helmet-async"
import { getTemplatePageTitle } from "../utils"
import { Loader } from "components/Loader/Loader"
import { DAUsResponse, TemplateInsightsResponse } from "api/typesGenerated"
import { ComponentProps } from "react"
import subDays from "date-fns/subDays"

export default function TemplateInsightsPage() {
const { template } = useTemplateLayoutContext()
const { data: templateInsights } = useQuery({
queryKey: ["templates", template.id, "usage"],
queryFn: () =>
getInsightsTemplate({
template_ids: template.id,
start_time: toTimeFilter(sevenDaysAgo()),
end_time: toTimeFilter(new Date()),
}),
})

return (
<>
Expand All @@ -40,22 +48,28 @@ export default function TemplateInsightsPage() {
gap: (theme) => theme.spacing(3),
}}
>
<DailyUsersPanel sx={{ gridColumn: "span 2" }} />
<DailyUsersPanel
sx={{ gridColumn: "span 2" }}
data={templateInsights?.interval_reports}
/>
<UserLatencyPanel />
<TemplateUsagePanel sx={{ gridColumn: "span 3" }} />
<TemplateUsagePanel
sx={{ gridColumn: "span 3" }}
data={templateInsights?.report.apps_usage}
/>
</Box>
</>
)
}

const DailyUsersPanel = (props: BoxProps) => {
const { template } = useTemplateLayoutContext()
const { data } = useQuery({
queryKey: ["templates", template.id, "dau"],
queryFn: () => getTemplateDAUs(template.id),
})
const DailyUsersPanel = ({
data,
...panelProps
}: PanelProps & {
data: TemplateInsightsResponse["interval_reports"] | undefined
}) => {
return (
<Panel {...props}>
<Panel {...panelProps}>
<PanelHeader sx={{ display: "flex", alignItems: "center", gap: 1 }}>
Active daily users
<HelpTooltip size="small">
Expand All @@ -67,21 +81,21 @@ const DailyUsersPanel = (props: BoxProps) => {
</PanelHeader>
<PanelContent>
{!data && <Loader sx={{ height: "100%" }} />}
{data && data.entries.length === 0 && <NoDataAvailable />}
{data && data.entries.length > 0 && <DAUChart daus={data} />}
{data && data.length === 0 && <NoDataAvailable />}
{data && data.length > 0 && <DAUChart daus={mapToDAUsResponse(data)} />}
</PanelContent>
</Panel>
)
}

const UserLatencyPanel = (props: BoxProps) => {
const UserLatencyPanel = (props: PanelProps) => {
const { template } = useTemplateLayoutContext()
const { data } = useQuery({
queryKey: ["templates", template.id, "user-latency"],
queryFn: () =>
getInsightsUserLatency({
template_ids: template.id,
start_time: toTimeFilter(new Date(template.created_at)),
start_time: toTimeFilter(sevenDaysAgo()),
end_time: toTimeFilter(new Date()),
}),
})
Expand Down Expand Up @@ -133,37 +147,29 @@ const UserLatencyPanel = (props: BoxProps) => {
)
}

const TemplateUsagePanel = (props: BoxProps) => {
const { template } = useTemplateLayoutContext()
const { data } = useQuery({
queryKey: ["templates", template.id, "usage"],
queryFn: () =>
getInsightsTemplate({
template_ids: template.id,
start_time: toTimeFilter(new Date(template.created_at)),
end_time: toTimeFilter(new Date()),
}),
})
const TemplateUsagePanel = ({
data,
...panelProps
}: PanelProps & {
data: TemplateInsightsResponse["report"]["apps_usage"] | undefined
}) => {
const totalInSeconds =
data?.report.apps_usage.reduce(
(total, usage) => total + usage.seconds,
0,
) ?? 1
data?.reduce((total, usage) => total + usage.seconds, 0) ?? 1
const usageColors = chroma
.scale([colors.green[8], colors.blue[8]])
.mode("lch")
.colors(data?.report.apps_usage.length ?? 0)
.colors(data?.length ?? 0)
// The API returns a row for each app, even if the user didn't use it.
const hasDataAvailable = data?.report.apps_usage.some((u) => u.seconds > 0)
const hasDataAvailable = data?.some((u) => u.seconds > 0)
return (
<Panel {...props}>
<Panel {...panelProps}>
<PanelHeader>App&lsquo;s & IDE usage</PanelHeader>
<PanelContent>
{!data && <Loader sx={{ height: 200 }} />}
{data && !hasDataAvailable && <NoDataAvailable sx={{ height: 200 }} />}
{data && hasDataAvailable && (
<Box sx={{ display: "flex", flexDirection: "column", gap: 3 }}>
{data.report.apps_usage
{data
.sort((a, b) => b.seconds - a.seconds)
.map((usage, i) => {
const percentage = (usage.seconds / totalInSeconds) * 100
Expand Down Expand Up @@ -237,6 +243,8 @@ const Panel = styled(Box)(({ theme }) => ({
flexDirection: "column",
}))

type PanelProps = ComponentProps<typeof Panel>

const PanelHeader = styled(Box)(({ theme }) => ({
fontSize: 14,
fontWeight: 500,
Expand Down Expand Up @@ -269,6 +277,20 @@ const NoDataAvailable = (props: BoxProps) => {
)
}

function mapToDAUsResponse(
data: TemplateInsightsResponse["interval_reports"],
): DAUsResponse {
return {
tz_hour_offset: 0,
entries: data.map((d) => {
return {
amount: d.active_users,
date: d.end_time,
}
}),
}
}

function toTimeFilter(date: Date) {
date.setHours(0, 0, 0, 0)
const year = date.getUTCFullYear()
Expand All @@ -294,3 +316,7 @@ function formatTime(seconds: number): string {
}
}
}

function sevenDaysAgo() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: weekAgo :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good one. I don't think a "week ago" is a good name for this because you are at Wed and a week ago would be the previous week from Mon to Fri so 7 days ago is different and for this case would be more accurate

return subDays(new Date(), 7)
}