mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2025-02-09 15:27:11 +00:00
vmui: add option to customize url params for individual pages (#2582)
This commit is contained in:
parent
87e4e76537
commit
8739fb8a91
3 changed files with 54 additions and 24 deletions
|
@ -19,29 +19,29 @@ import DashboardsLayout from "./components/PredefinedPanels/DashboardsLayout";
|
||||||
const App: FC = () => {
|
const App: FC = () => {
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<CssBaseline /> {/* CSS Baseline: kind of normalize.css made by materialUI team - can be scoped */}
|
<HashRouter>
|
||||||
<LocalizationProvider dateAdapter={DayjsUtils}> {/* Allows datepicker to work with DayJS */}
|
<CssBaseline /> {/* CSS Baseline: kind of normalize.css made by materialUI team - can be scoped */}
|
||||||
<StyledEngineProvider injectFirst>
|
<LocalizationProvider dateAdapter={DayjsUtils}> {/* Allows datepicker to work with DayJS */}
|
||||||
<ThemeProvider theme={THEME}> {/* Material UI theme customization */}
|
<StyledEngineProvider injectFirst>
|
||||||
<StateProvider> {/* Serialized into query string, common app settings */}
|
<ThemeProvider theme={THEME}> {/* Material UI theme customization */}
|
||||||
<AuthStateProvider> {/* Auth related info - optionally persisted to Local Storage */}
|
<StateProvider> {/* Serialized into query string, common app settings */}
|
||||||
<GraphStateProvider> {/* Graph settings */}
|
<AuthStateProvider> {/* Auth related info - optionally persisted to Local Storage */}
|
||||||
<SnackbarProvider> {/* Display various snackbars */}
|
<GraphStateProvider> {/* Graph settings */}
|
||||||
<HashRouter>
|
<SnackbarProvider> {/* Display various snackbars */}
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path={"/"} element={<HomeLayout/>}>
|
<Route path={"/"} element={<HomeLayout/>}>
|
||||||
<Route path={router.home} element={<CustomPanel/>}/>
|
<Route path={router.home} element={<CustomPanel/>}/>
|
||||||
<Route path={router.dashboards} element={<DashboardsLayout/>}/>
|
<Route path={router.dashboards} element={<DashboardsLayout/>}/>
|
||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
</HashRouter>
|
</SnackbarProvider>
|
||||||
</SnackbarProvider>
|
</GraphStateProvider>
|
||||||
</GraphStateProvider>
|
</AuthStateProvider>
|
||||||
</AuthStateProvider>
|
</StateProvider>
|
||||||
</StateProvider>
|
</ThemeProvider>
|
||||||
</ThemeProvider>
|
</StyledEngineProvider>
|
||||||
</StyledEngineProvider>
|
</LocalizationProvider>
|
||||||
</LocalizationProvider>
|
</HashRouter>
|
||||||
</>;
|
</>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React, {createContext, FC, useContext, useEffect, useMemo, useReducer} fr
|
||||||
import {Action, AppState, initialState, reducer} from "./reducer";
|
import {Action, AppState, initialState, reducer} from "./reducer";
|
||||||
import {getQueryStringValue, setQueryStringValue} from "../../utils/query-string";
|
import {getQueryStringValue, setQueryStringValue} from "../../utils/query-string";
|
||||||
import {Dispatch} from "react";
|
import {Dispatch} from "react";
|
||||||
|
import {useLocation} from "react-router-dom";
|
||||||
|
|
||||||
type StateContextType = { state: AppState, dispatch: Dispatch<Action> };
|
type StateContextType = { state: AppState, dispatch: Dispatch<Action> };
|
||||||
|
|
||||||
|
@ -17,12 +18,13 @@ export const initialPrepopulatedState = Object.entries(initialState)
|
||||||
}), {}) as AppState;
|
}), {}) as AppState;
|
||||||
|
|
||||||
export const StateProvider: FC = ({children}) => {
|
export const StateProvider: FC = ({children}) => {
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
const [state, dispatch] = useReducer(reducer, initialPrepopulatedState);
|
const [state, dispatch] = useReducer(reducer, initialPrepopulatedState);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setQueryStringValue(state as unknown as Record<string, unknown>);
|
setQueryStringValue(state as unknown as Record<string, unknown>);
|
||||||
}, [state]);
|
}, [state, location]);
|
||||||
|
|
||||||
const contextValue = useMemo(() => {
|
const contextValue = useMemo(() => {
|
||||||
return { state, dispatch };
|
return { state, dispatch };
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import get from "lodash.get";
|
import get from "lodash.get";
|
||||||
|
import router from "../router";
|
||||||
|
|
||||||
const stateToUrlParams = {
|
const graphStateToUrlParams = {
|
||||||
"time.duration": "range_input",
|
"time.duration": "range_input",
|
||||||
"time.period.date": "end_input",
|
"time.period.date": "end_input",
|
||||||
"time.period.step": "step_input",
|
"time.period.step": "step_input",
|
||||||
"time.relativeTime": "relative_time",
|
"time.relativeTime": "relative_time",
|
||||||
"displayType": "tab"
|
"displayType": "tab",
|
||||||
|
};
|
||||||
|
|
||||||
|
const stateToUrlParams = {
|
||||||
|
[router.home]: graphStateToUrlParams,
|
||||||
|
[router.dashboards]: graphStateToUrlParams,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO need function for detect types.
|
// TODO need function for detect types.
|
||||||
|
@ -32,14 +38,23 @@ const stateToUrlParams = {
|
||||||
export const setQueryStringWithoutPageReload = (qsValue: string): void => {
|
export const setQueryStringWithoutPageReload = (qsValue: string): void => {
|
||||||
const w = window;
|
const w = window;
|
||||||
if (w) {
|
if (w) {
|
||||||
const newurl = `${w.location.protocol}//${w.location.host}${w.location.pathname}?${qsValue}${w.location.hash}`;
|
const qs = qsValue ? `?${qsValue}` : "";
|
||||||
|
const newurl = `${w.location.protocol}//${w.location.host}${w.location.pathname}${qs}${w.location.hash}`;
|
||||||
w.history.pushState({ path: newurl }, "", newurl);
|
w.history.pushState({ path: newurl }, "", newurl);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setQueryStringValue = (newValue: Record<string, unknown>): void => {
|
export const setQueryStringValue = (newValue: Record<string, unknown>): void => {
|
||||||
const queryMap = new Map(Object.entries(stateToUrlParams));
|
const route = window.location.hash.replace("#", "");
|
||||||
const query = get(newValue, "query", "") as string[];
|
const params = stateToUrlParams[route] || {};
|
||||||
|
const queryMap = new Map(Object.entries(params));
|
||||||
|
const isGraphRoute = route === router.home || route === router.dashboards;
|
||||||
|
const newQsValue = isGraphRoute ? getGraphQsValue(newValue, queryMap) : getQsValue(newValue, queryMap);
|
||||||
|
setQueryStringWithoutPageReload(newQsValue.join("&"));
|
||||||
|
};
|
||||||
|
|
||||||
|
const getGraphQsValue = (newValue: Record<string, unknown>, queryMap: Map<string, string>): string[] => {
|
||||||
|
const query = get(newValue, "query", []) as string[];
|
||||||
const newQsValue: string[] = [];
|
const newQsValue: string[] = [];
|
||||||
query.forEach((q, i) => {
|
query.forEach((q, i) => {
|
||||||
queryMap.forEach((queryKey, stateKey) => {
|
queryMap.forEach((queryKey, stateKey) => {
|
||||||
|
@ -52,7 +67,20 @@ export const setQueryStringValue = (newValue: Record<string, unknown>): void =>
|
||||||
newQsValue.push(`g${i}.expr=${encodeURIComponent(q)}`);
|
newQsValue.push(`g${i}.expr=${encodeURIComponent(q)}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
setQueryStringWithoutPageReload(newQsValue.join("&"));
|
return newQsValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getQsValue = (newValue: Record<string, unknown>, queryMap: Map<string, string>): string[] => {
|
||||||
|
const newQsValue: string[] = [];
|
||||||
|
queryMap.forEach((queryKey, stateKey) => {
|
||||||
|
const value = get(newValue, stateKey, "") as string;
|
||||||
|
if (value) {
|
||||||
|
const valueEncoded = encodeURIComponent(value);
|
||||||
|
newQsValue.push(`${queryKey}=${valueEncoded}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return newQsValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getQueryStringValue = (
|
export const getQueryStringValue = (
|
||||||
|
|
Loading…
Reference in a new issue