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'
import secoLogo from '../../../img/logos/seco-logo-48x50.png'
import { showLanguageButton } from '../../../configs/sampo/GeneralConfig'
paddingLeft: theme.spacing(1.5),
paddingRight: theme.spacing(1.5)
sectionDesktop: {
display: 'none',
sectionMobile: {
display: 'flex',
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'
},
secoLogo: {
marginLeft: theme.spacing(1),
[theme.breakpoints.down('md')]: {
display: 'none'
}
/**
* 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 classes = useStyles()
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>
{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
{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))}
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 */}
<Typography />
<AppBar position='absolute'>
<Toolbar className={classes.toolbar}>
<Button component={AdapterLink} to='/'>
<Typography className={classes.homeButtonText} variant='h6'>{intl.get('appTitle.short')}</Typography>
</Button>
{!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))}
<div className={classes.appBarDivider} />
<Button
className={classes.appBarButton}
component={AdapterNavLink}
to={`${props.rootUrl}/feedback`}
isActive={(match, location) => location.pathname.startsWith(`${props.rootUrl}/feedback`)}
activeClassName={classes.appBarButtonActive}
>
{intl.get('topBar.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}
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
{intl.get('topBar.instructions')}
</Button>
{showLanguageButton &&
<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}>
<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.
*/