added meta data

This commit is contained in:
Nate Kelley 2025-09-24 12:39:45 -06:00
parent 86bcf6f00c
commit 53a955dfbe
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
4 changed files with 83 additions and 17 deletions

View File

@ -1,5 +1,5 @@
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { useCallback, useEffect } from 'react'; import { useCallback, useEffect, useMemo } from 'react';
import { versionGetAppVersion } from '@/api/query_keys/version'; import { versionGetAppVersion } from '@/api/query_keys/version';
import { Text } from '@/components/ui/typography'; import { Text } from '@/components/ui/typography';
import { useWindowFocus } from '@/hooks/useWindowFocus'; import { useWindowFocus } from '@/hooks/useWindowFocus';
@ -53,17 +53,6 @@ export const useAppVersion = () => {
}; };
const AppVersionMessage = () => { const AppVersionMessage = () => {
// const [countdown, setCountdown] = useState(180);
// useEffect(() => {
// const interval = setInterval(() => {
// setCountdown((prev) => Math.max(prev - 1, 0));
// if (countdown === 0) {
// window.location.reload();
// }
// }, 1000);
// return () => clearInterval(interval);
// }, []);
return ( return (
<Text> <Text>
A new version of the app is available. Please refresh the page to get the latest features. A new version of the app is available. Please refresh the page to get the latest features.
@ -78,3 +67,12 @@ export const useIsVersionChanged = () => {
}); });
return data; return data;
}; };
export const useAppVersionMeta = () => {
const { data } = useQuery({
...versionGetAppVersion,
select: (data) => data,
notifyOnChangeProps: ['data'],
});
return useMemo(() => ({ ...data, browserBuild }), [data]);
};

View File

@ -2,7 +2,6 @@ import { isServer } from '@tanstack/react-query';
import { ClientOnly } from '@tanstack/react-router'; import { ClientOnly } from '@tanstack/react-router';
import type { PostHogConfig } from 'posthog-js'; import type { PostHogConfig } from 'posthog-js';
import React, { type PropsWithChildren, useEffect, useState } from 'react'; import React, { type PropsWithChildren, useEffect, useState } from 'react';
import { useGetUserTeams } from '@/api/buster_rest/users';
import { import {
useGetUserBasicInfo, useGetUserBasicInfo,
useGetUserOrganization, useGetUserOrganization,
@ -10,10 +9,8 @@ import {
import { ComponentErrorCard } from '@/components/features/global/ComponentErrorCard'; import { ComponentErrorCard } from '@/components/features/global/ComponentErrorCard';
import { isDev } from '@/config/dev'; import { isDev } from '@/config/dev';
import { env } from '@/env'; import { env } from '@/env';
import { useMount } from '@/hooks/useMount'; import { useAppVersionMeta } from '../AppVersion/useAppVersion';
import packageJson from '../../../package.json';
const version = packageJson.version;
const POSTHOG_KEY = env.VITE_PUBLIC_POSTHOG_KEY; const POSTHOG_KEY = env.VITE_PUBLIC_POSTHOG_KEY;
const DEBUG_POSTHOG = false; const DEBUG_POSTHOG = false;
@ -41,6 +38,7 @@ const options: Partial<PostHogConfig> = {
}; };
const PosthogWrapper: React.FC<PropsWithChildren> = ({ children }) => { const PosthogWrapper: React.FC<PropsWithChildren> = ({ children }) => {
const appVersionMeta = useAppVersionMeta();
const user = useGetUserBasicInfo(); const user = useGetUserBasicInfo();
const userOrganizations = useGetUserOrganization(); const userOrganizations = useGetUserOrganization();
const userOrganizationId = userOrganizations?.id || ''; const userOrganizationId = userOrganizations?.id || '';
@ -89,8 +87,34 @@ const PosthogWrapper: React.FC<PropsWithChildren> = ({ children }) => {
organization: userOrganizations, organization: userOrganizations,
}); });
posthog.group(userOrganizationId, userOrganizationName); posthog.group(userOrganizationId, userOrganizationName);
// Register app version metadata to be included with all events
if (appVersionMeta) {
posthog.register({
app_version: appVersionMeta.buildId,
browser_build: appVersionMeta.browserBuild,
server_build: appVersionMeta.buildId,
version_changed: appVersionMeta.buildId !== appVersionMeta.browserBuild,
});
} }
}, [user?.id, userOrganizationId, userOrganizationName, posthogModules]); }
}, [user?.id, userOrganizationId, userOrganizationName, posthogModules, appVersionMeta]);
// Update app version metadata when it changes after PostHog is initialized
useEffect(() => {
if (posthogModules?.posthog && appVersionMeta) {
const { posthog } = posthogModules;
if (posthog.__loaded) {
posthog.register({
app_version: appVersionMeta.buildId,
browser_build: appVersionMeta.browserBuild,
server_build: appVersionMeta.buildId,
version_changed: appVersionMeta.buildId !== appVersionMeta.browserBuild,
});
}
}
}, [appVersionMeta, posthogModules]);
// Show children while loading or if modules failed to load // Show children while loading or if modules failed to load
if (isLoading || !posthogModules) { if (isLoading || !posthogModules) {

View File

@ -21,6 +21,7 @@ import { Route as AppIndexRouteImport } from './routes/app/index'
import { Route as AuthResetPasswordRouteImport } from './routes/auth.reset-password' import { Route as AuthResetPasswordRouteImport } from './routes/auth.reset-password'
import { Route as AuthLogoutRouteImport } from './routes/auth.logout' import { Route as AuthLogoutRouteImport } from './routes/auth.logout'
import { Route as AuthLoginRouteImport } from './routes/auth.login' import { Route as AuthLoginRouteImport } from './routes/auth.login'
import { Route as AppThrowRouteImport } from './routes/app.throw'
import { Route as AppSettingsRouteImport } from './routes/app/_settings' import { Route as AppSettingsRouteImport } from './routes/app/_settings'
import { Route as AppAppRouteImport } from './routes/app/_app' import { Route as AppAppRouteImport } from './routes/app/_app'
import { Route as EmbedReportReportIdRouteImport } from './routes/embed/report.$reportId' import { Route as EmbedReportReportIdRouteImport } from './routes/embed/report.$reportId'
@ -206,6 +207,11 @@ const AuthLoginRoute = AuthLoginRouteImport.update({
path: '/login', path: '/login',
getParentRoute: () => AuthRoute, getParentRoute: () => AuthRoute,
} as any) } as any)
const AppThrowRoute = AppThrowRouteImport.update({
id: '/throw',
path: '/throw',
getParentRoute: () => AppRoute,
} as any)
const AppSettingsRoute = AppSettingsRouteImport.update({ const AppSettingsRoute = AppSettingsRouteImport.update({
id: '/_settings', id: '/_settings',
getParentRoute: () => AppRoute, getParentRoute: () => AppRoute,
@ -933,6 +939,7 @@ export interface FileRoutesByFullPath {
'/auth': typeof AuthRouteWithChildren '/auth': typeof AuthRouteWithChildren
'/embed': typeof EmbedRouteWithChildren '/embed': typeof EmbedRouteWithChildren
'/healthcheck': typeof HealthcheckRoute '/healthcheck': typeof HealthcheckRoute
'/app/throw': typeof AppThrowRoute
'/auth/login': typeof AuthLoginRoute '/auth/login': typeof AuthLoginRoute
'/auth/logout': typeof AuthLogoutRoute '/auth/logout': typeof AuthLogoutRoute
'/auth/reset-password': typeof AuthResetPasswordRoute '/auth/reset-password': typeof AuthResetPasswordRoute
@ -1041,6 +1048,7 @@ export interface FileRoutesByTo {
'/embed': typeof EmbedRouteWithChildren '/embed': typeof EmbedRouteWithChildren
'/healthcheck': typeof HealthcheckRoute '/healthcheck': typeof HealthcheckRoute
'/app': typeof AppSettingsRestricted_layoutAdmin_onlyRouteWithChildren '/app': typeof AppSettingsRestricted_layoutAdmin_onlyRouteWithChildren
'/app/throw': typeof AppThrowRoute
'/auth/login': typeof AuthLoginRoute '/auth/login': typeof AuthLoginRoute
'/auth/logout': typeof AuthLogoutRoute '/auth/logout': typeof AuthLogoutRoute
'/auth/reset-password': typeof AuthResetPasswordRoute '/auth/reset-password': typeof AuthResetPasswordRoute
@ -1134,6 +1142,7 @@ export interface FileRoutesById {
'/healthcheck': typeof HealthcheckRoute '/healthcheck': typeof HealthcheckRoute
'/app/_app': typeof AppAppRouteWithChildren '/app/_app': typeof AppAppRouteWithChildren
'/app/_settings': typeof AppSettingsRouteWithChildren '/app/_settings': typeof AppSettingsRouteWithChildren
'/app/throw': typeof AppThrowRoute
'/auth/login': typeof AuthLoginRoute '/auth/login': typeof AuthLoginRoute
'/auth/logout': typeof AuthLogoutRoute '/auth/logout': typeof AuthLogoutRoute
'/auth/reset-password': typeof AuthResetPasswordRoute '/auth/reset-password': typeof AuthResetPasswordRoute
@ -1258,6 +1267,7 @@ export interface FileRouteTypes {
| '/auth' | '/auth'
| '/embed' | '/embed'
| '/healthcheck' | '/healthcheck'
| '/app/throw'
| '/auth/login' | '/auth/login'
| '/auth/logout' | '/auth/logout'
| '/auth/reset-password' | '/auth/reset-password'
@ -1366,6 +1376,7 @@ export interface FileRouteTypes {
| '/embed' | '/embed'
| '/healthcheck' | '/healthcheck'
| '/app' | '/app'
| '/app/throw'
| '/auth/login' | '/auth/login'
| '/auth/logout' | '/auth/logout'
| '/auth/reset-password' | '/auth/reset-password'
@ -1458,6 +1469,7 @@ export interface FileRouteTypes {
| '/healthcheck' | '/healthcheck'
| '/app/_app' | '/app/_app'
| '/app/_settings' | '/app/_settings'
| '/app/throw'
| '/auth/login' | '/auth/login'
| '/auth/logout' | '/auth/logout'
| '/auth/reset-password' | '/auth/reset-password'
@ -1669,6 +1681,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthLoginRouteImport preLoaderRoute: typeof AuthLoginRouteImport
parentRoute: typeof AuthRoute parentRoute: typeof AuthRoute
} }
'/app/throw': {
id: '/app/throw'
path: '/throw'
fullPath: '/app/throw'
preLoaderRoute: typeof AppThrowRouteImport
parentRoute: typeof AppRoute
}
'/app/_settings': { '/app/_settings': {
id: '/app/_settings' id: '/app/_settings'
path: '' path: ''
@ -3195,12 +3214,14 @@ const AppSettingsRouteWithChildren = AppSettingsRoute._addFileChildren(
interface AppRouteChildren { interface AppRouteChildren {
AppAppRoute: typeof AppAppRouteWithChildren AppAppRoute: typeof AppAppRouteWithChildren
AppSettingsRoute: typeof AppSettingsRouteWithChildren AppSettingsRoute: typeof AppSettingsRouteWithChildren
AppThrowRoute: typeof AppThrowRoute
AppIndexRoute: typeof AppIndexRoute AppIndexRoute: typeof AppIndexRoute
} }
const AppRouteChildren: AppRouteChildren = { const AppRouteChildren: AppRouteChildren = {
AppAppRoute: AppAppRouteWithChildren, AppAppRoute: AppAppRouteWithChildren,
AppSettingsRoute: AppSettingsRouteWithChildren, AppSettingsRoute: AppSettingsRouteWithChildren,
AppThrowRoute: AppThrowRoute,
AppIndexRoute: AppIndexRoute, AppIndexRoute: AppIndexRoute,
} }

View File

@ -0,0 +1,23 @@
import { createFileRoute } from '@tanstack/react-router';
import { useState } from 'react';
import { useMount } from '../hooks/useMount';
export const Route = createFileRoute('/app/throw')({
component: RouteComponent,
});
function RouteComponent() {
const [throwError, setThrowError] = useState(false);
useMount(() => {
setTimeout(() => {
setThrowError(true);
}, 1000);
});
if (throwError) {
throw new Error('Nate is testing this error');
}
return <div>Hello "/app/throw"! {throwError ? 'Throwing error' : 'Not throwing error'}</div>;
}