From b826c43987639e481e8453c6ad99b7e258c63b53 Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Mon, 30 Sep 2024 14:22:40 +0200 Subject: [PATCH] Calculate path prefix directly in initial settings Redux value (#14981) Without this, the page that is shown first renders once with an empty path prefix value, since the settings update takes a render cycle to complete. However, we only fetch certain data from the API exactly once for a given page, and not for every re-render with changed path prefix value (and we also wouldn't want to fetch it from the wrong location initially). This duplicates the served endpoint list once more, but exporting them from App.tsx would also have been dirty (hot reload only works when a file only exports one component and nothing else, thus there'd be a linter warning). Signed-off-by: Julius Volz --- web/ui/mantine-ui/src/App.tsx | 32 ++------------------ web/ui/mantine-ui/src/state/settingsSlice.ts | 30 ++++++++++++++++-- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/web/ui/mantine-ui/src/App.tsx b/web/ui/mantine-ui/src/App.tsx index 3e3466825c..3bec30fa31 100644 --- a/web/ui/mantine-ui/src/App.tsx +++ b/web/ui/mantine-ui/src/App.tsx @@ -56,12 +56,11 @@ import TSDBStatusPage from "./pages/TSDBStatusPage"; import FlagsPage from "./pages/FlagsPage"; import ConfigPage from "./pages/ConfigPage"; import AgentPage from "./pages/AgentPage"; -import { Suspense, useEffect } from "react"; +import { Suspense } from "react"; import ErrorBoundary from "./components/ErrorBoundary"; import { ThemeSelector } from "./components/ThemeSelector"; import { Notifications } from "@mantine/notifications"; -import { useAppDispatch } from "./state/hooks"; -import { updateSettings, useSettings } from "./state/settingsSlice"; +import { useSettings } from "./state/settingsSlice"; import SettingsMenu from "./components/SettingsMenu"; import ReadinessWrapper from "./components/ReadinessWrapper"; import NotificationsProvider from "./components/NotificationsProvider"; @@ -172,37 +171,12 @@ const theme = createTheme({ }, }); -// 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 pagePaths = [ - ...mainNavPages, - ...allStatusPages, - { path: "/agent" }, - ].map((p) => p.path); - - const pagePath = pagePaths.find((p) => path.endsWith(p)); - return path.slice(0, path.length - (pagePath || "").length); -}; - const navLinkXPadding = "md"; function App() { const [opened, { toggle }] = useDisclosure(); - const pathPrefix = getPathPrefix(window.location.pathname); - const dispatch = useAppDispatch(); - - useEffect(() => { - dispatch(updateSettings({ pathPrefix })); - }, [pathPrefix, dispatch]); - - const { agentMode, consolesLink } = useSettings(); + const { agentMode, consolesLink, pathPrefix } = useSettings(); const navLinks = ( <> diff --git a/web/ui/mantine-ui/src/state/settingsSlice.ts b/web/ui/mantine-ui/src/state/settingsSlice.ts index 1591c43882..ea744e0149 100644 --- a/web/ui/mantine-ui/src/state/settingsSlice.ts +++ b/web/ui/mantine-ui/src/state/settingsSlice.ts @@ -4,7 +4,7 @@ import { initializeFromLocalStorage } from "./initializeFromLocalStorage"; interface Settings { consolesLink: string | null; - lookbackDelta: string, + lookbackDelta: string; agentMode: boolean; ready: boolean; pathPrefix: string; @@ -30,6 +30,32 @@ export const localStorageKeyEnableSyntaxHighlighting = export const localStorageKeyEnableLinter = "settings.enableLinter"; export const localStorageKeyShowAnnotations = "settings.showAnnotations"; +// 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 pagePaths = [ + "/query", + "/alerts", + "/targets", + "/rules", + "/service-discovery", + "/status", + "/tsdb-status", + "/flags", + "/config", + "/alertmanager-discovery", + "/agent", + ]; + + const pagePath = pagePaths.find((p) => path.endsWith(p)); + return path.slice(0, path.length - (pagePath || "").length); +}; + export const initialState: Settings = { consolesLink: GLOBAL_CONSOLES_LINK === "CONSOLES_LINK_PLACEHOLDER" || @@ -44,7 +70,7 @@ export const initialState: Settings = { GLOBAL_LOOKBACKDELTA === null ? "" : GLOBAL_LOOKBACKDELTA, - pathPrefix: "", + pathPrefix: getPathPrefix(window.location.pathname), useLocalTime: initializeFromLocalStorage( localStorageKeyUseLocalTime, false