mirror of
https://github.com/elyby/accounts-frontend.git
synced 2025-05-31 14:11:58 +05:30
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:
@@ -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);
|
||||
|
||||
68
packages/app/pages/root/Toolbar.tsx
Normal file
68
packages/app/pages/root/Toolbar.tsx
Normal 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;
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user