import "@mantine/core/styles.css"; import "@mantine/code-highlight/styles.css"; import "@mantine/notifications/styles.css"; import "@mantine/dates/styles.css"; import classes from "./App.module.css"; import PrometheusLogo from "./images/prometheus-logo.svg"; import { ActionIcon, Affix, AppShell, Box, Burger, Button, Group, MantineProvider, Menu, Skeleton, Text, Transition, createTheme, rem, } from "@mantine/core"; import { useDisclosure, useWindowScroll } from "@mantine/hooks"; import { IconAdjustments, IconArrowUp, IconBellFilled, IconChevronDown, IconChevronRight, IconCloudDataConnection, IconDatabase, IconDatabaseSearch, IconFileAnalytics, IconFlag, IconHeartRateMonitor, IconInfoCircle, IconServerCog, IconSettings, } from "@tabler/icons-react"; import { BrowserRouter, NavLink, Navigate, Route, Routes, } from "react-router-dom"; import { IconTable } from "@tabler/icons-react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; // import { ReactQueryDevtools } from "react-query/devtools"; import QueryPage from "./pages/query/QueryPage"; import AlertsPage from "./pages/AlertsPage"; import RulesPage from "./pages/RulesPage"; import TargetsPage from "./pages/TargetsPage"; import ServiceDiscoveryPage from "./pages/ServiceDiscoveryPage"; import StatusPage from "./pages/StatusPage"; import TSDBStatusPage from "./pages/TSDBStatusPage"; import FlagsPage from "./pages/FlagsPage"; import ConfigPage from "./pages/ConfigPage"; import AgentPage from "./pages/AgentPage"; import { Suspense, useContext } from "react"; import ErrorBoundary from "./ErrorBoundary"; import { ThemeSelector } from "./ThemeSelector"; import { SettingsContext } from "./settings"; import { Notifications } from "@mantine/notifications"; import { useAppDispatch } from "./state/hooks"; import { updateSettings } from "./state/settingsSlice"; const queryClient = new QueryClient(); const navIconStyle = { width: rem(15), height: rem(15) }; const mainNavPages = [ { title: "Query", path: "/query", icon: , element: , }, { title: "Alerts", path: "/alerts", icon: , element: , }, ]; const monitoringStatusPages = [ { title: "Targets", path: "/targets", icon: , element: , }, { title: "Rules", path: "/rules", icon: , element: , }, { title: "Service discovery", path: "/service-discovery", icon: , element: , }, ]; const serverStatusPages = [ { title: "Runtime & build information", path: "/status", icon: , element: , }, { title: "TSDB status", path: "/tsdb-status", icon: , element: , }, { title: "Command-line flags", path: "/flags", icon: , element: , }, { title: "Configuration", path: "/config", icon: , element: , }, ]; const allStatusPages = [...monitoringStatusPages, ...serverStatusPages]; const allPages = [...mainNavPages, ...allStatusPages]; const theme = createTheme({ colors: { "codebox-bg": [ "#f5f5f5", "#e7e7e7", "#cdcdcd", "#b2b2b2", "#9a9a9a", "#8b8b8b", "#848484", "#717171", "#656565", "#575757", ], }, }); // This dynamically/generically determines the pathPrefix by stripping the first known // endpoint suffix from the window location path. It works out of the box for both direct // hosting and reverse proxy deployments with no additional configurations required. const getPathPrefix = (path: string) => { if (path.endsWith("/")) { path = path.slice(0, -1); } const pagePath = allPages.find((p) => path.endsWith(p.path))?.path; return path.slice(0, path.length - (pagePath || "").length); }; const navLinkXPadding = "md"; function App() { const [scroll, scrollTo] = useWindowScroll(); const [opened, { toggle }] = useDisclosure(); const { agentMode } = useContext(SettingsContext); const pathPrefix = getPathPrefix(window.location.pathname); const dispatch = useAppDispatch(); dispatch(updateSettings({ pathPrefix })); const navLinks = ( <> {mainNavPages.map((p) => ( ))} {allStatusPages.map((p) => ( } /> ))} } /> Monitoring status {monitoringStatusPages.map((p) => ( {p.title} ))} Server status {serverStatusPages.map((p) => ( {p.title} ))} {/* */} ); return ( Prometheus{agentMode && " Agent"} {navLinks} {} } > Settings {navLinks} {Array.from(Array(10), (_, i) => ( ))} } > } /> } /> } /> } /> {allStatusPages.map((p) => ( ))} 0}> {(transitionStyles) => ( )} {/* */} ); } export default App;