diff --git a/frontend/src/AppRoutes/index.tsx b/frontend/src/AppRoutes/index.tsx new file mode 100644 index 0000000000..17eeec680e --- /dev/null +++ b/frontend/src/AppRoutes/index.tsx @@ -0,0 +1,43 @@ +import React, { Suspense } from "react"; +import ROUTES from "constants/routes"; +import { BrowserRouter, Route, Switch, Redirect } from "react-router-dom"; +import Spinner from "components/Spinner"; +import NotFound from "components/NotFound"; + +import { IS_LOGGED_IN } from "constants/auth"; + +import AppLayout from "modules/AppLayout"; +import { RouteProvider } from "modules/RouteProvider"; +import routes from "./routes"; + +const App = () => ( + + + + }> + + {routes.map(({ path, component, exact }) => { + return ; + })} + + {/* This logic should be moved to app layout */} + { + return localStorage.getItem(IS_LOGGED_IN) === "yes" ? ( + + ) : ( + + ); + }} + /> + + + + + + +); + +export default App; diff --git a/frontend/src/AppRoutes/routes.ts b/frontend/src/AppRoutes/routes.ts new file mode 100644 index 0000000000..967f8e7160 --- /dev/null +++ b/frontend/src/AppRoutes/routes.ts @@ -0,0 +1,70 @@ +import { + ServiceMetricsPage, + ServiceMapPage, + TraceDetailPage, + TraceGraphPage, + UsageExplorerPage, + ServicesTablePage, + SignupPage, + SettingsPage, + InstrumentationPage, +} from "pages"; +import ROUTES from "constants/routes"; +import { RouteProps } from "react-router-dom"; + +const routes: AppRoutes[] = [ + { + component: SignupPage, + path: ROUTES.SIGN_UP, + exact: true, + }, + { + component: ServicesTablePage, + path: ROUTES.APPLICATION, + exact: true, + }, + { + path: ROUTES.SERVICE_METRICS, + exact: true, + component: ServiceMetricsPage, + }, + { + path: ROUTES.SERVICE_MAP, + component: ServiceMapPage, + exact: true, + }, + { + path: ROUTES.TRACE_GRAPH, + exact: true, + component: TraceGraphPage, + }, + { + path: ROUTES.SETTINGS, + exact: true, + component: SettingsPage, + }, + { + path: ROUTES.USAGE_EXPLORER, + exact: true, + component: UsageExplorerPage, + }, + { + path: ROUTES.INSTRUMENTATION, + exact: true, + component: InstrumentationPage, + }, + { + path: ROUTES.TRACES, + exact: true, + component: TraceDetailPage, + }, +]; + +interface AppRoutes { + component: RouteProps["component"]; + path: RouteProps["path"]; + exact: RouteProps["exact"]; + isPrivate?: boolean; +} + +export default routes; diff --git a/frontend/src/components/Loadable/index.tsx b/frontend/src/components/Loadable/index.tsx new file mode 100644 index 0000000000..c2967bdfc3 --- /dev/null +++ b/frontend/src/components/Loadable/index.tsx @@ -0,0 +1,17 @@ +import { lazy, ComponentType } from "react"; + +function Loadable(importPath: { + (): LoadableProps; +}): React.LazyExoticComponent { + const LazyComponent = lazy(() => importPath()); + + return LazyComponent; +} + +type LazyComponent = ComponentType>; + +type LoadableProps = Promise<{ + default: LazyComponent; +}>; + +export default Loadable; diff --git a/frontend/src/components/Spiner.tsx b/frontend/src/components/Spiner.tsx deleted file mode 100644 index ea2d02a1cb..0000000000 --- a/frontend/src/components/Spiner.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import { Spin } from 'antd'; -import styled from "styled-components"; -import { LoadingOutlined } from '@ant-design/icons'; -const antIcon = ; - -const SpinerStyle = styled.div` -position: fixed; -z-index: 999; -height: 4em; -// width: 4em; -overflow: visible; -margin: auto; -top: 0; -left: 50%; -bottom: 0; -right: 0; -`; - -export const CustomSpinner = ({ - size, - tip, -}:{ - size:string, - tip:string, -})=>{ - return( - <> - - - - - ) -} - -export const DefaultSpinner = ()=>{ - return( - <> - - - ) -} \ No newline at end of file diff --git a/frontend/src/components/Spinner/index.tsx b/frontend/src/components/Spinner/index.tsx new file mode 100644 index 0000000000..1c9dd0a7c6 --- /dev/null +++ b/frontend/src/components/Spinner/index.tsx @@ -0,0 +1,19 @@ +import React from "react"; +import { Spin, SpinProps } from "antd"; +import { LoadingOutlined } from "@ant-design/icons"; + +import { SpinerStyle } from "./styles"; + +const Spinner = ({ size, tip, height }: SpinnerProps): JSX.Element => ( + + } /> + +); + +interface SpinnerProps { + size?: SpinProps["size"]; + tip?: SpinProps["tip"]; + height?: React.CSSProperties["height"]; +} + +export default Spinner; diff --git a/frontend/src/components/Spinner/styles.ts b/frontend/src/components/Spinner/styles.ts new file mode 100644 index 0000000000..c84a071053 --- /dev/null +++ b/frontend/src/components/Spinner/styles.ts @@ -0,0 +1,16 @@ +import React from "react"; +import styled from "styled-components"; + +interface Props { + height: React.CSSProperties["height"]; +} + +export const SpinerStyle = styled.div` + z-index: 999; + overflow: visible; + margin: auto; + display: flex; + justify-content: center; + align-items: center; + height: ${({ height = "100vh" }) => height}; +`; diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index e1d50d7d3f..84813ff216 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -3,18 +3,15 @@ import ReactDOM from "react-dom"; import { Provider } from "react-redux"; import { ThemeSwitcherProvider } from "react-css-theme-switcher"; import store from "store"; -import AppWrapper from "modules/AppWrapper"; +import AppRoutes from "AppRoutes"; import "assets/index.css"; -import { BrowserRouter as Router } from "react-router-dom"; import themes from "themes"; ReactDOM.render( - - - + , diff --git a/frontend/src/modules/BaseLayout.tsx b/frontend/src/modules/AppLayout.tsx similarity index 100% rename from frontend/src/modules/BaseLayout.tsx rename to frontend/src/modules/AppLayout.tsx diff --git a/frontend/src/modules/AppWrapper.tsx b/frontend/src/modules/AppWrapper.tsx deleted file mode 100644 index b3e1a2b2dc..0000000000 --- a/frontend/src/modules/AppWrapper.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import React, { Suspense } from "react"; -import { useThemeSwitcher } from "react-css-theme-switcher"; -import ROUTES from "constants/routes"; -import { IS_LOGGED_IN } from "constants/auth"; -import { BrowserRouter, Route, Switch, Redirect } from "react-router-dom"; -import { CustomSpinner } from "components/Spiner"; - -import BaseLayout from "./BaseLayout"; -import { - ServiceMetrics, - ServiceMap, - TraceDetail, - TraceGraph, - UsageExplorer, - ServicesTable, - Signup, - SettingsPage, - InstrumentationPage, -} from "pages"; -import { RouteProvider } from "./RouteProvider"; -import NotFound from "components/NotFound"; - -const App = () => { - const { status } = useThemeSwitcher(); - - if (status === "loading") { - return ; - } - - return ( - - - - }> - - - - - - - - - - - { - return localStorage.getItem(IS_LOGGED_IN) === "yes" ? ( - - ) : ( - - ); - }} - /> - - - - - - - - ); -}; - -export default App; diff --git a/frontend/src/modules/Metrics/ServicesTable.tsx b/frontend/src/modules/Metrics/ServicesTable.tsx index 51a37a211f..836b022e5c 100644 --- a/frontend/src/modules/Metrics/ServicesTable.tsx +++ b/frontend/src/modules/Metrics/ServicesTable.tsx @@ -3,13 +3,13 @@ import { NavLink } from "react-router-dom"; import { Button, Space, Table } from "antd"; import styled from "styled-components"; import { connect } from "react-redux"; +import Spinner from "components/Spinner"; import { SKIP_ONBOARDING } from "constants/onboarding"; import ROUTES from "constants/routes"; import { getServicesList, GlobalTime } from "store/actions"; import { servicesListItem } from "store/actions/MetricsActions"; import { StoreState } from "store/reducers"; import { CustomModal } from "components/Modal"; -import { CustomSpinner, DefaultSpinner } from "components/Spiner"; interface ServicesTableProps { servicesList: servicesListItem[]; @@ -124,7 +124,7 @@ const _ServicesTable = (props: ServicesTableProps) => { }, [props.servicesList, errorObject]); if (!initialDataFetch) { - return ; + return ; } if (refetchFromBackend && !skipOnboarding) { @@ -150,7 +150,7 @@ const _ServicesTable = (props: ServicesTableProps) => { allowFullScreen >
- +
No instrumentation data. diff --git a/frontend/src/modules/Servicemap/ServiceMap.tsx b/frontend/src/modules/Servicemap/ServiceMap.tsx index b16d24a513..09182c05ae 100644 --- a/frontend/src/modules/Servicemap/ServiceMap.tsx +++ b/frontend/src/modules/Servicemap/ServiceMap.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useRef } from "react"; import { connect } from "react-redux"; -import { RouteComponentProps } from "react-router-dom"; +import { RouteComponentProps, withRouter } from "react-router-dom"; import { GlobalTime, serviceMapStore, @@ -13,8 +13,8 @@ import { StoreState } from "store/reducers"; import { getZoomPx, getGraphData, getTooltip, transformLabel } from "./utils"; import SelectService from "./SelectService"; import { ForceGraph2D } from "react-force-graph"; +import Spinner from "components/Spinner"; import { useRoute } from "modules/RouteProvider"; -import { CustomSpinner } from "components/Spiner"; const Container = styled.div` .force-graph-container .graph-tooltip { @@ -78,7 +78,7 @@ const ServiceMap = (props: ServiceMapProps) => { fgRef.current && fgRef.current.d3Force("charge").strength(-400); }); if (!serviceMap.items.length || !serviceMap.services.length) { - return ; + return ; } const zoomToService = (value: string) => { @@ -150,7 +150,9 @@ const mapStateToProps = ( }; }; -export default connect(mapStateToProps, { - getServiceMapItems: getServiceMapItems, - getDetailedServiceMapItems: getDetailedServiceMapItems, -})(ServiceMap); +export default withRouter( + connect(mapStateToProps, { + getServiceMapItems: getServiceMapItems, + getDetailedServiceMapItems: getDetailedServiceMapItems, + })(ServiceMap), +); diff --git a/frontend/src/pages.ts b/frontend/src/pages.ts index ffe2fb173d..8e31f8648c 100644 --- a/frontend/src/pages.ts +++ b/frontend/src/pages.ts @@ -1,28 +1,61 @@ -import React from "react"; +import Loadable from "./components/Loadable"; -export const ServiceMetrics = React.lazy( - () => import("modules/Metrics/ServiceMetricsDef"), -); -export const ServiceMap = React.lazy( - () => import("modules/Servicemap/ServiceMap"), -); -export const TraceDetail = React.lazy( - () => import("modules/Traces/TraceDetail"), -); -export const TraceGraph = React.lazy( - () => import("modules/Traces/TraceGraphDef"), -); -export const UsageExplorer = React.lazy( - () => import("modules/Usage/UsageExplorerDef"), -); -export const ServicesTable = React.lazy( - () => import("modules/Metrics/ServicesTableDef"), -); -export const Signup = React.lazy(() => import("modules/Auth/Signup")); -export const SettingsPage = React.lazy( - () => import("modules/Settings/settingsPage"), +export const ServiceMetricsPage = Loadable( + () => + import( + /* webpackChunkName: "ServiceMetricsPage" */ "modules/Metrics/ServiceMetricsDef" + ), ); -export const InstrumentationPage = React.lazy( - () => import("modules/add-instrumentation/instrumentationPage"), +export const ServiceMapPage = Loadable( + () => + import( + /* webpackChunkName: "ServiceMapPage" */ "modules/Servicemap/ServiceMap" + ), +); + +export const TraceDetailPage = Loadable( + () => + import( + /* webpackChunkName: "TraceDetailPage" */ "modules/Traces/TraceDetail" + ), +); + +export const TraceGraphPage = Loadable( + () => + import( + /* webpackChunkName: "TraceGraphPage" */ "modules/Traces/TraceGraphDef" + ), +); + +export const UsageExplorerPage = Loadable( + () => + import( + /* webpackChunkName: "UsageExplorerPage" */ "modules/Usage/UsageExplorerDef" + ), +); + +export const ServicesTablePage = Loadable( + () => + import( + /* webpackChunkName: "ServicesTablePage" */ "modules/Metrics/ServicesTableDef" + ), +); + +export const SignupPage = Loadable( + () => import(/* webpackChunkName: "SignupPage" */ "modules/Auth/Signup"), +); + +export const SettingsPage = Loadable( + () => + import( + /* webpackChunkName: "SettingsPage" */ "modules/Settings/settingsPage" + ), +); + +export const InstrumentationPage = Loadable( + () => + import( + /* webpackChunkName: "InstrumentationPage" */ "modules/add-instrumentation/instrumentationPage" + ), ); diff --git a/frontend/src/react-app-env.d.ts b/frontend/src/typings/react-app-env.d.ts similarity index 100% rename from frontend/src/react-app-env.d.ts rename to frontend/src/typings/react-app-env.d.ts diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js index 755ca2d326..e5fb2865b2 100644 --- a/frontend/webpack.config.js +++ b/frontend/webpack.config.js @@ -29,7 +29,9 @@ module.exports = { port: portFinderSync.getPort(3000), }, output: { - filename: "js/bundle.[chunkhash].min.js", + filename: ({ chunk: { name, hash } }) => { + return `js/${name}-${hash}.js`; + }, path: resolve(__dirname, "./build"), publicPath: "/", }, diff --git a/frontend/webpack.config.prod.js b/frontend/webpack.config.prod.js index 6c71b20fbd..91162a79da 100644 --- a/frontend/webpack.config.prod.js +++ b/frontend/webpack.config.prod.js @@ -11,7 +11,9 @@ module.exports = { devtool: "source-map", entry: resolve(__dirname, "./src/index.tsx"), output: { - filename: "js/bundle.[chunkhash].min.js", + filename: ({ chunk: { name, hash } }) => { + return `js/${name}-${hash}.js`; + }, path: resolve(__dirname, "./build"), publicPath: "/", },