From 83185436351574900c1bdc5107621a3ecc966155 Mon Sep 17 00:00:00 2001 From: esikkala <esko.ikkala@aalto.fi> Date: Tue, 18 Jan 2022 08:58:14 +0200 Subject: [PATCH] Adapt main page and top bar for MUI v5 --- src/client/components/App.js | 41 ++- src/client/components/main_layout/TextPage.js | 95 +++--- src/client/components/main_layout/TopBar.js | 275 +++++++++--------- .../main_layout/TopBarSearchField.js | 108 ++++--- .../components/perspectives/sampo/Footer.js | 82 +++--- .../components/perspectives/sampo/Main.js | 19 +- src/client/containers/SemanticPortal.js | 51 ++-- src/client/img/logos/logo.png | Bin 0 -> 3694 bytes src/configs/portalConfig.json | 5 +- 9 files changed, 351 insertions(+), 325 deletions(-) create mode 100644 src/client/img/logos/logo.png diff --git a/src/client/components/App.js b/src/client/components/App.js index cf785afd..a4de9f0f 100644 --- a/src/client/components/App.js +++ b/src/client/components/App.js @@ -1,12 +1,22 @@ import React from 'react' -import { ThemeProvider, StyledEngineProvider, createTheme } from '@mui/material/styles' +import { ThemeProvider, createTheme } from '@mui/material/styles' import AdapterMoment from '@mui/lab/AdapterDateFns' import LocalizationProvider from '@mui/lab/LocalizationProvider' // import 'moment/locale/fi' import SemanticPortal from '../containers/SemanticPortal' import portalConfig from '../../configs/portalConfig.json' -const { colorPalette } = portalConfig.layoutConfig +const { colorPalette, reducedHeightBreakpoint, hundredPercentHeightBreakPoint, topBar } = portalConfig.layoutConfig + +const muiDefaultBreakpoints = { + xs: 0, + sm: 600, + md: 900, + lg: 1200, + xl: 1536 +} + +const defaultTheme = createTheme() const theme = createTheme({ palette: { @@ -17,7 +27,26 @@ const theme = createTheme({ main: colorPalette.secondary.main } }, + breakpoints: { + values: { + ...muiDefaultBreakpoints, + reducedHeight: muiDefaultBreakpoints[reducedHeightBreakpoint], + hundredPercentHeight: muiDefaultBreakpoints[hundredPercentHeightBreakPoint] + } + }, components: { + MuiToolbar: { + styleOverrides: { + regular: { + [defaultTheme.breakpoints.down(reducedHeightBreakpoint)]: { + minHeight: topBar.reducedHeight + }, + [defaultTheme.breakpoints.up(reducedHeightBreakpoint)]: { + minHeight: topBar.defaultHeight + } + } + } + }, MuiTooltip: { tooltip: { fontSize: '1 rem' @@ -64,11 +93,9 @@ const theme = createTheme({ const App = () => ( <LocalizationProvider dateAdapter={AdapterMoment}> - <StyledEngineProvider injectFirst> - <ThemeProvider theme={theme}> - <SemanticPortal /> - </ThemeProvider> - </StyledEngineProvider> + <ThemeProvider theme={theme}> + <SemanticPortal /> + </ThemeProvider> </LocalizationProvider> ) diff --git a/src/client/components/main_layout/TextPage.js b/src/client/components/main_layout/TextPage.js index 5f7f70cd..c7b99249 100644 --- a/src/client/components/main_layout/TextPage.js +++ b/src/client/components/main_layout/TextPage.js @@ -1,50 +1,77 @@ import React from 'react' import PropTypes from 'prop-types' -import makeStyles from '@mui/styles/makeStyles'; import Paper from '@mui/material/Paper' - -const useStyles = makeStyles(theme => ({ - root: { - width: '100%', - height: '100%', - display: 'flex', - justifyContent: 'center' - }, - layout: { - width: 'auto', - padding: theme.spacing(3), - marginLeft: theme.spacing(3), - marginRight: theme.spacing(3), - [theme.breakpoints.down('md')]: { - padding: theme.spacing(1.5), - marginLeft: 0, - marginRight: 0 - }, - [theme.breakpoints.up(1100 + theme.spacing(6))]: { - width: 1100, - marginLeft: 'auto', - marginRight: 'auto' - }, - overflow: 'auto' - } -})) +import Box from '@mui/material/Box' +import { getSpacing } from '../../helpers/helpers' /** * A component for creating a responsive page with static content. */ const TextPage = props => { - const classes = useStyles() - + const { layoutConfig } = props return ( - <div className={classes.root}> - <Paper className={classes.layout}> - {props.children} - </Paper> - </div> + <Box + sx={theme => ({ + margin: theme.spacing(0.5), + width: `calc(100% - ${getSpacing(theme, 1)}px)`, + [theme.breakpoints.up(layoutConfig.hundredPercentHeightBreakPoint)]: { + height: `calc(100% - ${layoutConfig.topBar.reducedHeight + getSpacing(theme, 1)}px)` + }, + [theme.breakpoints.up(layoutConfig.reducedHeightBreakpoint)]: { + height: `calc(100% - ${layoutConfig.topBar.defaultHeight + getSpacing(theme, 1)}px)` + } + })} + > + <Box + sx={{ + width: '100%', + height: '100%', + display: 'flex', + justifyContent: 'center' + }} + > + <Paper + sx={theme => ({ + width: 'auto', + padding: theme.spacing(3), + marginLeft: theme.spacing(3), + marginRight: theme.spacing(3), + [theme.breakpoints.down('md')]: { + padding: theme.spacing(1.5), + marginLeft: 0, + marginRight: 0 + }, + [theme.breakpoints.up(1100 + getSpacing(theme, 6))]: { + width: 1100, + marginLeft: 'auto', + marginRight: 'auto' + }, + overflow: 'auto', + '& h1': { + ...theme.typography.h2, + marginTop: 0, + marginBottom: theme.spacing(1) + }, + '& h2': { + ...theme.typography.h4 + }, + '& h3': { + ...theme.typography.h6 + }, + '& p, li': { + ...theme.typography.body1 + } + })} + > + {props.children} + </Paper> + </Box> + </Box> ) } TextPage.propTypes = { + layoutConfig: PropTypes.object.isRequired, /** * The content of the page. */ diff --git a/src/client/components/main_layout/TopBar.js b/src/client/components/main_layout/TopBar.js index 312f6d57..862f9add 100644 --- a/src/client/components/main_layout/TopBar.js +++ b/src/client/components/main_layout/TopBar.js @@ -7,9 +7,10 @@ import IconButton from '@mui/material/IconButton' import Typography from '@mui/material/Typography' import MenuItem from '@mui/material/MenuItem' import Menu from '@mui/material/Menu' -import makeStyles from '@mui/styles/makeStyles' import MoreIcon from '@mui/icons-material/MoreVert' import Button from '@mui/material/Button' +import Box from '@mui/material/Box' +import { useTheme } from '@mui/material/styles' import { Link, NavLink } from 'react-router-dom' import TopBarSearchField from './TopBarSearchField' import TopBarInfoButton from './TopBarInfoButton' @@ -18,113 +19,22 @@ import Divider from '@mui/material/Divider' import { has } from 'lodash' import secoLogo from '../../img/logos/seco-logo-48x50.png' -const useStyles = makeStyles(theme => ({ - grow: { - flexGrow: 1 - }, - 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) - }), - sectionDesktop: props => ({ - display: 'none', - [theme.breakpoints.up(props.layoutConfig.topBar.mobileMenuBreakpoint)]: { - display: 'flex' - } - }), - link: { - textDecoration: 'none' - }, - sectionMobile: props => ({ - display: 'flex', - [theme.breakpoints.up(props.layoutConfig.topBar.mobileMenuBreakpoint)]: { - display: 'none' - } - }), - appBarButton: { - whiteSpace: 'nowrap', - 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: props => ({ - marginLeft: theme.spacing(1), - [theme.breakpoints.down(props.layoutConfig.topBar.mobileMenuBreakpoint)]: { - display: 'none' - } - }), - secoLogoImage: props => ({ - height: 32, - [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { - height: 50 - } - }), - mainLogo: props => ({ - height: props.layoutConfig.topBar.logoImageReducedHeight || 23, - [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { - height: props.layoutConfig.topBar.logoImageHeight || 40 - }, - marginRight: theme.spacing(1) - }), - mainLogoButtonRoot: { - paddingLeft: 0, - [theme.breakpoints.down('sm')]: { - minWidth: 48 - } - }, - mainLogoButtonLabel: { - justifyContent: 'left' - }, - mainLogoTypography: props => ({ - // set color and background explicitly to keep Google Lighthouse happy - color: '#fff', - background: theme.palette.primary.main, - whiteSpace: 'nowrap', - textTransform: props.layoutConfig.topBar.logoTextTransform, - [theme.breakpoints.down('md')]: { - fontSize: '1.5rem' - }, - ...(props.layoutConfig.topBar.hideLogoTextOnMobile && { - [theme.breakpoints.down('sm')]: { - display: 'none' - } - }) - }), - logoSecondary: props => ({ - height: 26, - [theme.breakpoints.up('sm')]: { - height: 32 - }, - [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { - height: 52 - } - }), - mobileMenuButton: { - padding: 12 - } -})) - /** * 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 theme = useTheme() + // custom style function for utilizing React Router's isActive prop + const createAppBarButtonStyle = isActive => ({ + whiteSpace: 'nowrap', + color: 'white !important', + border: isActive ? '1px solid white' : `1px solid ${theme.palette.primary.main}` + }) const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React.useState(null) const isMobileMenuOpen = Boolean(mobileMoreAnchorEl) const { perspectives, currentLocale, availableLocales, rootUrl, layoutConfig } = props const { topBar } = layoutConfig - const classes = useStyles(props) const handleMobileMenuOpen = event => setMobileMoreAnchorEl(event.currentTarget) const handleMobileMenuClose = () => setMobileMoreAnchorEl(null) const federatedSearchMode = props.location.pathname.indexOf('federated-search') !== -1 @@ -133,9 +43,11 @@ const TopBar = props => { showSearchField = layoutConfig.topBar.showSearchField } - // 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} />) + // https://mui.com/guides/routing/#button + const AdapterLink = React.forwardRef((props, ref) => + <Link ref={ref} {...props} role={undefined} />) + const AdapterNavLink = React.forwardRef((props, ref) => + <NavLink ref={ref} {...props} role={undefined} />) const getInternalLink = perspective => { const searchMode = has(perspective, 'searchMode') ? perspective.searchMode : 'faceted-search' @@ -152,19 +64,22 @@ const TopBar = props => { const renderMobileMenuItem = perspective => { if (has(perspective, 'externalUrl')) { return ( - <a - className={classes.link} + <Box + component='a' key={perspective.id} href={perspective.externalUrl} target='_blank' rel='noopener noreferrer' + sx={{ + textDecoration: 'none' + }} > <MenuItem> {perspective.label ? perspective.label.toUpperCase() : intl.get(`perspectives.${perspective.id}.label`).toUpperCase()} </MenuItem> - </a> + </Box> ) } else { return ( @@ -183,31 +98,33 @@ const TopBar = props => { const renderDesktopTopMenuItem = perspective => { if (has(perspective, 'externalUrl')) { return ( - <a - className={classes.link} + <Box + component='a' key={perspective.id} href={perspective.externalUrl} target='_blank' rel='noopener noreferrer' + sx={{ + textDecoration: 'none' + }} > <Button - className={classes.appBarButton} + sx={createAppBarButtonStyle(false)} > {perspective.label ? perspective.label : intl.get(`perspectives.${perspective.id}.label`).toUpperCase()} </Button> - </a> + </Box> ) } else { return ( <Button key={perspective.id} - className={classes.appBarButton} component={AdapterNavLink} to={getInternalLink(perspective)} isActive={(match, location) => location.pathname.startsWith(`${props.rootUrl}/${perspective.id}`)} - activeClassName={classes.appBarButtonActive} + style={isActive => createAppBarButtonStyle(isActive)} > {intl.get(`perspectives.${perspective.id}.label`).toUpperCase()} </Button> @@ -219,17 +136,19 @@ const TopBar = props => { let jsx if (item.externalLink) { jsx = ( - <a - className={classes.link} + <Box key={item.id} href={intl.get(`topBar.info.${item.translatedUrl}`)} target='_blank' rel='noopener noreferrer' + sx={{ + textDecoration: 'none' + }} > <MenuItem onClick={handleMobileMenuClose}> {intl.get(`topBar.info.${item.translatedText}`).toUpperCase()} </MenuItem> - </a> + </Box> ) } else { jsx = ( @@ -284,28 +203,56 @@ const TopBar = props => { } 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='static'> - <Toolbar className={classes.topBarToolbar}> + <Toolbar + disableGutters + sx={theme => ({ + paddingLeft: theme.spacing(1.5), + paddingRight: theme.spacing(1.5) + })} + > <Button + sx={theme => ({ + paddingLeft: 0, + [theme.breakpoints.down('sm')]: { + minWidth: 48 + } + })} component={AdapterLink} to='/' - classes={{ - root: classes.mainLogoButtonRoot, - label: classes.mainLogoButtonLabel - }} onClick={() => federatedSearchMode ? props.clientFSClearResults() : null} > {topBar.logoImage && - <img - className={classes.mainLogo} + <Box + component='img' src={topBar.logoImage} alt={`${intl.get('appTitle.short')} logo`} + sx={theme => ({ + height: props.layoutConfig.topBar.logoImageReducedHeight || 23, + [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { + height: props.layoutConfig.topBar.logoImageHeight || 40 + }, + marginRight: theme.spacing(1) + })} />} {!topBar.hideLogoText && - <Typography className={classes.mainLogoTypography} variant='h5'> + <Typography + sx={theme => ({ + color: '#fff', + background: theme.palette.primary.main, + whiteSpace: 'nowrap', + textTransform: props.layoutConfig.topBar.logoTextTransform, + [theme.breakpoints.down('md')]: { + fontSize: '1.5rem' + }, + ...(props.layoutConfig.topBar.hideLogoTextOnMobile && { + [theme.breakpoints.down('sm')]: { + display: 'none' + } + }) + })} + variant='h5' + > {props.xsScreen ? intl.get('appTitle.mobile') : intl.get('appTitle.short')} </Typography>} </Button> @@ -316,7 +263,20 @@ const TopBar = props => { rel='noopener noreferrer' > <Button> - <img className={classes.logoSecondary} src={topBar.logoImageSecondary} alt='logoSecondary' /> + <Box + component='img' + src={topBar.logoImageSecondary} + alt='logoSecondary' + sx={theme => ({ + height: 26, + [theme.breakpoints.up('sm')]: { + height: 32 + }, + [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { + height: 52 + } + })} + /> </Button> </a>} {showSearchField && @@ -326,10 +286,23 @@ const TopBar = props => { xsScreen={props.xsScreen} rootUrl={rootUrl} />} - <div className={classes.grow} /> - <div className={classes.sectionDesktop}> + <Box sx={{ flexGrow: 1 }} /> + <Box + sx={theme => ({ + display: 'none', + [theme.breakpoints.up(props.layoutConfig.topBar.mobileMenuBreakpoint)]: { + display: 'flex' + } + })} + > {perspectives.map((perspective, index) => perspective.hideTopPerspectiveButton ? null : renderDesktopTopMenuItem(perspective, index))} - <div className={classes.appBarDivider} /> + <Box + sx={theme => ({ + marginLeft: theme.spacing(1), + marginRight: theme.spacing(1), + borderLeft: '2px solid white' + })} + /> {renderDesktopTopMenuItem({ id: 'feedback', externalUrl: props.layoutConfig.topBar.feedbackLink, @@ -343,11 +316,10 @@ const TopBar = props => { })} {!topBar.externalInstructions && <Button - className={classes.appBarButton} component={AdapterNavLink} to={`${props.rootUrl}/instructions`} isActive={(match, location) => location.pathname.startsWith(`${props.rootUrl}/instructions`)} - activeClassName={classes.appBarButtonActive} + style={isActive => createAppBarButtonStyle(isActive)} > {intl.get('topBar.instructions')} </Button>} @@ -358,22 +330,41 @@ const TopBar = props => { loadLocales={props.loadLocales} location={props.location} />} - </div> - <a - className={classes.secoLogo} + </Box> + <Box + component='a' href='https://seco.cs.aalto.fi' target='_blank' rel='noopener noreferrer' + sx={theme => ({ + marginLeft: theme.spacing(1), + [theme.breakpoints.down(props.layoutConfig.topBar.mobileMenuBreakpoint)]: { + display: 'none' + } + })} > <Button aria-label='link to Semantic Computing research group homepage'> - <img - className={classes.secoLogoImage} + <Box + component='img' src={secoLogo} alt='Semantic Computing research group logo' + sx={theme => ({ + height: 32, + [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { + height: 50 + } + })} /> </Button> - </a> - <div className={classes.sectionMobile}> + </Box> + <Box + sx={theme => ({ + display: 'flex', + [theme.breakpoints.up(props.layoutConfig.topBar.mobileMenuBreakpoint)]: { + display: 'none' + } + })} + > {props.layoutConfig.topBar.showLanguageButton && <TopBarLanguageButton currentLocale={currentLocale} @@ -384,17 +375,17 @@ const TopBar = props => { <IconButton aria-label='display more actions' color='inherit' - className={classes.mobileMenuButton} + edge='end' onClick={handleMobileMenuOpen} size='large' > <MoreIcon /> </IconButton> - </div> + </Box> </Toolbar> </AppBar> {renderMobileMenu(perspectives)} - </div> + </> ) } diff --git a/src/client/components/main_layout/TopBarSearchField.js b/src/client/components/main_layout/TopBarSearchField.js index 0c89fb47..0b6bd6a7 100644 --- a/src/client/components/main_layout/TopBarSearchField.js +++ b/src/client/components/main_layout/TopBarSearchField.js @@ -1,56 +1,12 @@ import React from 'react' import PropTypes from 'prop-types' import intl from 'react-intl-universal' -import { alpha } from '@mui/material/styles'; -import withStyles from '@mui/styles/withStyles'; +import { alpha } from '@mui/material/styles' +import Box from '@mui/material/Box' import SearchIcon from '@mui/icons-material/Search' import InputBase from '@mui/material/InputBase' -// import CircularProgress from '@mui/material/CircularProgress'; import history from '../../History' -const styles = theme => ({ - search: { - position: 'relative', - borderRadius: theme.shape.borderRadius, - backgroundColor: alpha(theme.palette.common.white, 0.15), - '&:hover': { - backgroundColor: alpha(theme.palette.common.white, 0.25) - }, - // marginRight: theme.spacing(3), - // marginLeft: theme.spacing(2.5), - width: '100%', - maxWidth: 300, - [theme.breakpoints.up('sm')]: { - marginLeft: theme.spacing(3), - width: 'auto' - } - }, - searchIcon: { - width: theme.spacing(9), - height: '100%', - position: 'absolute', - pointerEvents: 'none', - display: 'flex', - alignItems: 'center', - justifyContent: 'center' - }, - inputRoot: { - color: 'inherit', - width: '100%' - }, - inputInput: { - paddingTop: theme.spacing(1), - paddingRight: theme.spacing(1), - paddingBottom: theme.spacing(1), - paddingLeft: theme.spacing(10), - transition: theme.transitions.create('width'), - width: '100%', - [theme.breakpoints.up('md')]: { - width: 200 - } - } -}) - /** * A search field that can be embedded into the TopBar. */ @@ -93,30 +49,66 @@ class TopBarSearchField extends React.Component { } render () { - const { classes, xsScreen } = this.props - const placeholder = xsScreen ? intl.get('topBar.searchBarPlaceHolderShort') : intl.get('topBar.searchBarPlaceHolder') + const { xsScreen } = this.props + const placeholder = xsScreen + ? intl.get('topBar.searchBarPlaceHolderShort') + : intl.get('topBar.searchBarPlaceHolder') return ( - <div className={classes.search}> - <div className={classes.searchIcon}> + <Box + sx={theme => ({ + position: 'relative', + borderRadius: theme.shape.borderRadius, + backgroundColor: alpha(theme.palette.common.white, 0.15), + '&:hover': { + backgroundColor: alpha(theme.palette.common.white, 0.25) + }, + marginRight: theme.spacing(2), + marginLeft: 0, + width: '100%', + [theme.breakpoints.up('sm')]: { + marginLeft: theme.spacing(3), + width: 'auto' + } + })} + > + <Box + sx={theme => ({ + padding: theme.spacing(0, 2), + height: '100%', + position: 'absolute', + pointerEvents: 'none', + display: 'flex', + alignItems: 'center', + justifyContent: 'center' + })} + > <SearchIcon /> - </div> + </Box> <InputBase placeholder={placeholder} - classes={{ - root: classes.inputRoot, - input: classes.inputInput - }} inputProps={{ 'aria-label': 'search' }} onChange={this.handleChange} onKeyDown={this.handleOnKeyDown} + sx={theme => ({ + color: 'inherit', + '& .MuiInputBase-input': { + padding: theme.spacing(1, 1, 1, 0), + // vertical padding + font size from searchIcon + paddingLeft: `calc(1em + ${theme.spacing(4)})`, + transition: theme.transitions.create('width'), + width: '100%', + [theme.breakpoints.up('md')]: { + width: '20ch' + } + } + })} /> - </div> + </Box> ) } } TopBarSearchField.propTypes = { - classes: PropTypes.object.isRequired, fetchFullTextResults: PropTypes.func, xsScreen: PropTypes.bool.isRequired, rootUrl: PropTypes.string.isRequired @@ -124,4 +116,4 @@ TopBarSearchField.propTypes = { export const TopBarSearchFieldComponent = TopBarSearchField -export default withStyles(styles)(TopBarSearchField) +export default TopBarSearchField diff --git a/src/client/components/perspectives/sampo/Footer.js b/src/client/components/perspectives/sampo/Footer.js index 6a301866..c400c34f 100644 --- a/src/client/components/perspectives/sampo/Footer.js +++ b/src/client/components/perspectives/sampo/Footer.js @@ -2,33 +2,13 @@ import React from 'react' import Paper from '@mui/material/Paper' import PropTypes from 'prop-types' import Grid from '@mui/material/Grid' -import makeStyles from '@mui/styles/makeStyles'; +import makeStyles from '@mui/styles/makeStyles' +import { getSpacing } from '../../../helpers/helpers' import aaltoLogo from '../../../img/logos/Aalto_SCI_EN_13_BLACK_2_cropped.png' import hyLogo from '../../../img/logos/university-of-helsinki-logo-transparent-black.png' import heldigLogo from '../../../img/logos/heldig-logo-transparent-black.png' const useStyles = makeStyles(theme => ({ - root: { - display: 'block', - boxShadow: '0 -20px 20px -20px #333', - borderRadius: 0 - }, - layout: props => ({ - [theme.breakpoints.up(props.layoutConfig.hundredPercentHeightBreakPoint)]: { - height: props.layoutConfig.footer.reducedHeight - // height: 115, for two row footer - }, - [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { - height: props.layoutConfig.footer.defaultHeight - }, - marginLeft: theme.spacing(2), - marginRight: theme.spacing(2), - [theme.breakpoints.up(1500 + theme.spacing(6))]: { - width: 1500, - marginLeft: 'auto', - marginRight: 'auto' - } - }), gridContainer: { height: '100%', marginTop: 0, @@ -85,26 +65,46 @@ const useStyles = makeStyles(theme => ({ const Footer = props => { const classes = useStyles(props) return ( - <Paper className={classes.root}> - <div className={classes.layout}> - <Grid className={classes.gridContainer} container spacing={3}> - <Grid item xs className={classes.gridItem}> - <a className={classes.link} href='https://www.aalto.fi/en/school-of-science' target='_blank' rel='noopener noreferrer'> - <img className={classes.aaltoLogo} src={aaltoLogo} alt='Aalto University logo' /> - </a> - </Grid> - <Grid item xs className={classes.gridItem}> - <a className={classes.link} href='https://www.helsinki.fi/en' target='_blank' rel='noopener noreferrer'> - <img className={classes.hyLogo} src={hyLogo} alt='University of Helsinki logo' /> - </a> - </Grid> - <Grid item xs className={classes.gridItem}> - <a className={classes.link} href='https://www.helsinki.fi/en/helsinki-centre-for-digital-humanities' target='_blank' rel='noopener noreferrer'> - <img className={classes.heldigLogo} src={heldigLogo} alt='Helsinki Centre for Digital Humanities logo' /> - </a> - </Grid> + <Paper + sx={theme => ({ + boxShadow: '0 -20px 20px -20px #333', + borderRadius: 0, + height: { + hundredPercentHeight: props.layoutConfig.footer.reducedHeight, + reducedHeight: props.layoutConfig.footer.defaultHeight + } + })} + > + <Grid + className={classes.gridContainer} + container spacing={3} + sx={theme => ({ + height: '100%', + marginTop: 0, + marginBottom: 0, + [theme.breakpoints.up(1500 + getSpacing(theme, 6))]: { + width: 1500, + marginLeft: 'auto', + marginRight: 'auto' + } + })} + > + <Grid item xs className={classes.gridItem}> + <a className={classes.link} href='https://www.aalto.fi/en/school-of-science' target='_blank' rel='noopener noreferrer'> + <img className={classes.aaltoLogo} src={aaltoLogo} alt='Aalto University logo' /> + </a> + </Grid> + <Grid item xs className={classes.gridItem}> + <a className={classes.link} href='https://www.helsinki.fi/en' target='_blank' rel='noopener noreferrer'> + <img className={classes.hyLogo} src={hyLogo} alt='University of Helsinki logo' /> + </a> + </Grid> + <Grid item xs className={classes.gridItem}> + <a className={classes.link} href='https://www.helsinki.fi/en/helsinki-centre-for-digital-humanities' target='_blank' rel='noopener noreferrer'> + <img className={classes.heldigLogo} src={heldigLogo} alt='Helsinki Centre for Digital Humanities logo' /> + </a> </Grid> - </div> + </Grid> </Paper> ) } diff --git a/src/client/components/perspectives/sampo/Main.js b/src/client/components/perspectives/sampo/Main.js index 62df9eea..56db65f0 100644 --- a/src/client/components/perspectives/sampo/Main.js +++ b/src/client/components/perspectives/sampo/Main.js @@ -49,19 +49,18 @@ const Main = props => { sx={theme => { const { layoutConfig } = props const defaultHeightReduction = layoutConfig.topBar.defaultHeight + - layoutConfig.footer.defaultHeight + getSpacing(theme, 1) + layoutConfig.footer.defaultHeight + getSpacing(theme, 2) const reducedHeightReduction = layoutConfig.topBar.reducedHeight + - layoutConfig.footer.reducedHeight + getSpacing(theme, 1) + layoutConfig.footer.reducedHeight + getSpacing(theme, 2) return { - [theme.breakpoints.up(props.layoutConfig.hundredPercentHeightBreakPoint)]: { - overflow: 'auto', - height: `calc(100% - ${reducedHeightReduction}px)` + paddingBottom: theme.spacing(2), + height: { + hundredPercentHeight: `calc(100% - ${reducedHeightReduction}px)`, + reducedHeight: `calc(100% - ${defaultHeightReduction}px)` }, - [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { - overflow: 'auto', - height: `calc(100% - ${defaultHeightReduction}px)` - }, - marginBottom: theme.spacing(1) + overflow: { + hundredPercentHeight: 'auto' + } } }} > diff --git a/src/client/containers/SemanticPortal.js b/src/client/containers/SemanticPortal.js index 7b24a5d1..069ab294 100644 --- a/src/client/containers/SemanticPortal.js +++ b/src/client/containers/SemanticPortal.js @@ -5,7 +5,6 @@ import { has } from 'lodash' import { connect } from 'react-redux' import { makeStyles } from '@material-ui/core/styles' import { withRouter, Route, Redirect, Switch } from 'react-router-dom' -import classNames from 'classnames' import { compose } from '@shakacode/recompose' import { useTheme } from '@mui/material/styles' import useMediaQuery from '@mui/material/useMediaQuery' @@ -114,16 +113,6 @@ const useStyles = makeStyles(theme => ({ height: `calc(100% - ${layoutConfig.topBar.defaultHeight + layoutConfig.footer.defaultHeight + theme.spacing(1)}px)` } }, - textPageContainer: { - margin: theme.spacing(0.5), - width: `calc(100% - ${theme.spacing(1)}px)`, - [theme.breakpoints.up(layoutConfig.hundredPercentHeightBreakPoint)]: { - height: `calc(100% - ${layoutConfig.topBar.reducedHeight + theme.spacing(1.5)}px)` - }, - [theme.breakpoints.up(layoutConfig.reducedHeightBreakpoint)]: { - height: `calc(100% - ${layoutConfig.topBar.defaultHeight + theme.spacing(1.5)}px)` - } - }, perspectiveContainer: { margin: theme.spacing(0.5), width: `calc(100% - ${theme.spacing(1)}px)`, @@ -244,7 +233,7 @@ const SemanticPortal = props => { const { error } = props const theme = useTheme() const classes = useStyles(props) - const xsScreen = useMediaQuery(theme.breakpoints.down('xs')) + const xsScreen = useMediaQuery(theme.breakpoints.down('sm')) const smScreen = useMediaQuery(theme.breakpoints.between('sm', 'md')) const mdScreen = useMediaQuery(theme.breakpoints.between('md', 'lg')) const lgScreen = useMediaQuery(theme.breakpoints.between('lg', 'xl')) @@ -626,31 +615,29 @@ const SemanticPortal = props => { <Route path={`${rootUrlWithLang}/about`} render={() => - <div className={classNames(classes.mainContainer, classes.textPageContainer)}> - <TextPage> - {intl.getHTML('aboutThePortalPartOne')} - {knowledgeGraphMetadataConfig.showTable && - <KnowledgeGraphMetadataTable - portalConfig={portalConfig} - layoutConfig={layoutConfig} - perspectiveID={knowledgeGraphMetadataConfig.perspective} - resultClass='knowledgeGraphMetadata' - fetchKnowledgeGraphMetadata={props.fetchKnowledgeGraphMetadata} - knowledgeGraphMetadata={props[knowledgeGraphMetadataConfig.perspective] - ? props[knowledgeGraphMetadataConfig.perspective].knowledgeGraphMetadata - : null} - />} - {intl.getHTML('aboutThePortalPartTwo')} - </TextPage> - </div>} + <TextPage layoutConfig={layoutConfig}> + {intl.getHTML('aboutThePortalPartOne')} + {knowledgeGraphMetadataConfig.showTable && + <KnowledgeGraphMetadataTable + portalConfig={portalConfig} + layoutConfig={layoutConfig} + perspectiveID={knowledgeGraphMetadataConfig.perspective} + resultClass='knowledgeGraphMetadata' + fetchKnowledgeGraphMetadata={props.fetchKnowledgeGraphMetadata} + knowledgeGraphMetadata={props[knowledgeGraphMetadataConfig.perspective] + ? props[knowledgeGraphMetadataConfig.perspective].knowledgeGraphMetadata + : null} + />} + {intl.getHTML('aboutThePortalPartTwo')} + </TextPage>} />} {!layoutConfig.topBar.externalInstructions && <Route path={`${rootUrlWithLang}/instructions`} render={() => - <div className={classNames(classes.mainContainer, classes.textPageContainer)}> - <TextPage>{intl.getHTML('instructions')}</TextPage> - </div>} + <TextPage layoutConfig={layoutConfig}> + {intl.getHTML('instructions')} + </TextPage>} />} </> </div> diff --git a/src/client/img/logos/logo.png b/src/client/img/logos/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1738c87bdb9b30662d587927cc0e822d5bac06a7 GIT binary patch literal 3694 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 literal 0 HcmV?d00001 diff --git a/src/configs/portalConfig.json b/src/configs/portalConfig.json index fe3e88ce..bbc7c36f 100644 --- a/src/configs/portalConfig.json +++ b/src/configs/portalConfig.json @@ -62,11 +62,14 @@ "paginationToolbarHeight": 37, "tableFontSize": "0.8rem", "topBar": { + "logoImage": "logos/logo.png", + "logoTextTransform": "none", + "hideLogoTextOnMobile": true, "showLanguageButton": true, "feedbackLink": "https://link.webropolsurveys.com/...", "externalInstructions": false, "externalAboutPage": false, - "reducedHeight": 44, + "reducedHeight": 48, "defaultHeight": 64, "mobileMenuBreakpoint": 1360, "infoDropdown": [ -- GitLab