Skip to content

Commit

Permalink
kids-first#3356 make surethat no unwanted components are loaded when …
Browse files Browse the repository at this point in the history
…logging out
  • Loading branch information
evans-g-crsj committed Jul 1, 2021
1 parent 89725dc commit e8964ed
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 87 deletions.
32 changes: 23 additions & 9 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,14 @@ const App = compose(
// eslint-disable-next-line react/prop-types
const protectRoute = ({ loggedInUser, WrapperPage = Page, ...props }) => {
if (userIsRequiredToLogIn(loggedInUser)) {
return (
<SideImagePage
logo={logo}
sideImagePath={loginImage}
Component={LoginPage}
Footer={LoginFooter}
/>
);
return <Redirect to={ROUTES.login} />;
} else if (isJoinFormNeeded(loggedInUser)) {
return <Redirect to="/join" />;
// eslint-disable-next-line react/prop-types
} else if (!loggedInUser.acceptedTerms) {
return <Redirect to={ROUTES.termsConditions} />;
}

return <WrapperPage {...props} />;
};

Expand All @@ -90,6 +84,27 @@ const App = compose(
<Suspense fallback={<Spinner className={'spinner'} size={'large'} />}>
<Switch>
<Route path={ROUTES.authRedirect} exact component={AuthRedirect} />
<Route
path={ROUTES.login}
exact
render={() => {
if (
!userIsRequiredToLogIn(loggedInUser) &&
!isJoinFormNeeded(loggedInUser) &&
loggedInUser.acceptedTerms
) {
return <Redirect to="/" />;
}
return (
<SideImagePage
logo={logo}
sideImagePath={loginImage}
Component={LoginPage}
Footer={LoginFooter}
/>
);
}}
/>
<Route
path={ROUTES.termsConditions}
exact
Expand Down Expand Up @@ -134,7 +149,6 @@ const App = compose(
}
/>
<Route
/* temporary: this will be the new variant db page*/
path={ROUTES.variant}
exact
render={(props) =>
Expand Down
4 changes: 2 additions & 2 deletions src/chartkit/components/ChartLoadGate.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';
import { Spin } from 'antd';
import PropTypes from 'prop-types';
import { Spinner } from 'uikit/Spinner';

const ErrorText = () => <div>Error no data</div>;

const ChartLoadGate = ({ fetchedState: { isLoading, data }, Chart, Error = ErrorText }) =>
isLoading ? <Spinner size={'large'} /> : data ? <Chart data={data} /> : <Error />;
isLoading ? <Spin size={'large'} /> : data ? <Chart data={data} /> : <Error />;

ChartLoadGate.propTypes = {
fetchedState: PropTypes.object,
Expand Down
3 changes: 1 addition & 2 deletions src/common/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const ROUTES = {
variant: '/variant',
gen3Redirect: '/gen3_redirect',
join: '/join',
login: '/',
login: '/login',
redirected: '/redirected',
orcid: '/orcid',
participant: '/participant',
Expand All @@ -21,7 +21,6 @@ const ROUTES = {
variantDb: '/variant',
profile: '/profile',
termsConditions: '/termsConditions',
/* temporary while constructing the new variant page*/
};

export default ROUTES;
106 changes: 49 additions & 57 deletions src/components/Header/UserMenu.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,43 @@
import React from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';
import autobind from 'auto-bind-es5';
import { compose } from 'recompose';
import { Menu } from 'antd';

import HeaderMenu from './HeaderMenu';
import { injectState } from 'freactal';
import PropTypes from 'prop-types';
import { compose } from 'recompose';

import ROUTES from 'common/routes';
import { uiLogout } from 'components/LogoutButton';
import { withApi } from 'services/api';
import { injectState } from 'freactal';

import { effectsShape, historyShape } from 'shapes';
import Gravatar from 'uikit/Gravatar';
import { uiLogout } from 'components/LogoutButton';

import { effectsShape, historyShape } from 'shapes';
import HeaderMenu from './HeaderMenu';

import './Header.css';

const getUrlForUser = (user, hash = '') => `${ROUTES.user}/${user._id}${hash}`;

class UserMenu extends React.Component {
static propTypes = {
effects: effectsShape.isRequired,
history: historyShape.isRequired,
api: PropTypes.func.isRequired,
state: PropTypes.shape({
loggedInUser: PropTypes.object,
}).isRequired,
};
const menuItems = [
<Menu.Item key="profile">My Profile</Menu.Item>,
<Menu.Item key="settings">Settings</Menu.Item>,
<Menu.Divider key="divider 1" />,
<Menu.Item key="logout">Logout</Menu.Item>,
];

constructor(props) {
super(props);
autobind(this);
}
const UserMenu = (props) => {
const {
state: { loggedInUser },
effects: { setToken, setUser, clearIntegrationTokens, setIsLoadingUser },
history,
api,
} = props;

handleMenuClick({ key }) {
const {
history,
api,
effects: { setToken, setUser, clearIntegrationTokens },
state: { loggedInUser },
} = this.props;
// Menu is not displayed if no user is connected, or if we don't have the user profile yet
if (!loggedInUser) {
return null;
}

const handleMenuClick = ({ key }) => {
switch (key) {
case 'profile':
history.push(getUrlForUser(loggedInUser, '#aboutMe'));
Expand All @@ -51,39 +46,36 @@ class UserMenu extends React.Component {
history.push(getUrlForUser(loggedInUser, '#settings'));
break;
case 'logout':
uiLogout({ loggedInUser, setToken, setUser, clearIntegrationTokens, api, history });
uiLogout({
loggedInUser,
setToken,
setUser,
clearIntegrationTokens,
api,
history,
setIsLoadingUser,
});
break;
default:
console.warn(`Unhandled menu item with key "${key}"`);
}
}

render() {
const {
state: { loggedInUser },
} = this.props;

// Menu is not displayed if no user is connected, or if we don't have the user profile yet
if (!loggedInUser) {
return null;
}
};

const menuItems = [
<Menu.Item key="profile">My Profile</Menu.Item>,
<Menu.Item key="settings">Settings</Menu.Item>,
<Menu.Divider key="divider 1" />,
<Menu.Item key="logout">Logout</Menu.Item>,
];
return (
<HeaderMenu onClick={handleMenuClick} menuItems={menuItems}>
<Gravatar className="headerProfilePicture" email={loggedInUser.email || ''} size={39} />
<span className="userName">{loggedInUser.firstName}</span>
</HeaderMenu>
);
};

return (
<HeaderMenu onClick={this.handleMenuClick} menuItems={menuItems}>
<React.Fragment>
<Gravatar className="headerProfilePicture" email={loggedInUser.email || ''} size={39} />
<span className="userName">{loggedInUser.firstName}</span>
</React.Fragment>
</HeaderMenu>
);
}
}
UserMenu.propTypes = {
effects: effectsShape.isRequired,
history: historyShape.isRequired,
api: PropTypes.func.isRequired,
state: PropTypes.shape({
loggedInUser: PropTypes.object,
}).isRequired,
};

export default compose(injectState, withRouter, withApi)(UserMenu);
14 changes: 9 additions & 5 deletions src/components/Login/TermsConditions.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
/* eslint-disable react/prop-types */
import React, { FunctionComponent } from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';
import { Button } from 'antd';
import './termsConditions.css';
import SplashPage from '../SplashPage';
import { uiLogout } from '../LogoutButton';
// @ts-ignore
import { injectState } from 'freactal';
import { RouteComponentProps, withRouter } from 'react-router-dom';
import { withApi } from 'services/api';
// @ts-ignore
import { compose } from 'recompose';

import { withApi } from 'services/api';
import { Api } from 'store/apiTypes';
import { InjectStateProps } from 'store/freactalStateTypes';

import { uiLogout } from '../LogoutButton';
import SplashPage from '../SplashPage';

import TermsConditionsAcceptButton from './TermsConditionsAcceptButton';
import TermsConditionsBody from './TermsConditionsBody';

import './termsConditions.css';

type Props = InjectStateProps & Api & RouteComponentProps;

const TermsConditions: FunctionComponent<Props> = ({
Expand Down
15 changes: 11 additions & 4 deletions src/components/LogoutButton.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { logoutAll } from 'services/login';
import { updateProfile, getUserLoggedInProfile } from 'services/profiles';
import isEmpty from 'lodash/isEmpty';
import { removeForumBanner } from 'ForumBanner';
import isEmpty from 'lodash/isEmpty';

import ROUTES from 'common/routes';
import { logoutAll } from 'services/login';
import { getUserLoggedInProfile, updateProfile } from 'services/profiles';

export const uiLogout = async ({
loggedInUser,
Expand All @@ -10,7 +12,12 @@ export const uiLogout = async ({
clearIntegrationTokens,
api,
history,
setIsLoadingUser = null,
}) => {
if (setIsLoadingUser) {
setIsLoadingUser(true);
}

const isUserInMemory = loggedInUser && !isEmpty(loggedInUser);
if (isUserInMemory) {
const fetchedProfile = await getUserLoggedInProfile();
Expand All @@ -35,6 +42,6 @@ export const uiLogout = async ({
})
.then(() => {
removeForumBanner();
history.push('/');
history.push(ROUTES.login);
});
};
1 change: 1 addition & 0 deletions src/shapes/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export default PropTypes.shape({
setUser: PropTypes.func.isRequired,
setToken: PropTypes.func.isRequired,
clearIntegrationTokens: PropTypes.func.isRequired,
setIsLoadingUser: PropTypes.func,
});
18 changes: 10 additions & 8 deletions src/stateProviders/provideLoggedInUser.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { addHeaders } from '@kfarranger/components/dist';
import { mergeIntoState, provideState } from 'freactal';
import get from 'lodash/get';
import jwtDecode from 'jwt-decode';
import { addHeaders } from '@kfarranger/components/dist';
import { setToken } from 'services/ajax';
import { getAllFieldNamesPromise, updateProfile } from 'services/profiles';
import get from 'lodash/get';

import { EGO_JWT_KEY, SERVICES } from 'common/constants';
import { removeCookie, setCookie } from 'services/cookie';
import { handleJWT, isAdminToken, validateJWT } from 'components/Login/utils';
import { refreshToken } from 'services/login';
import ROUTES from 'common/routes';
import { handleJWT, isAdminToken, validateJWT } from 'components/Login/utils';
import { getUserGroups } from 'components/Login/utils';
import { setToken } from 'services/ajax';
import { trackUserSession } from 'services/analyticsTracking';
import { initializeApi } from 'services/api';
import { removeCookie, setCookie } from 'services/cookie';
import history from 'services/history';
import { getUserGroups } from 'components/Login/utils';
import { refreshToken } from 'services/login';
import { getAllFieldNamesPromise, updateProfile } from 'services/profiles';
import { hasUserRole } from 'utils';

const setEgoTokenCookie = (token) => {
Expand Down Expand Up @@ -190,5 +191,6 @@ export default provideState({
SERVICES.forEach((service) => localStorage.removeItem(`integration_${service}`));
return { ...state, integrationTokens: {} };
},
setIsLoadingUser: (isLoading) => (state) => ({ ...state, isLoadingUser: isLoading }),
},
});

0 comments on commit e8964ed

Please sign in to comment.