AllenYuan

Untitled

Jun 1st, 2020
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.66 KB | None | 0 0
  1. import {
  2. IconButton,
  3. List,
  4. ListItem,
  5. ListItemText,
  6. Menu,
  7. MenuItem,
  8. SwipeableDrawer,
  9. } from '@material-ui/core';
  10. import {BugReport, Menu as MenuIcon, Settings} from '@material-ui/icons';
  11. import LogOutButton from 'material-ui/svg-icons/action/power-settings-new';
  12. import {Toolbar, ToolbarGroup} from 'material-ui/Toolbar';
  13. import PropTypes from 'prop-types';
  14. import React, {useCallback, useState, useRef} from 'react';
  15. import {useSelector} from 'react-redux';
  16. import {Link} from 'react-router-dom';
  17. import styled from 'styled-components';
  18.  
  19. import {GITHUB_REPO} from '../../config';
  20. import AccountWidget from '../AccountWidget';
  21. import AppLogo from '../App/AppLogo';
  22. import constants from '../constants';
  23.  
  24. const REPORT_BUG_PATH = `//github.com/${GITHUB_REPO}/issues`;
  25.  
  26. // create styling for each major subcomponent of Header
  27. const VerticalAlignToolbar = styled(ToolbarGroup)`
  28. display: flex;
  29. align-items: center;
  30. justify-content: center;
  31. `;
  32.  
  33. const VerticalAlignDiv = styled.div`
  34. display: flex;
  35. align-items: center;
  36. justify-content: center;
  37. `;
  38.  
  39. const TabContainer = styled.div`
  40. display: flex;
  41. flex-direction: column;
  42. font-weight: ${constants.fontWeightNormal};
  43. height: 100%;
  44. justify-content: center;
  45. margin: 0 12px;
  46. text-align: center;
  47. position: relative;
  48. `;
  49.  
  50. const AppLogoWrapper = styled.div`
  51. // for small screens, remove the applogo from the navigation
  52. @media screen and (max-width: 800px) {
  53. display: none;
  54. }
  55. `;
  56.  
  57. const DropdownMenu = styled(Menu)`
  58. & .MuiMenu-paper {
  59. background: ${constants.primarySurfaceColor};
  60. }
  61. `;
  62.  
  63. const DropdownMenuItem = styled(MenuItem)`
  64. color: ${constants.primaryTextColor} !important;
  65. padding-bottom: 12px !important;
  66. padding-top: 12px !important;
  67. `;
  68.  
  69. const ToolbarHeader = styled(Toolbar)`
  70. backdrop-filter: blur(16px);
  71. background-color: ${constants.defaultPrimaryColorSolid} !important;
  72. height: 56px;
  73. left: 0;
  74. padding: 8px 16px !important;
  75. position: fixed;
  76. top: 0;
  77. width: 100%;
  78. z-index: 100%;
  79.  
  80. & a {
  81. color: ${constants.primaryTextColor};
  82.  
  83. &:hover {
  84. color: ${constants.primaryTextColor};
  85. opacity: 0.6;
  86. }
  87. }
  88. `;
  89.  
  90. const MenuContent = styled.div`
  91. background: ${constants.primarySurfaceColor};
  92. max-width: 300px;
  93. height: 100%;
  94. overflow: auto;
  95. min-width: 220px;
  96. `;
  97.  
  98. const MenuLogoWrapper = styled.div`
  99. align-items: center;
  100. display: flex;
  101. justify-content: center;
  102. padding: 24px 0;
  103. `;
  104.  
  105. const DrawerLink = styled(Link)`
  106. color: ${constants.textColorPrimary};
  107. `;
  108.  
  109. const LinkGroup = ({navbarPages}) => (
  110. <VerticalAlignToolbar>
  111. {navbarPages.map((page) => (
  112. <TabContainer key={page.key}>
  113. <Link to={page.to}>{page.label}</Link>
  114. {Boolean(page.feature) && (
  115. <div
  116. style={{
  117. position: 'absolute',
  118. textTransform: 'uppercase',
  119. fontSize: '10px',
  120. top: '-10px',
  121. right: '0',
  122. color: 'lightblue',
  123. }}
  124. >
  125. {page.feature}
  126. </div>
  127. )}
  128. </TabContainer>
  129. ))}
  130. </VerticalAlignToolbar>
  131. );
  132.  
  133. LinkGroup.propTypes = {
  134. navbarPages: PropTypes.shape([{}]),
  135. };
  136.  
  137. const SettingsGroup = ({ children }) => {
  138. const [anchorEl, setAnchorEl] = useState(null); // setanchorel hook
  139. const buttonRef = useRef(); // ref for anchorEl
  140.  
  141. // init the handleclose callback: clear setanchorel
  142. const handleClose = useCallback(() => {
  143. setAnchorEl(undefined);
  144. }, [setAnchorEl]);
  145.  
  146. return (
  147. <>
  148. <IconButton
  149. ref={buttonRef}
  150. color="inherit"
  151. onClick={(e) => setAnchorEl(e.currentTarget)}
  152. >
  153. <Settings />
  154. </IconButton>
  155. {buttonRef.current && (
  156. <DropdownMenu
  157. anchorEl={buttonRef.current}
  158. open={Boolean(anchorEl)}
  159. onClose={handleClose}
  160. PaperProps={{ style: { maxHeight: 600 }}}
  161. >
  162. {children}
  163. </DropdownMenu>
  164. )}
  165. </>
  166. );
  167. };
  168.  
  169. const MenuButtonWrapper = styled.div`
  170. margin-right: 12px;
  171. `;
  172.  
  173. const LogoGroup = ({ onMenuClick }) => (
  174. <div style={{ marginRight: 16 }}>
  175. <VerticalAlignToolbar>
  176. <MenuButtonWrapper>
  177. <IconButton edge="start" color="inherit" onClick={onMenuClick}>
  178. <MenuIcon />
  179. </IconButton>
  180. </MenuButtonWrapper>
  181. <AppLogoWrapper>
  182. <AppLogo />
  183. </AppLogoWrapper>
  184. </VerticalAlignToolbar>
  185. </div>
  186. );
  187.  
  188. LogoGroup.propTypes = {
  189. onMenuClick: PropTypes.func,
  190. };
  191.  
  192. const AccountGroup = () => (
  193. <VerticalAlignToolbar>
  194. <AccountWidget />
  195. </VerticalAlignToolbar>
  196. );
  197.  
  198. const ReportBug = ({ strings }) => (
  199. <DropdownMenuItem
  200. component="a"
  201. href={REPORT_BUG_PATH}
  202. target="_blank" // open in new tab
  203. rel="noopener noreferrer" // security for opening in new tab
  204. >
  205. <BugReport style={{ marginRight: 32, width: 24, height: 24 }} />
  206. {strings.app_report_bug}
  207. </DropdownMenuItem>
  208. );
  209.  
  210. ReportBug.propTypes = {
  211. strings: PropTypes.shape({}),
  212. };
  213.  
  214. const LogOut = ({ strings }) => (
  215. <DropdownMenuItem
  216. component="a"
  217. href={`${process.env.REACT_APP_API_HOST}/logout`}
  218. rel="noopener noreferrer"
  219. >
  220. <LogOutButton style={{ marginRight: 32, width: 24, height: 24 }} />
  221. {strings.app_logout}
  222. </DropdownMenuItem>
  223. );
  224.  
  225. LogOut.propTypes = {
  226. strings: PropTypes.shape({}),
  227. };
  228.  
  229. const Header = ({ location, disableSearch }) => {
  230. // set hooks
  231. const [menuIsOpen, setMenuState] = useState(false);
  232.  
  233. // state selectors
  234. const small = useSelector((state) => state.browser.greaterThan.small);
  235. const user = useSelector((state) => {
  236. console.log('header state', state);
  237. return state.app.metadata.data.user;
  238. });
  239. const strings = useSelector((state) => state.app.strings);
  240.  
  241. // data encoding navbar
  242. const navbarPages = [
  243. {
  244. key: 'header_matches',
  245. to: '/matches',
  246. label: strings.header_matches,
  247. },
  248. {
  249. key: 'header_heroes',
  250. to: '/heroes',
  251. label: strings.header_heroes,
  252. },
  253. {
  254. key: 'header_explorer',
  255. to: '/explorer',
  256. label: strings.header_explorer,
  257. },
  258. {
  259. key: 'header_combos',
  260. to: '/combos',
  261. label: strings.combos,
  262. feature: '2020 BP',
  263. },
  264. {
  265. key: 'header_api',
  266. to: '/api-keys',
  267. label: strings.header_api,
  268. },
  269. ];
  270.  
  271. // add some pages revealed by drawer
  272. const drawerPages = [
  273. ...navbarPages,
  274. {
  275. key: 'header_distributions',
  276. to: '/distributions',
  277. label: strings.header_distributions,
  278. },
  279. {
  280. key: 'header_records',
  281. to: '/records',
  282. label: strings.header_records,
  283. },
  284. {
  285. key: 'header_meta',
  286. to: '/meta',
  287. label: strings.header_meta,
  288. },
  289. {
  290. key: 'header_scenarios',
  291. to: '/scenarios',
  292. label: strings.header_scenarios,
  293. },
  294. ];
  295.  
  296. return (
  297. <>
  298. <ToolbarHeader>
  299. {/* logo/settings groups */}
  300. <VerticalAlignDiv>
  301. <LogoGroup onMenuClick={() => setMenuState(true)} />
  302. {small && <LinkGroup navbarPages={navbarPages} />}
  303. </VerticalAlignDiv>
  304. <VerticalAlignDiv style={{ marginLeft: '16px' }}>
  305. {small && <AccountGroup />}
  306. <SettingsGroup>
  307. <ReportBug strings={strings} />
  308. {user ? <LogOut strings={strings} /> : null}
  309. </SettingsGroup>
  310. </VerticalAlignDiv>
  311. {/* drawer */}
  312. <SwipeableDrawer
  313. onOpen={() => setMenuState(true)}
  314. onClose = {() => setMenuState(false)}
  315. open = {menuIsOpen}
  316. >
  317. <MenuContent>
  318. <MenuLogoWrapper>
  319. <div>
  320. <AppLogo onClick={() => setMenuState(false)} />
  321. </div>
  322. </MenuLogoWrapper>
  323. {/* render the drawer links */}
  324. <List>
  325. {drawerPages.map((page) => (
  326. <DrawerLink key={`drawer__${page.to}`} to={page.to}>
  327. <ListItem
  328. button
  329. key={`drawer__${page.to}`}
  330. onClick={() => setMenuState(false)}
  331. >
  332. <ListItemText primary={page.label} />
  333. </ListItem>
  334. </DrawerLink>
  335. ))}
  336. </List>
  337. {/* render user links/login links */}
  338. <List>
  339. {user ? (
  340. <>
  341. <DrawerLink to={`/players/${user.account_id}`}>
  342. <ListItem button onClick={() => setMenuState(false)}>
  343. <ListItemText primary={strings.app_my_profile} />
  344. </ListItem>
  345. </DrawerLink>
  346. <DrawerLink
  347. as="a"
  348. href={`${process.env.REACT_APP_API_HOST}/logout`}
  349. >
  350. <ListItem button onClick={() => setMenuState(false)}>
  351. <ListItemText primary={strings.app_logout} />
  352. </ListItem>
  353. </DrawerLink>
  354. </>
  355. ) : (
  356. <>
  357. <DrawerLink
  358. as="a"
  359. href={`${process.env.REACT_APP_API_HOST}/login`}
  360. >
  361. <ListItem button onClick={() => setMenuState(false)}>
  362. <ListItemText primary={strings.app_login} />
  363. </ListItem>
  364. </DrawerLink>
  365. </>
  366. )}
  367. </List>
  368. </MenuContent>
  369. </SwipeableDrawer>
  370. </ToolbarHeader>
  371. </>
  372. );
  373. };
  374.  
  375. export default Header;
Add Comment
Please, Sign In to add comment