Split the AccountSwitcher component on 2 independent implementations

Improve auth's ChooseAccount visual behavior
Rework the ComponentLoader component. Make it more stylable
This commit is contained in:
ErickSkrauch
2020-10-23 01:23:59 +03:00
parent c58816212d
commit 8075192472
33 changed files with 711 additions and 696 deletions

View File

@@ -1,7 +1,5 @@
import React from 'react';
import { withRouter } from 'react-router-dom';
import { FormattedMessage as Message } from 'react-intl';
import { Route, Link, Switch } from 'react-router-dom';
import { Route, Switch } from 'react-router-dom';
import { Helmet } from 'react-helmet-async';
import clsx from 'clsx';
@@ -10,16 +8,15 @@ import { resetAuth } from 'app/components/auth/actions';
import { ScrollIntoView } from 'app/components/ui/scroll';
import PrivateRoute from 'app/containers/PrivateRoute';
import AuthFlowRoute from 'app/containers/AuthFlowRoute';
import Userbar from 'app/components/userbar/Userbar';
import { PopupStack } from 'app/components/ui/popup';
import * as loader from 'app/services/loader';
import { getActiveAccount } from 'app/components/accounts/reducer';
import { User } from 'app/components/user';
import { Account } from 'app/components/accounts/reducer';
import { ComponentLoader } from 'app/components/ui/loader';
import Toolbar from './Toolbar';
import styles from './root.scss';
import siteName from './siteName.intl';
import PageNotFound from 'app/pages/404/PageNotFound';
@@ -35,9 +32,6 @@ class RootPage extends React.PureComponent<{
user: User;
isPopupActive: boolean;
onLogoClick: (event: React.MouseEvent<HTMLAnchorElement>) => void;
location: {
pathname: string;
};
}> {
componentDidMount() {
this.onPageUpdate();
@@ -52,9 +46,7 @@ class RootPage extends React.PureComponent<{
}
render() {
const { props } = this;
const { user, account, isPopupActive, onLogoClick } = this.props;
const isRegisterPage = props.location.pathname === '/register';
if (document && document.body) {
document.body.style.overflow = isPopupActive ? 'hidden' : '';
@@ -74,16 +66,7 @@ class RootPage extends React.PureComponent<{
[styles.isPopupActive]: isPopupActive,
})}
>
<div className={styles.header} data-testid="toolbar">
<div className={styles.headerContent}>
<Link to="/" className={styles.logo} onClick={onLogoClick} data-testid="home-page">
<Message {...siteName} />
</Link>
<div className={styles.userbar}>
<Userbar account={account} guestAction={isRegisterPage ? 'login' : 'register'} />
</div>
</div>
</div>
<Toolbar account={account} onLogoClick={onLogoClick} />
<div className={styles.body}>
<React.Suspense fallback={<ComponentLoader />}>
<Switch>
@@ -111,15 +94,13 @@ class RootPage extends React.PureComponent<{
}
}
export default withRouter(
connect(
(state) => ({
user: state.user,
account: getActiveAccount(state),
isPopupActive: state.popup.popups.length > 0,
}),
{
onLogoClick: resetAuth,
},
)(RootPage),
);
export default connect(
(state) => ({
user: state.user,
account: getActiveAccount(state),
isPopupActive: state.popup.popups.length > 0,
}),
{
onLogoClick: resetAuth,
},
)(RootPage);

View File

@@ -0,0 +1,68 @@
import React, { ComponentType, MouseEventHandler, ReactElement, useCallback } from 'react';
import { FormattedMessage as Message } from 'react-intl';
import { Link, useLocation } from 'react-router-dom';
import { useReduxDispatch, useReduxSelector } from 'app/functions';
import { authenticate, revoke } from 'app/components/accounts/actions';
import { Account } from 'app/components/accounts/reducer';
import buttons from 'app/components/ui/buttons.scss';
import LoggedInPanel from 'app/components/userbar/LoggedInPanel';
import * as loader from 'app/services/loader';
import siteName from './siteName.intl';
import styles from './root.scss';
interface Props {
account: Account | null;
onLogoClick?: MouseEventHandler<HTMLAnchorElement>;
}
const Toolbar: ComponentType<Props> = ({ onLogoClick, account }) => {
const dispatch = useReduxDispatch();
const location = useLocation();
const availableAccounts = useReduxSelector((state) => state.accounts.available);
const switchAccount = useCallback((account: Account) => {
loader.show();
return dispatch(authenticate(account)).finally(loader.hide);
}, []);
const removeAccount = useCallback((account: Account) => dispatch(revoke(account)), []);
let userBar: ReactElement;
if (account) {
userBar = (
<LoggedInPanel
activeAccount={account}
accounts={availableAccounts}
onSwitchAccount={switchAccount}
onRemoveAccount={removeAccount}
/>
);
} else if (location.pathname === '/register') {
userBar = (
<Link to="/login" className={buttons.blue}>
<Message key="login" defaultMessage="Sign in" />
</Link>
);
} else {
userBar = (
<Link to="/register" className={buttons.blue}>
<Message key="register" defaultMessage="Join" />
</Link>
);
}
return (
<div className={styles.toolbar} data-testid="toolbar">
<div className={styles.toolbarContent}>
<Link to="/" className={styles.siteName} onClick={onLogoClick} data-testid="home-page">
<Message {...siteName} />
</Link>
<div className={styles.userBar}>{userBar}</div>
</div>
</div>
);
};
export default Toolbar;

View File

@@ -1,7 +1,7 @@
@import '~app/components/ui/colors.scss';
@import '~app/components/ui/fonts.scss';
$userBarHeight: 50px;
$toolbarHeight: 50px;
.root {
height: 100%;
@@ -9,11 +9,11 @@ $userBarHeight: 50px;
.viewPort {
height: 100%;
transition: filter 0.4s 0.1s ease;
}
.isPopupActive {
filter: blur(5px);
transition: filter 0.4s 0.1s ease;
}
.wrapper {
@@ -21,21 +21,21 @@ $userBarHeight: 50px;
margin: 0 auto;
}
.header {
.toolbar {
position: fixed;
top: 0;
z-index: 100;
height: $userBarHeight;
height: $toolbarHeight;
width: 100%;
background: $green;
}
.headerContent {
.toolbarContent {
composes: wrapper;
position: relative;
}
.logo {
.siteName {
line-height: 50px;
padding: 0 20px;
display: inline-block;
@@ -44,7 +44,15 @@ $userBarHeight: 50px;
font-family: $font-family-title;
font-size: 33px;
color: #fff !important;
color: #fff!important; // TODO: why?
}
.userBar {
position: absolute;
right: 0;
left: 115px;
top: 0;
text-align: right;
}
.body {
@@ -55,12 +63,5 @@ $userBarHeight: 50px;
min-height: 100%;
box-sizing: border-box;
padding-top: $userBarHeight; // place for header
}
.userbar {
position: absolute;
right: 0;
left: 115px;
top: 0;
padding-top: $toolbarHeight; // space for the toolbar
}