diff --git a/src/client/components/App.js b/src/client/components/App.js index cf785afd49b166a8efb41cc0d5b1a396af96f8a2..a4de9f0f5fb08173eac788f591d8b9faf746405d 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 5f7f70cddebd67007a1a7fa803863219d29dd531..c7b992495de7359c6becfd2e86c30b388f9e1211 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 312f6d578a339eeaabfdd16231761acd8ebe7c11..862f9add1965ccc1a59a652217bf166c33e7accb 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 0c89fb4708e67a8354a7c68dccf749c4ec7f0699..0b6bd6a7ab5c60eadd412594cda9fd9f420fd3a6 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 6a3018660c0ec4ad740133ac690a8f97ee2a4c48..c400c34f1ba11f8f92c3d42aec65856fc272624f 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 62df9eea49e5716cf4320c5b04bf26c04e0913a3..56db65f0af0c1f00990609dd13ea8b22a175a7af 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 7b24a5d1c1de884e76d8da0b98494703dfe773f1..069ab294a4c79d300130cdbd843d16ebd5569651 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 Binary files /dev/null and b/src/client/img/logos/logo.png differ diff --git a/src/configs/portalConfig.json b/src/configs/portalConfig.json index fe3e88ce656d75ed5744d46c2c9e3807f7e9443f..bbc7c36fdc536d05eca6a8da357d2900105d80ca 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": [