diff --git a/package.json b/package.json index 1530589e..bfcc4932 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "@patternfly/react-icons": "^3.10.10", "@patternfly/react-styles": "^3.4.6", "react-document-title": "^2.0.3", - "react-router-dom": "^5.0.1" + "react-router-dom": "^5.0.1", + "react-router-last-location": "^2.0.1" } } diff --git a/src/app/AppLayout/AppLayout.tsx b/src/app/AppLayout/AppLayout.tsx index 8b9c9a06..73203fac 100644 --- a/src/app/AppLayout/AppLayout.tsx +++ b/src/app/AppLayout/AppLayout.tsx @@ -53,7 +53,7 @@ const AppLayout: React.FunctionComponent = ({children}) => { {routes.map((route, idx) => { return ( - {route.label} + {route.label} ); })} diff --git a/src/app/DynamicImport.tsx b/src/app/DynamicImport.tsx index ae3a5bb8..b0bd1588 100644 --- a/src/app/DynamicImport.tsx +++ b/src/app/DynamicImport.tsx @@ -4,12 +4,21 @@ import { accessibleRouteChangeHandler } from '@app/utils/utils'; interface IDynamicImport { load: () => Promise; children: any; + focusContentAfterMount: boolean; } class DynamicImport extends React.Component { public state = { component: null }; + private routeFocusTimer: number; + constructor(props: IDynamicImport) { + super(props); + this.routeFocusTimer = 0; + } + public componentWillUnmount() { + window.clearTimeout(this.routeFocusTimer); + } public componentDidMount() { this.props.load().then(component => { if (component) { @@ -18,9 +27,11 @@ class DynamicImport extends React.Component { }); } }) - .then(() => { - accessibleRouteChangeHandler(); - }); + .then(() => { + if (this.props.focusContentAfterMount) { + this.routeFocusTimer = accessibleRouteChangeHandler(); + } + }); } public render() { return this.props.children(this.state.component); diff --git a/src/app/NotFound/NotFound.tsx b/src/app/NotFound/NotFound.tsx index e37fe501..d5c2d7b5 100644 --- a/src/app/NotFound/NotFound.tsx +++ b/src/app/NotFound/NotFound.tsx @@ -6,7 +6,7 @@ const NotFound: React.FunctionComponent = () => { return (
- Back to Dashboard + Take me home
); } diff --git a/src/app/routes.tsx b/src/app/routes.tsx index a2059257..b456985d 100644 --- a/src/app/routes.tsx +++ b/src/app/routes.tsx @@ -1,33 +1,35 @@ import * as React from 'react'; -import { Redirect, Route, RouteComponentProps, Switch } from 'react-router-dom'; +import { Route, RouteComponentProps, Switch } from 'react-router-dom'; import { Alert, PageSection } from '@patternfly/react-core'; import { DynamicImport } from '@app/DynamicImport'; import { accessibleRouteChangeHandler } from '@app/utils/utils'; import { Dashboard } from '@app/Dashboard/Dashboard'; import { NotFound } from '@app/NotFound/NotFound'; import DocumentTitle from 'react-document-title'; - +import { LastLocationProvider, useLastLocation } from 'react-router-last-location'; +let routeFocusTimer: number; const getSupportModuleAsync = () => { return () => import(/* webpackChunkName: 'support' */ '@app/Support/Support'); }; const Support = (routeProps: RouteComponentProps) => { + const lastNavigation = useLastLocation(); return ( - + {(Component: any) => { - let loadedComponent: any; - if (Component === null) { - loadedComponent = ( - -
- -
-
- ); - } else { - loadedComponent = ; - } - return loadedComponent + let loadedComponent: any; + if (Component === null) { + loadedComponent = ( + +
+ +
+
+ ); + } else { + loadedComponent = ; + } + return loadedComponent }}
); @@ -39,6 +41,8 @@ const RouteWithTitleUpdates = ({ title, ...rest }) => { + const lastNavigation = useLastLocation(); + function routeWithTitle(routeProps: RouteComponentProps) { return ( @@ -48,9 +52,12 @@ const RouteWithTitleUpdates = ({ } React.useEffect(() => { - if (!isAsync) { - accessibleRouteChangeHandler() + if (!isAsync && lastNavigation !== null) { + routeFocusTimer = accessibleRouteChangeHandler() } + return () => { + clearTimeout(routeFocusTimer); + }; }, []); return ( @@ -74,7 +81,7 @@ const routes: IAppRoute[] = [ exact: true, icon: null, label: 'Dashboard', - path: '/dashboard', + path: '/', title: 'Main Dashboard Title' }, { @@ -89,19 +96,20 @@ const routes: IAppRoute[] = [ ]; const AppRoutes = () => ( - - {routes.map(({ path, exact, component, title, isAsync }, idx) => ( - - ))} - - - + + + {routes.map(({ path, exact, component, title, isAsync }, idx) => ( + + ))} + + + ); export { AppRoutes, routes }; diff --git a/src/app/utils/utils.ts b/src/app/utils/utils.ts index f596d003..78c131fb 100644 --- a/src/app/utils/utils.ts +++ b/src/app/utils/utils.ts @@ -1,6 +1,8 @@ export function accessibleRouteChangeHandler() { - const mainContainer = document.getElementById('primary-app-container'); - if (mainContainer) { - mainContainer.focus(); - } + return window.setTimeout(() => { + const mainContainer = document.getElementById('primary-app-container'); + if (mainContainer) { + mainContainer.focus(); + } + }, 50); } diff --git a/webpack.common.js b/webpack.common.js index 7154927d..5be16079 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -36,6 +36,8 @@ module.exports = { path.resolve(__dirname, 'node_modules/patternfly/dist/fonts'), path.resolve(__dirname, 'node_modules/@patternfly/react-core/dist/styles/assets/fonts'), path.resolve(__dirname, 'node_modules/@patternfly/react-core/dist/styles/assets/pficon'), + path.resolve(__dirname, 'node_modules/@patternfly/patternfly/assets/fonts'), + path.resolve(__dirname, 'node_modules/@patternfly/patternfly/assets/pficon') ], use: { loader: 'file-loader', diff --git a/yarn.lock b/yarn.lock index ad8f1485..5d737154 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7183,6 +7183,11 @@ react-router-dom@^5.0.1: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" +react-router-last-location@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/react-router-last-location/-/react-router-last-location-2.0.1.tgz#54d625876dd1448594fa1114aa02e7e21db12970" + integrity sha512-3FbFIWwUr2qN28vN9DNdFp6RhUH/yif6ILVff1zT+hLdyGmlNPh3GuPhveb7bHQLgB744QW8L0qtWjX58ESuZQ== + react-router@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.0.1.tgz#04ee77df1d1ab6cb8939f9f01ad5702dbadb8b0f"