diff --git a/web/ui/mantine-ui/src/App.tsx b/web/ui/mantine-ui/src/App.tsx index 5592ece21..54082741b 100644 --- a/web/ui/mantine-ui/src/App.tsx +++ b/web/ui/mantine-ui/src/App.tsx @@ -55,13 +55,12 @@ 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 { Suspense } from "react"; import ErrorBoundary from "./components/ErrorBoundary"; import { ThemeSelector } from "./components/ThemeSelector"; -import { SettingsContext } from "./settings"; import { Notifications } from "@mantine/notifications"; import { useAppDispatch } from "./state/hooks"; -import { updateSettings } from "./state/settingsSlice"; +import { updateSettings, useSettings } from "./state/settingsSlice"; import SettingsMenu from "./components/SettingsMenu"; const queryClient = new QueryClient(); @@ -182,12 +181,13 @@ 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 { agentMode } = useSettings(); + const navLinks = ( <> {mainNavPages diff --git a/web/ui/mantine-ui/src/api/api.ts b/web/ui/mantine-ui/src/api/api.ts index 2cc18029f..9c8db2e3f 100644 --- a/web/ui/mantine-ui/src/api/api.ts +++ b/web/ui/mantine-ui/src/api/api.ts @@ -1,5 +1,5 @@ import { useQuery, useSuspenseQuery } from "@tanstack/react-query"; -import { useAppSelector } from "../state/hooks"; +import { useSettings } from "../state/settingsSlice"; export const API_PATH = "api/v1"; @@ -92,7 +92,7 @@ export const useAPIQuery = ({ params, enabled, }: QueryOptions) => { - const pathPrefix = useAppSelector((state) => state.settings.pathPrefix); + const { pathPrefix } = useSettings(); return useQuery>({ queryKey: key ? [key] : [path, params], @@ -105,7 +105,7 @@ export const useAPIQuery = ({ }; export const useSuspenseAPIQuery = ({ key, path, params }: QueryOptions) => { - const pathPrefix = useAppSelector((state) => state.settings.pathPrefix); + const { pathPrefix } = useSettings(); return useSuspenseQuery>({ queryKey: key ? [key] : [path, params], diff --git a/web/ui/mantine-ui/src/components/SettingsMenu.tsx b/web/ui/mantine-ui/src/components/SettingsMenu.tsx index 45f91b391..7552693d7 100644 --- a/web/ui/mantine-ui/src/components/SettingsMenu.tsx +++ b/web/ui/mantine-ui/src/components/SettingsMenu.tsx @@ -1,8 +1,8 @@ import { Popover, ActionIcon, Fieldset, Checkbox, Stack } from "@mantine/core"; import { IconSettings } from "@tabler/icons-react"; import { FC } from "react"; -import { useAppDispatch, useAppSelector } from "../state/hooks"; -import { updateSettings } from "../state/settingsSlice"; +import { useAppDispatch } from "../state/hooks"; +import { updateSettings, useSettings } from "../state/settingsSlice"; const SettingsMenu: FC = () => { const { @@ -12,7 +12,7 @@ const SettingsMenu: FC = () => { enableSyntaxHighlighting, enableLinter, showAnnotations, - } = useAppSelector((state) => state.settings); + } = useSettings(); const dispatch = useAppDispatch(); return ( diff --git a/web/ui/mantine-ui/src/main.tsx b/web/ui/mantine-ui/src/main.tsx index 6136fa893..eaf55214e 100644 --- a/web/ui/mantine-ui/src/main.tsx +++ b/web/ui/mantine-ui/src/main.tsx @@ -1,33 +1,14 @@ import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App.tsx"; -import { Settings, SettingsContext } from "./settings.ts"; import store from "./state/store.ts"; import { Provider } from "react-redux"; import "./fonts/codicon.ttf"; -// Declared/defined in public/index.html, value replaced by Prometheus when serving bundle. -declare const GLOBAL_CONSOLES_LINK: string; -declare const GLOBAL_AGENT_MODE: string; -declare const GLOBAL_READY: string; - -const settings: Settings = { - consolesLink: - GLOBAL_CONSOLES_LINK === "CONSOLES_LINK_PLACEHOLDER" || - GLOBAL_CONSOLES_LINK === "" || - GLOBAL_CONSOLES_LINK === null - ? null - : GLOBAL_CONSOLES_LINK, - agentMode: GLOBAL_AGENT_MODE === "true", - ready: GLOBAL_READY === "true", -}; - ReactDOM.createRoot(document.getElementById("root")!).render( - - - - - + + + ); diff --git a/web/ui/mantine-ui/src/pages/AlertsPage.tsx b/web/ui/mantine-ui/src/pages/AlertsPage.tsx index 414779aad..25f1ecc32 100644 --- a/web/ui/mantine-ui/src/pages/AlertsPage.tsx +++ b/web/ui/mantine-ui/src/pages/AlertsPage.tsx @@ -22,6 +22,7 @@ import { useAppDispatch, useAppSelector } from "../state/hooks"; import { IconInfoCircle, IconSearch } from "@tabler/icons-react"; import { LabelBadges } from "../components/LabelBadges"; import { updateAlertFilters } from "../state/alertsPageSlice"; +import { useSettings } from "../state/settingsSlice"; export default function AlertsPage() { const { data } = useSuspenseAPIQuery({ @@ -32,9 +33,7 @@ export default function AlertsPage() { }); const dispatch = useAppDispatch(); - const showAnnotations = useAppSelector( - (state) => state.settings.showAnnotations - ); + const { showAnnotations } = useSettings(); const filters = useAppSelector((state) => state.alertsPage.filters); const ruleStatsCount = { @@ -56,8 +55,8 @@ export default function AlertsPage() { o === "inactive" ? badgeClasses.healthOk : o === "pending" - ? badgeClasses.healthWarn - : badgeClasses.healthErr + ? badgeClasses.healthWarn + : badgeClasses.healthErr } placeholder="Filter by alert state" values={filters.state} @@ -121,8 +120,8 @@ export default function AlertsPage() { numFiring > 0 ? "5px solid var(--mantine-color-red-4)" : numPending > 0 - ? "5px solid var(--mantine-color-orange-5)" - : "5px solid var(--mantine-color-green-4)", + ? "5px solid var(--mantine-color-orange-5)" + : "5px solid var(--mantine-color-green-4)", }} > diff --git a/web/ui/mantine-ui/src/pages/TSDBStatusPage.tsx b/web/ui/mantine-ui/src/pages/TSDBStatusPage.tsx index e315ea99b..44e67a38b 100644 --- a/web/ui/mantine-ui/src/pages/TSDBStatusPage.tsx +++ b/web/ui/mantine-ui/src/pages/TSDBStatusPage.tsx @@ -1,8 +1,8 @@ import { Stack, Card, Group, Table, Text } from "@mantine/core"; import { useSuspenseAPIQuery } from "../api/api"; import { TSDBStatusResult } from "../api/responseTypes/tsdbStatus"; -import { useAppSelector } from "../state/hooks"; import { formatTimestamp } from "../lib/formatTime"; +import { useSettings } from "../state/settingsSlice"; export default function TSDBStatusPage() { const { @@ -17,7 +17,7 @@ export default function TSDBStatusPage() { }, } = useSuspenseAPIQuery({ path: `/status/tsdb` }); - const useLocalTime = useAppSelector((state) => state.settings.useLocalTime); + const { useLocalTime } = useSettings(); const unixToTime = (unix: number): string => { const formatted = formatTimestamp(unix, useLocalTime); diff --git a/web/ui/mantine-ui/src/pages/query/DataTable.tsx b/web/ui/mantine-ui/src/pages/query/DataTable.tsx index 733d3fe1d..e401edea1 100644 --- a/web/ui/mantine-ui/src/pages/query/DataTable.tsx +++ b/web/ui/mantine-ui/src/pages/query/DataTable.tsx @@ -21,11 +21,11 @@ import { useAPIQuery } from "../../api/api"; import classes from "./DataTable.module.css"; import dayjs from "dayjs"; import timezone from "dayjs/plugin/timezone"; -import { useAppSelector } from "../../state/hooks"; import { formatTimestamp } from "../../lib/formatTime"; import HistogramChart from "./HistogramChart"; import { Histogram } from "../../types/types"; import { bucketRangeString } from "./HistogramHelpers"; +import { useSettings } from "../../state/settingsSlice"; dayjs.extend(timezone); const maxFormattableSeries = 1000; @@ -64,7 +64,7 @@ const DataTable: FC = ({ expr, evalTime, retriggerIdx }) => { expr !== "" && refetch(); }, [retriggerIdx, refetch, expr, evalTime]); - const useLocalTime = useAppSelector((state) => state.settings.useLocalTime); + const { useLocalTime } = useSettings(); // Show a skeleton only on the first load, not on subsequent ones. if (isLoading) { diff --git a/web/ui/mantine-ui/src/pages/query/ExpressionInput.tsx b/web/ui/mantine-ui/src/pages/query/ExpressionInput.tsx index 53c817106..cbb4823b2 100644 --- a/web/ui/mantine-ui/src/pages/query/ExpressionInput.tsx +++ b/web/ui/mantine-ui/src/pages/query/ExpressionInput.tsx @@ -61,7 +61,7 @@ import { } from "@tabler/icons-react"; import { useAPIQuery } from "../../api/api"; import { notifications } from "@mantine/notifications"; -import { useAppSelector } from "../../state/hooks"; +import { useSettings } from "../../state/settingsSlice"; const promqlExtension = new PromQLExtension(); @@ -126,7 +126,7 @@ const ExpressionInput: FC = ({ enableAutocomplete, enableSyntaxHighlighting, enableLinter, - } = useAppSelector((state) => state.settings); + } = useSettings(); const [expr, setExpr] = useState(initialExpr); useEffect(() => { setExpr(initialExpr); diff --git a/web/ui/mantine-ui/src/pages/query/TimeInput.tsx b/web/ui/mantine-ui/src/pages/query/TimeInput.tsx index a5ac8305a..193b2bba0 100644 --- a/web/ui/mantine-ui/src/pages/query/TimeInput.tsx +++ b/web/ui/mantine-ui/src/pages/query/TimeInput.tsx @@ -2,7 +2,7 @@ import { Group, ActionIcon, CloseButton } from "@mantine/core"; import { DatesProvider, DateTimePicker } from "@mantine/dates"; import { IconChevronLeft, IconChevronRight } from "@tabler/icons-react"; import { FC } from "react"; -import { useAppSelector } from "../../state/hooks"; +import { useSettings } from "../../state/settingsSlice"; interface TimeInputProps { time: number | null; // Timestamp in milliseconds. @@ -20,7 +20,7 @@ const TimeInput: FC = ({ onChangeTime, }) => { const baseTime = () => (time !== null ? time : Date.now().valueOf()); - const useLocalTime = useAppSelector((state) => state.settings.useLocalTime); + const { useLocalTime } = useSettings(); return ( diff --git a/web/ui/mantine-ui/src/settings.ts b/web/ui/mantine-ui/src/settings.ts deleted file mode 100644 index 1595870a7..000000000 --- a/web/ui/mantine-ui/src/settings.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { createContext } from "react"; - -export interface Settings { - consolesLink: string | null; - agentMode: boolean; - ready: boolean; -} - -export const SettingsContext = createContext({ - consolesLink: null, - agentMode: false, - ready: false, -}); diff --git a/web/ui/mantine-ui/src/state/settingsSlice.ts b/web/ui/mantine-ui/src/state/settingsSlice.ts index 199e63add..b315dda7e 100644 --- a/web/ui/mantine-ui/src/state/settingsSlice.ts +++ b/web/ui/mantine-ui/src/state/settingsSlice.ts @@ -1,6 +1,10 @@ import { PayloadAction, createSlice } from "@reduxjs/toolkit"; +import { useAppSelector } from "./hooks"; interface Settings { + consolesLink: string | null; + agentMode: boolean; + ready: boolean; pathPrefix: string; useLocalTime: boolean; enableQueryHistory: boolean; @@ -10,7 +14,20 @@ interface Settings { showAnnotations: boolean; } +// Declared/defined in public/index.html, value replaced by Prometheus when serving bundle. +declare const GLOBAL_CONSOLES_LINK: string; +declare const GLOBAL_AGENT_MODE: string; +declare const GLOBAL_READY: string; + const initialState: Settings = { + consolesLink: + GLOBAL_CONSOLES_LINK === "CONSOLES_LINK_PLACEHOLDER" || + GLOBAL_CONSOLES_LINK === "" || + GLOBAL_CONSOLES_LINK === null + ? null + : GLOBAL_CONSOLES_LINK, + agentMode: GLOBAL_AGENT_MODE === "true", + ready: GLOBAL_READY === "true", pathPrefix: "", useLocalTime: false, enableQueryHistory: false, @@ -32,4 +49,8 @@ export const settingsSlice = createSlice({ export const { updateSettings } = settingsSlice.actions; +export const useSettings = () => { + return useAppSelector((state) => state.settings); +}; + export default settingsSlice.reducer;