vmui: add option to customize url params for individual pages (#2582)

This commit is contained in:
Yury Molodov 2022-05-17 14:13:15 +03:00 committed by Aliaksandr Valialkin
parent 87e4e76537
commit 8739fb8a91
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1
3 changed files with 54 additions and 24 deletions

View file

@ -19,29 +19,29 @@ import DashboardsLayout from "./components/PredefinedPanels/DashboardsLayout";
const App: FC = () => {
return <>
<CssBaseline /> {/* CSS Baseline: kind of normalize.css made by materialUI team - can be scoped */}
<LocalizationProvider dateAdapter={DayjsUtils}> {/* Allows datepicker to work with DayJS */}
<StyledEngineProvider injectFirst>
<ThemeProvider theme={THEME}> {/* Material UI theme customization */}
<StateProvider> {/* Serialized into query string, common app settings */}
<AuthStateProvider> {/* Auth related info - optionally persisted to Local Storage */}
<GraphStateProvider> {/* Graph settings */}
<SnackbarProvider> {/* Display various snackbars */}
<HashRouter>
<HashRouter>
<CssBaseline /> {/* CSS Baseline: kind of normalize.css made by materialUI team - can be scoped */}
<LocalizationProvider dateAdapter={DayjsUtils}> {/* Allows datepicker to work with DayJS */}
<StyledEngineProvider injectFirst>
<ThemeProvider theme={THEME}> {/* Material UI theme customization */}
<StateProvider> {/* Serialized into query string, common app settings */}
<AuthStateProvider> {/* Auth related info - optionally persisted to Local Storage */}
<GraphStateProvider> {/* Graph settings */}
<SnackbarProvider> {/* Display various snackbars */}
<Routes>
<Route path={"/"} element={<HomeLayout/>}>
<Route path={router.home} element={<CustomPanel/>}/>
<Route path={router.dashboards} element={<DashboardsLayout/>}/>
</Route>
</Routes>
</HashRouter>
</SnackbarProvider>
</GraphStateProvider>
</AuthStateProvider>
</StateProvider>
</ThemeProvider>
</StyledEngineProvider>
</LocalizationProvider>
</SnackbarProvider>
</GraphStateProvider>
</AuthStateProvider>
</StateProvider>
</ThemeProvider>
</StyledEngineProvider>
</LocalizationProvider>
</HashRouter>
</>;
};

View file

@ -2,6 +2,7 @@ import React, {createContext, FC, useContext, useEffect, useMemo, useReducer} fr
import {Action, AppState, initialState, reducer} from "./reducer";
import {getQueryStringValue, setQueryStringValue} from "../../utils/query-string";
import {Dispatch} from "react";
import {useLocation} from "react-router-dom";
type StateContextType = { state: AppState, dispatch: Dispatch<Action> };
@ -17,12 +18,13 @@ export const initialPrepopulatedState = Object.entries(initialState)
}), {}) as AppState;
export const StateProvider: FC = ({children}) => {
const location = useLocation();
const [state, dispatch] = useReducer(reducer, initialPrepopulatedState);
useEffect(() => {
setQueryStringValue(state as unknown as Record<string, unknown>);
}, [state]);
}, [state, location]);
const contextValue = useMemo(() => {
return { state, dispatch };

View file

@ -1,12 +1,18 @@
import qs from "qs";
import get from "lodash.get";
import router from "../router";
const stateToUrlParams = {
const graphStateToUrlParams = {
"time.duration": "range_input",
"time.period.date": "end_input",
"time.period.step": "step_input",
"time.relativeTime": "relative_time",
"displayType": "tab"
"displayType": "tab",
};
const stateToUrlParams = {
[router.home]: graphStateToUrlParams,
[router.dashboards]: graphStateToUrlParams,
};
// TODO need function for detect types.
@ -32,14 +38,23 @@ const stateToUrlParams = {
export const setQueryStringWithoutPageReload = (qsValue: string): void => {
const w = window;
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);
}
};
export const setQueryStringValue = (newValue: Record<string, unknown>): void => {
const queryMap = new Map(Object.entries(stateToUrlParams));
const query = get(newValue, "query", "") as string[];
const route = window.location.hash.replace("#", "");
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[] = [];
query.forEach((q, i) => {
queryMap.forEach((queryKey, stateKey) => {
@ -52,7 +67,20 @@ export const setQueryStringValue = (newValue: Record<string, unknown>): void =>
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 = (