feat(ServiceMap): dispatch isLoaded route via context

This commit is contained in:
Nidhi Tandon 2021-05-23 14:15:13 +05:30
parent 245050aac2
commit 44495b7669
4 changed files with 132 additions and 42 deletions

View File

@ -17,6 +17,7 @@ import {
SettingsPage, SettingsPage,
IntstrumentationPage, IntstrumentationPage,
} from "Src/pages"; } from "Src/pages";
import { RouteProvider } from "./RouteProvider";
const App = () => { const App = () => {
const { status } = useThemeSwitcher(); const { status } = useThemeSwitcher();
@ -30,42 +31,38 @@ const App = () => {
<Suspense fallback={<Spin size="large" />}> <Suspense fallback={<Spin size="large" />}>
<Route path={"/"}> <Route path={"/"}>
<Switch> <Switch>
<BaseLayout> <RouteProvider>
<Route path={ROUTES.SIGN_UP} exact component={Signup} /> <BaseLayout>
<Route path={ROUTES.APPLICATION} exact component={ServicesTable} /> <Route path={ROUTES.SIGN_UP} exact component={Signup} />
<Route path={ROUTES.SERVICE_METRICS} exact component={ServiceMetrics} /> <Route path={ROUTES.APPLICATION} exact component={ServicesTable} />
<Route <Route path={ROUTES.SERVICE_METRICS} exact component={ServiceMetrics} />
path={ROUTES.SERVICE_MAP} <Route path={ROUTES.SERVICE_MAP} exact component={ServiceMap} />
exact <Route path={ROUTES.TRACES} exact component={TraceDetail} />
render={(props) => ( <Route path={ROUTES.TRACE_GRAPH} exact component={TraceGraph} />
<ServiceMap {...props} componentPath={ROUTES.SERVICE_MAP} /> <Route path={ROUTES.SETTINGS} exact component={SettingsPage} />
)} <Route
/> path={ROUTES.INSTRUMENTATION}
<Route path={ROUTES.TRACES} exact component={TraceDetail} /> exact
<Route path={ROUTES.TRACE_GRAPH} exact component={TraceGraph} /> component={IntstrumentationPage}
<Route path={ROUTES.SETTINGS} exact component={SettingsPage} /> />
<Route <Route
path={ROUTES.INSTRUMENTATION} path={ROUTES.USAGE_EXPLORER}
exact exactexact
component={IntstrumentationPage} component={UsageExplorer}
/> />
<Route <Route
path={ROUTES.USAGE_EXPLORER} path="/"
exactexact exact
component={UsageExplorer} render={() => {
/> return localStorage.getItem(IS_LOGGED_IN) === "yes" ? (
<Route <Redirect to={ROUTES.APPLICATION} />
path="/" ) : (
exact <Redirect to={ROUTES.SIGN_UP} />
render={() => { );
return localStorage.getItem(IS_LOGGED_IN) === "yes" ? ( }}
<Redirect to={ROUTES.APPLICATION} /> />
) : ( </BaseLayout>
<Redirect to={ROUTES.SIGN_UP} /> </RouteProvider>
);
}}
/>
</BaseLayout>
</Switch> </Switch>
</Route> </Route>
</Suspense> </Suspense>

View File

@ -1,15 +1,55 @@
import React, { ReactNode } from "react"; import React, { ReactNode, useEffect } from "react";
import { Layout } from "antd"; import { Layout } from "antd";
import SideNav from "./Nav/SideNav"; import SideNav from "./Nav/SideNav";
import TopNav from "./Nav/TopNav"; import TopNav from "./Nav/TopNav";
import { useLocation } from "react-router-dom";
import ROUTES from "Src/constants/routes";
import { useRoute } from "./RouteProvider";
const { Content, Footer } = Layout; const { Content, Footer } = Layout;
interface BaseLayoutProps { interface BaseLayoutProps {
children: ReactNode; children: ReactNode;
} }
interface RouteObj {
[key: string]: {
route: string;
isLoaded: boolean;
};
}
const BaseLayout: React.FC<BaseLayoutProps> = ({ children }) => { const BaseLayout: React.FC<BaseLayoutProps> = ({ children }) => {
const location = useLocation();
const { dispatch } = useRoute();
/*
Create a routes obj with values as
{
SERVICE_MAP: {
route: '/service-map',
isLoaded: false
}
*/
const routes: RouteObj = {};
Object.keys(ROUTES).map((items) => {
routes[items] = {
route: `${ROUTES[items]}`,
isLoaded: false,
};
});
useEffect(() => {
/*
Update the isLoaded property in routes obj
if the route matches the current pathname
*/
Object.keys(ROUTES).map((items) => {
routes[items].isLoaded = routes[items].route === location.pathname;
});
dispatch({ type: "UPDATE", payload: routes });
}, [location]);
return ( return (
<Layout style={{ minHeight: "100vh" }}> <Layout style={{ minHeight: "100vh" }}>
<SideNav /> <SideNav />

View File

@ -0,0 +1,51 @@
import React, { useContext, createContext, ReactNode, Dispatch } from "react";
type State = {
[key: string]: {
route: string;
isLoaded: boolean;
};
};
type Action = {
type: "UPDATE";
payload: State;
};
interface ContextType {
state: State;
dispatch: Dispatch<Action>;
}
const RouteContext = createContext<ContextType | null>(null);
interface RouteProviderProps {
children: ReactNode;
}
const updateLocation = (state: State, action: Action): State => {
if (action.type === "UPDATE") {
return {
...state,
...action.payload,
};
}
return {
...state,
};
};
const RouteProvider: React.FC<RouteProviderProps> = ({ children }) => {
const [state, dispatch] = React.useReducer(updateLocation, {});
const value = { state, dispatch };
return <RouteContext.Provider value={value}>{children}</RouteContext.Provider>;
};
const useRoute = (): ContextType => {
const context = useContext(RouteContext);
if (context === undefined) {
throw new Error("useRoute must be used within a RouteProvider");
}
return context as ContextType;
};
export { RouteProvider, useRoute };

View File

@ -1,6 +1,6 @@
import React, { useEffect, useRef } from "react"; import React, { useContext, useEffect, useRef } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { RouteComponentProps, useLocation } from "react-router-dom"; import { RouteComponentProps } from "react-router-dom";
import { import {
GlobalTime, GlobalTime,
serviceMapStore, serviceMapStore,
@ -14,6 +14,7 @@ import { StoreState } from "../../store/reducers";
import { getZoomPx, getGraphData, getTooltip, transformLabel } from "./utils"; import { getZoomPx, getGraphData, getTooltip, transformLabel } from "./utils";
import SelectService from "./SelectService"; import SelectService from "./SelectService";
import { ForceGraph2D } from "react-force-graph"; import { ForceGraph2D } from "react-force-graph";
import { useRoute } from "../RouteProvider";
const Container = styled.div` const Container = styled.div`
.force-graph-container .graph-tooltip { .force-graph-container .graph-tooltip {
@ -54,16 +55,17 @@ export interface graphDataType {
const ServiceMap = (props: ServiceMapProps) => { const ServiceMap = (props: ServiceMapProps) => {
const fgRef = useRef(); const fgRef = useRef();
const location = useLocation(); const { state } = useRoute();
const { const {
getDetailedServiceMapItems, getDetailedServiceMapItems,
getServiceMapItems, getServiceMapItems,
globalTime, globalTime,
serviceMap, serviceMap,
componentPath,
} = props; } = props;
useEffect(() => { useEffect(() => {
if (location.pathname === componentPath) { if (state.SERVICE_MAP.isLoaded) {
getServiceMapItems(globalTime); getServiceMapItems(globalTime);
getDetailedServiceMapItems(globalTime); getDetailedServiceMapItems(globalTime);
} }