Newer
Older
import React from 'react'
import PropTypes from 'prop-types'
import intl from 'react-intl-universal'
import AppBar from '@material-ui/core/AppBar'
import Toolbar from '@material-ui/core/Toolbar'
import IconButton from '@material-ui/core/IconButton'
import Typography from '@material-ui/core/Typography'
import MenuItem from '@material-ui/core/MenuItem'
import Menu from '@material-ui/core/Menu'
import MoreIcon from '@material-ui/icons/MoreVert'
import Button from '@material-ui/core/Button'
import { Link, NavLink } from 'react-router-dom'
import TopBarSearchField from '../../main_layout/TopBarSearchField'
import TopBarInfoButton from '../../main_layout/TopBarInfoButton'
import TopBarLanguageButton from '../../main_layout/TopBarLanguageButton'
import Divider from '@material-ui/core/Divider'
import { has } from 'lodash'
topBarToolbar: props => ({
minHeight: props.layoutConfig.topBar.reducedHeight,
[theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: {
minHeight: props.layoutConfig.topBar.defaultHeight
},
paddingLeft: theme.spacing(1.5),
paddingRight: theme.spacing(1.5)
display: 'none',
[theme.breakpoints.up(props.layoutConfig.topBar.mobileMenuBreakpoint)]: {
display: 'flex',
[theme.breakpoints.up(props.layoutConfig.topBar.mobileMenuBreakpoint)]: {
homeButtonText: {
whiteSpace: 'nowrap',
[theme.breakpoints.down('sm')]: {
fontSize: '1rem'
}
},
appBarButton: {
color: 'white !important',
border: `1px solid ${theme.palette.primary.main}`
appBarButtonActive: {
border: '1px solid white'
},
appBarDivider: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
borderLeft: '2px solid white'
[theme.breakpoints.down(props.layoutConfig.topBar.mobileMenuBreakpoint)]: {
/**
* Responsive app bar with a search field, perspective links, info links and a language
* selector. Based on Material-UI's App Bar component.
*/
const TopBar = props => {
const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React.useState(null)
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl)
const { perspectives, currentLocale, availableLocales, rootUrl } = props
const handleMobileMenuOpen = event => setMobileMoreAnchorEl(event.currentTarget)
const handleMobileMenuClose = () => setMobileMoreAnchorEl(null)
const clientFSMode = props.location.pathname.indexOf('clientFS') !== -1
// https://material-ui.com/components/buttons/#third-party-routing-library
const AdapterLink = React.forwardRef((props, ref) => <Link innerRef={ref} {...props} />)
const AdapterNavLink = React.forwardRef((props, ref) => <NavLink innerRef={ref} {...props} />)
const searchMode = perspective.id.startsWith('clientFS') ? 'federated-search' : 'faceted-search'
key={perspective.id}
href={perspective.externalUrl}
target='_blank'
rel='noopener noreferrer'
>
<MenuItem>
{perspective.label
? perspective.label.toUpperCase()
: intl.get(`perspectives.${perspective.id}.label`).toUpperCase()}
component={AdapterLink}
to={`${props.rootUrl}/${perspective.id}/${searchMode}`}
{intl.get(`perspectives.${perspective.id}.label`).toUpperCase()}
const searchMode = perspective.id.startsWith('clientFS') ? 'federated-search' : 'faceted-search'
key={perspective.id}
href={perspective.externalUrl}
target='_blank'
rel='noopener noreferrer'
>
<Button
{perspective.label
? perspective.label
: intl.get(`perspectives.${perspective.id}.label`).toUpperCase()}
className={classes.appBarButton}
component={AdapterNavLink}
to={`${props.rootUrl}/${perspective.id}/${searchMode}`}
isActive={(match, location) => location.pathname.startsWith(`${props.rootUrl}/${perspective.id}`)}
activeClassName={classes.appBarButtonActive}
{intl.get(`perspectives.${perspective.id}.label`).toUpperCase()}
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
open={isMobileMenuOpen}
onClose={handleMobileMenuClose}
{perspectives.map(perspective => perspective.isHidden ? null : renderMobileMenuItem(perspective))}
label: intl.get('topBar.feedback')
})}
{/* <MenuItem
component={AdapterLink}
to={`${props.rootUrl}/feedback`}
component={AdapterLink}
to={`${props.rootUrl}/about`}
{intl.get('topBar.info.aboutThePortal').toUpperCase()}
component={AdapterLink}
to={`${props.rootUrl}/instructions`}
return (
<div className={classes.root}>
{/* Add an empty Typography element to ensure that that the MuiTypography class is loaded for
any lower level components that use MuiTypography class only in translation files */}
<AppBar position='static'>
<Toolbar className={classes.topBarToolbar}>
<Typography className={classes.homeButtonText} variant='h6'>
{props.xsScreen ? intl.get('appTitle.mobile') : intl.get('appTitle.short')}
</Typography>
{!clientFSMode &&
<TopBarSearchField
fetchFullTextResults={props.fetchFullTextResults}
clearResults={props.clearResults}
xsScreen={props.xsScreen}
rootUrl={rootUrl}
/>}
<div className={classes.grow} />
<div className={classes.sectionDesktop}>
{perspectives.map((perspective, index) => perspective.isHidden ? null : renderDesktopTopMenuItem(perspective, index))}
{renderDesktopTopMenuItem({
id: 'feedback',
<TopBarInfoButton rootUrl={props.rootUrl} />
<Button
className={classes.appBarButton}
component={AdapterNavLink}
to={`${props.rootUrl}/instructions`}
isActive={(match, location) => location.pathname.startsWith(`${props.rootUrl}/instructions`)}
activeClassName={classes.appBarButtonActive}
<TopBarLanguageButton
currentLocale={currentLocale}
availableLocales={availableLocales}
loadLocales={props.loadLocales}
location={props.location}
/>}
</div>
<a
className={classes.secoLogo}
href='https://seco.cs.aalto.fi'
target='_blank'
rel='noopener noreferrer'
>
<Button><img src={secoLogo} /></Button>
</a>
<div className={classes.sectionMobile}>
<TopBarLanguageButton
currentLocale={currentLocale}
availableLocales={availableLocales}
loadLocales={props.loadLocales}
location={props.location}
/>}
<IconButton aria-haspopup='true' onClick={handleMobileMenuOpen} color='inherit'>
<MoreIcon />
</IconButton>
</div>
</Toolbar>
</AppBar>
{renderMobileMenu(perspectives)}
</div>
)
/**
* Redux action for full text search results using the search field.
*/
fetchFullTextResults: PropTypes.func.isRequired,
/**
* Redux action for clearing the full text results.
*/
loadLocales: PropTypes.func.isRequired,
currentLocale: PropTypes.string.isRequired,
/**
* Available locales as an array of objects with two-letter codes as keys.
*/
availableLocales: PropTypes.array.isRequired,
/**
* Perspective config as an array of objects.
*/
perspectives: PropTypes.array.isRequired,
/**
* Flag for checking if the screen is extra small.
*/
/**
* React Router's location object. The perspective links are highlighted based on this.
*/
rootUrl: PropTypes.string.isRequired,
layoutConfig: PropTypes.object.isRequired