mirror of
https://github.com/prometheus/prometheus.git
synced 2025-02-21 03:16:00 -08:00
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 <julius.volz@gmail.com>
117 lines
3.4 KiB
TypeScript
117 lines
3.4 KiB
TypeScript
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
|
|
import { useAppSelector } from "./hooks";
|
|
import { initializeFromLocalStorage } from "./initializeFromLocalStorage";
|
|
|
|
interface Settings {
|
|
consolesLink: string | null;
|
|
lookbackDelta: string;
|
|
agentMode: boolean;
|
|
ready: boolean;
|
|
pathPrefix: string;
|
|
useLocalTime: boolean;
|
|
enableQueryHistory: boolean;
|
|
enableAutocomplete: boolean;
|
|
enableSyntaxHighlighting: boolean;
|
|
enableLinter: boolean;
|
|
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;
|
|
declare const GLOBAL_LOOKBACKDELTA: string;
|
|
|
|
export const localStorageKeyUseLocalTime = "settings.useLocalTime";
|
|
export const localStorageKeyEnableQueryHistory = "settings.enableQueryHistory";
|
|
export const localStorageKeyEnableAutocomplete = "settings.enableAutocomplete";
|
|
export const localStorageKeyEnableSyntaxHighlighting =
|
|
"settings.enableSyntaxHighlighting";
|
|
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" ||
|
|
GLOBAL_CONSOLES_LINK === "" ||
|
|
GLOBAL_CONSOLES_LINK === null
|
|
? null
|
|
: GLOBAL_CONSOLES_LINK,
|
|
agentMode: GLOBAL_AGENT_MODE === "true",
|
|
ready: GLOBAL_READY === "true",
|
|
lookbackDelta:
|
|
GLOBAL_LOOKBACKDELTA === "LOOKBACKDELTA_PLACEHOLDER" ||
|
|
GLOBAL_LOOKBACKDELTA === null
|
|
? ""
|
|
: GLOBAL_LOOKBACKDELTA,
|
|
pathPrefix: getPathPrefix(window.location.pathname),
|
|
useLocalTime: initializeFromLocalStorage<boolean>(
|
|
localStorageKeyUseLocalTime,
|
|
false
|
|
),
|
|
enableQueryHistory: initializeFromLocalStorage<boolean>(
|
|
localStorageKeyEnableQueryHistory,
|
|
false
|
|
),
|
|
enableAutocomplete: initializeFromLocalStorage<boolean>(
|
|
localStorageKeyEnableAutocomplete,
|
|
true
|
|
),
|
|
enableSyntaxHighlighting: initializeFromLocalStorage<boolean>(
|
|
localStorageKeyEnableSyntaxHighlighting,
|
|
true
|
|
),
|
|
enableLinter: initializeFromLocalStorage<boolean>(
|
|
localStorageKeyEnableLinter,
|
|
true
|
|
),
|
|
showAnnotations: initializeFromLocalStorage<boolean>(
|
|
localStorageKeyShowAnnotations,
|
|
true
|
|
),
|
|
};
|
|
|
|
export const settingsSlice = createSlice({
|
|
name: "settings",
|
|
initialState,
|
|
reducers: {
|
|
updateSettings: (state, { payload }: PayloadAction<Partial<Settings>>) => {
|
|
Object.assign(state, payload);
|
|
},
|
|
},
|
|
});
|
|
|
|
export const { updateSettings } = settingsSlice.actions;
|
|
|
|
export const useSettings = () => {
|
|
return useAppSelector((state) => state.settings);
|
|
};
|
|
|
|
export default settingsSlice.reducer;
|