Enable rum for good
This commit is contained in:
parent
9302a940a0
commit
af75776dae
4 changed files with 217 additions and 104 deletions
133
ui/src/App.tsx
133
ui/src/App.tsx
|
|
@ -1,124 +1,49 @@
|
|||
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
||||
import { LoginPage } from "@ui/pages/login";
|
||||
import { SignUpPage } from "@ui/pages/signup";
|
||||
import { BrowserRouter as Router, useRoutes } from "react-router-dom";
|
||||
import { ThemeProvider } from "@ui/contexts/ThemeContext";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { ResetPasswordPage } from "@ui/pages/reset-password";
|
||||
import { LandingPage } from "@ui/pages/landing";
|
||||
import { PublicRoute } from "@ui/components/PublicRoute";
|
||||
import { TabloPage } from "@ui/pages/tablo";
|
||||
import { SessionProvider } from "@ui/contexts/SessionContext";
|
||||
import { OAuthSigninPage } from "@ui/pages/oauth-signin";
|
||||
import { NotFoundPage } from "@ui/pages/NotFoundPage";
|
||||
import { Layout } from "@ui/components/Layout";
|
||||
import { DevisPage } from "@ui/pages/devis";
|
||||
import { FacturesPage } from "@ui/pages/factures";
|
||||
import { PlanningPage } from "@ui/pages/planning";
|
||||
import { ChantiersPage } from "@ui/pages/chantiers";
|
||||
import { ChatPage } from "@ui/pages/chat";
|
||||
import { FeedbackPage } from "@ui/pages/feedback";
|
||||
import { SupportPage } from "@ui/pages/support";
|
||||
import { AllCommunityModule, ModuleRegistry } from "ag-grid-community";
|
||||
import ChatProvider from "@ui/providers/ChatProvider";
|
||||
import { UserStoreProvider } from "@ui/providers/UserStoreProvider";
|
||||
import { ProtectedRoute } from "@ui/components/ProtectedRoute";
|
||||
import { JoinPage } from "@ui/pages/join";
|
||||
import { CreateEventModal } from "@ui/components/CreateEventModal";
|
||||
import { isProd } from "@ui/utils/helpers";
|
||||
import { useEffect } from "react";
|
||||
import { datadogRum } from "@datadog/browser-rum";
|
||||
import { initRum } from "@ui/lib/rum";
|
||||
import { DatadogRumProvider } from "@ui/providers/DatadogRumProvider";
|
||||
import { routes } from "@ui/lib/routes";
|
||||
|
||||
// Register all Community features
|
||||
ModuleRegistry.registerModules([AllCommunityModule]);
|
||||
|
||||
export const App = () => {
|
||||
useEffect(() => {
|
||||
initRum();
|
||||
datadogRum.startSessionReplayRecording();
|
||||
}, [location]);
|
||||
const AppRoutes = () => {
|
||||
const element = useRoutes(routes);
|
||||
return element;
|
||||
};
|
||||
|
||||
export const App = () => {
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<SessionProvider>
|
||||
<UserStoreProvider>
|
||||
<Router>
|
||||
<div
|
||||
className={twMerge(
|
||||
"min-h-screen",
|
||||
!isProd ? "bg-orange-50" : "bg-white",
|
||||
"dark:bg-gray-900"
|
||||
)}
|
||||
>
|
||||
<Routes>
|
||||
<Route path="/" element={<ProtectedRoute fallback="/login" />}>
|
||||
<Route element={<Layout />}>
|
||||
<Route index element={<TabloPage />} />
|
||||
<Route path="tablo" element={<TabloPage />} />
|
||||
<Route path="devis" element={<DevisPage />} />
|
||||
<Route path="factures" element={<FacturesPage />} />
|
||||
<Route path="planning" element={<PlanningPage />}>
|
||||
<Route index />
|
||||
<Route path=":tablo_id" />
|
||||
<Route path="create" element={<CreateEventModal />} />
|
||||
</Route>
|
||||
<Route path="kanban" element={<NotFoundPage />}>
|
||||
<Route index />
|
||||
<Route path=":tablo_id" />
|
||||
</Route>
|
||||
<Route path="chantiers" element={<ChantiersPage />} />
|
||||
<Route
|
||||
path="chat"
|
||||
element={
|
||||
<ChatProvider>
|
||||
<ChatPage />
|
||||
</ChatProvider>
|
||||
}
|
||||
>
|
||||
<Route index />
|
||||
<Route path=":channelId" />
|
||||
</Route>
|
||||
<Route path="feedback" element={<FeedbackPage />} />
|
||||
<Route path="support" element={<SupportPage />} />
|
||||
</Route>
|
||||
</Route>
|
||||
|
||||
<Route
|
||||
element={
|
||||
<ProtectedRoute
|
||||
fallback="/login"
|
||||
shouldRedirectToCurrentPage
|
||||
/>
|
||||
<DatadogRumProvider>
|
||||
<div
|
||||
className={twMerge(
|
||||
"min-h-screen",
|
||||
!isProd ? "bg-orange-50" : "bg-white",
|
||||
"dark:bg-gray-900"
|
||||
)}
|
||||
>
|
||||
<AppRoutes />
|
||||
<style>
|
||||
{`
|
||||
@keyframes slide {
|
||||
0% { transform: translateX(-100vw); }
|
||||
100% { transform: translateX(100vw); }
|
||||
}
|
||||
>
|
||||
<Route element={<Layout />}>
|
||||
<Route path="join/:tablo_name" element={<JoinPage />} />
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path="login-with-oauth" element={<OAuthSigninPage />} />
|
||||
<Route path="landing" element={<LandingPage />} />
|
||||
<Route element={<PublicRoute />}>
|
||||
<Route path="login" element={<LoginPage />} />
|
||||
<Route path="signup" element={<SignUpPage />} />
|
||||
<Route
|
||||
path="reset-password"
|
||||
element={<ResetPasswordPage />}
|
||||
/>
|
||||
</Route>
|
||||
<Route path="*" element={<NotFoundPage />} />
|
||||
</Routes>
|
||||
<style>
|
||||
{`
|
||||
@keyframes slide {
|
||||
0% { transform: translateX(-100vw); }
|
||||
100% { transform: translateX(100vw); }
|
||||
}
|
||||
.animate-slide {
|
||||
animation: slide 24s linear infinite;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</div>
|
||||
.animate-slide {
|
||||
animation: slide 24s linear infinite;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</div>
|
||||
</DatadogRumProvider>
|
||||
</Router>
|
||||
</UserStoreProvider>
|
||||
</SessionProvider>
|
||||
|
|
|
|||
139
ui/src/lib/routes.tsx
Normal file
139
ui/src/lib/routes.tsx
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
import { RouteObject } from "react-router-dom";
|
||||
import { ProtectedRoute } from "@ui/components/ProtectedRoute";
|
||||
import { Layout } from "@ui/components/Layout";
|
||||
import { TabloPage } from "@ui/pages/tablo";
|
||||
import { DevisPage } from "@ui/pages/devis";
|
||||
import { FacturesPage } from "@ui/pages/factures";
|
||||
import { PlanningPage } from "@ui/pages/planning";
|
||||
import { NotFoundPage } from "@ui/pages/NotFoundPage";
|
||||
import { JoinPage } from "@ui/pages/join";
|
||||
import { OAuthSigninPage } from "@ui/pages/oauth-signin";
|
||||
import { LandingPage } from "@ui/pages/landing";
|
||||
import { LoginPage } from "@ui/pages/login";
|
||||
import { SignUpPage } from "@ui/pages/signup";
|
||||
import { ResetPasswordPage } from "@ui/pages/reset-password";
|
||||
import { PublicRoute } from "@ui/components/PublicRoute";
|
||||
import ChatProvider from "@ui/providers/ChatProvider";
|
||||
import { CreateEventModal } from "@ui/components/CreateEventModal";
|
||||
import { ChantiersPage } from "@ui/pages/chantiers";
|
||||
import { ChatPage } from "@ui/pages/chat";
|
||||
import { FeedbackPage } from "@ui/pages/feedback";
|
||||
import { SupportPage } from "@ui/pages/support";
|
||||
|
||||
export const routes: RouteObject[] = [
|
||||
// Protected routes
|
||||
{
|
||||
path: "/",
|
||||
element: <ProtectedRoute fallback="/login" />,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
element: <Layout />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <TabloPage />,
|
||||
},
|
||||
{
|
||||
path: "tablo",
|
||||
element: <TabloPage />,
|
||||
},
|
||||
{
|
||||
path: "devis",
|
||||
element: <DevisPage />,
|
||||
},
|
||||
{
|
||||
path: "factures",
|
||||
element: <FacturesPage />,
|
||||
},
|
||||
{
|
||||
path: "planning",
|
||||
element: <PlanningPage />,
|
||||
children: [
|
||||
{ index: true },
|
||||
{ path: ":tablo_id" },
|
||||
{ path: "create", element: <CreateEventModal /> },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "kanban",
|
||||
element: <NotFoundPage />,
|
||||
children: [{ index: true }, { path: ":tablo_id" }],
|
||||
},
|
||||
{
|
||||
path: "chantiers",
|
||||
element: <ChantiersPage />,
|
||||
},
|
||||
{
|
||||
path: "chat",
|
||||
element: (
|
||||
<ChatProvider>
|
||||
<ChatPage />
|
||||
</ChatProvider>
|
||||
),
|
||||
children: [{ index: true }, { path: ":channelId" }],
|
||||
},
|
||||
{
|
||||
path: "feedback",
|
||||
element: <FeedbackPage />,
|
||||
},
|
||||
{
|
||||
path: "support",
|
||||
element: <SupportPage />,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
// Protected routes with redirect to current page
|
||||
{
|
||||
path: "/join/:tablo_name",
|
||||
element: <ProtectedRoute fallback="/login" shouldRedirectToCurrentPage />,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
element: <Layout />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <JoinPage />,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
// OAuth signin route
|
||||
{
|
||||
path: "/login-with-oauth",
|
||||
element: <OAuthSigninPage />,
|
||||
},
|
||||
// Landing page
|
||||
{
|
||||
path: "/landing",
|
||||
element: <LandingPage />,
|
||||
},
|
||||
// Public routes (authentication pages)
|
||||
{
|
||||
path: "/",
|
||||
element: <PublicRoute />,
|
||||
children: [
|
||||
{
|
||||
path: "login",
|
||||
element: <LoginPage />,
|
||||
},
|
||||
{
|
||||
path: "signup",
|
||||
element: <SignUpPage />,
|
||||
},
|
||||
{
|
||||
path: "reset-password",
|
||||
element: <ResetPasswordPage />,
|
||||
},
|
||||
],
|
||||
},
|
||||
// Catch-all route for 404
|
||||
{
|
||||
path: "*",
|
||||
element: <NotFoundPage />,
|
||||
},
|
||||
];
|
||||
|
|
@ -15,5 +15,7 @@ export const initRum = () => {
|
|||
sessionReplaySampleRate: 80,
|
||||
defaultPrivacyLevel: "mask-user-input",
|
||||
plugins: [reactPlugin({ router: true })],
|
||||
trackViewsManually: true,
|
||||
startSessionReplayRecordingManually: false,
|
||||
});
|
||||
};
|
||||
|
|
|
|||
47
ui/src/providers/DatadogRumProvider.tsx
Normal file
47
ui/src/providers/DatadogRumProvider.tsx
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import { datadogRum } from "@datadog/browser-rum";
|
||||
import { routes } from "@ui/lib/routes";
|
||||
import { initRum } from "@ui/lib/rum";
|
||||
import { useEffect } from "react";
|
||||
import { matchRoutes, RouteMatch, useLocation } from "react-router-dom";
|
||||
|
||||
function computeViewName(routeMatches: RouteMatch[]) {
|
||||
let viewName = "";
|
||||
for (let index = 0; index < routeMatches.length; index++) {
|
||||
const routeMatch = routeMatches[index];
|
||||
const path = routeMatch.route.path;
|
||||
// Skip pathless routes
|
||||
if (!path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (path.startsWith("/")) {
|
||||
// Handle absolute child route paths
|
||||
viewName = path;
|
||||
} else {
|
||||
// Handle route paths ending with "/"
|
||||
viewName += viewName.endsWith("/") ? path : `/${path}`;
|
||||
}
|
||||
}
|
||||
|
||||
return viewName || "/";
|
||||
}
|
||||
|
||||
export const DatadogRumProvider = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
const location = useLocation();
|
||||
useEffect(() => {
|
||||
initRum();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const routeMatches = matchRoutes(routes, location.pathname);
|
||||
const viewName = routeMatches && computeViewName(routeMatches);
|
||||
if (viewName) {
|
||||
datadogRum.startView({ name: viewName });
|
||||
}
|
||||
}, [location.pathname]);
|
||||
return <>{children}</>;
|
||||
};
|
||||
Loading…
Reference in a new issue