From 81082c8bf39cebed28803448b8431642a319ed33 Mon Sep 17 00:00:00 2001 From: esikkala <esko.ikkala@aalto.fi> Date: Tue, 8 Jun 2021 11:17:48 +0300 Subject: [PATCH] Refactor layout - unify main level container styles - new layout config object - better support for small screens --- src/client/components/App.js | 12 + src/client/components/facet_bar/FacetBar.js | 28 +- .../components/facet_bar/FacetHeader.js | 13 +- src/client/components/facet_bar/FacetInfo.js | 15 +- .../components/facet_results/ApexChart.js | 10 +- src/client/components/facet_results/Deck.js | 11 +- src/client/components/facet_results/Export.js | 10 +- .../components/facet_results/LeafletMap.js | 31 +- .../components/facet_results/Network.js | 7 +- .../components/facet_results/ResultTable.js | 23 +- .../facet_results/VirtualizedTable.js | 8 +- .../components/main_layout/InfoHeader.js | 108 +-- src/client/components/main_layout/Main.js | 36 +- src/client/components/main_layout/MainCard.js | 9 +- .../components/main_layout/PerspectiveTabs.js | 18 +- .../sampo/FacetedSearchPerspective.js | 3 +- .../components/perspectives/sampo/Footer.js | 43 +- .../perspectives/sampo/InstanceHomePage.js | 19 +- .../perspectives/sampo/Perspective1.js | 17 +- .../perspectives/sampo/Perspective2.js | 6 +- .../perspectives/sampo/Perspective3.js | 12 +- .../components/perspectives/sampo/TopBar.js | 46 +- .../sampo/client_fs/ClientFSMain.js | 53 +- .../sampo/client_fs/ClientFSPerspective.js | 25 +- src/client/configs/sampo/GeneralConfig.js | 40 +- .../configs/sampo/Leaflet/LeafletConfig.js | 3 + src/client/configs/sampo/PerspectiveConfig.js | 9 +- src/client/containers/SemanticPortal.js | 696 +++++++++--------- src/client/index.css | 17 +- 29 files changed, 730 insertions(+), 598 deletions(-) diff --git a/src/client/components/App.js b/src/client/components/App.js index 07346cad..f9755774 100644 --- a/src/client/components/App.js +++ b/src/client/components/App.js @@ -21,6 +21,18 @@ const theme = createMuiTheme({ } } }, + MuiAccordionSummary: { + content: { + '&$expanded': { + marginTop: 4 + } + }, + expandIcon: { + '&$expanded': { + marginTop: -16 + } + } + }, MuiButton: { endIcon: { marginLeft: 0 diff --git a/src/client/components/facet_bar/FacetBar.js b/src/client/components/facet_bar/FacetBar.js index 12ce8e3d..57b65ae0 100644 --- a/src/client/components/facet_bar/FacetBar.js +++ b/src/client/components/facet_bar/FacetBar.js @@ -30,10 +30,14 @@ const styles = theme => ({ borderBottomLeftRadius: 0, borderBottomRightRadius: 0 }, - accordionSummaryRoot: { + accordionSummaryRoot: props => ({ paddingLeft: theme.spacing(1), - cursor: 'default !important' - }, + cursor: 'default !important', + minHeight: 38, + [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { + minHeight: 48 + } + }), accordionSummaryContent: { margin: 0 }, @@ -73,7 +77,7 @@ class FacetBar extends React.Component { } } - handleExpandButtonOnClick = facetID => () => { + handleExpandButtonOnClick = facetID => event => { const activeFacets = this.state.activeFacets if (activeFacets.has(facetID)) { activeFacets.delete(facetID) @@ -244,6 +248,7 @@ class FacetBar extends React.Component { <Accordion key={facetID} expanded={isActive} + // onClick={this.handleExpandButtonOnClick(facetID)} > <AccordionSummary classes={{ @@ -273,6 +278,7 @@ class FacetBar extends React.Component { updateFacetOption={this.props.updateFacetOption} facetDescription={description} rootUrl={this.props.rootUrl} + layoutConfig={this.props.layoutConfig} /> </AccordionSummary> <AccordionDetails @@ -284,6 +290,15 @@ class FacetBar extends React.Component { ) } + getTypographyVariant = () => { + const { screenSize } = this.props + let variant = 'h6' + if (screenSize === 'xs' || screenSize === 'sm' || screenSize === 'md') { + variant = 'subtitle2' + } + return variant + } + renderFacets = ({ classes, facets, someFacetIsFetching }) => { const { screenSize } = this.props if (screenSize === 'xs' || screenSize === 'sm') { @@ -298,7 +313,7 @@ class FacetBar extends React.Component { aria-controls='panel1a-content' id='panel1a-header' > - <Typography variant='h6'>{intl.get('facetBar.filters')}</Typography> + <Typography variant={this.getTypographyVariant()}>{intl.get('facetBar.filters')}</Typography> </AccordionSummary> <AccordionDetails className={classes.accordionDetails} @@ -375,7 +390,8 @@ class FacetBar extends React.Component { screenSize={this.props.screenSize} /> </Paper>} - {this.renderFacets({ classes, facets, someFacetIsFetching })} + {(facetedSearchMode === 'serverFS' || facetData.results !== null) && + this.renderFacets({ classes, facets, someFacetIsFetching })} </div> ) } diff --git a/src/client/components/facet_bar/FacetHeader.js b/src/client/components/facet_bar/FacetHeader.js index 81170948..65a56179 100644 --- a/src/client/components/facet_bar/FacetHeader.js +++ b/src/client/components/facet_bar/FacetHeader.js @@ -30,6 +30,12 @@ const styles = theme => ({ // justifyContent: 'space-between', width: '100%' }, + facetLabel: props => ({ + fontSize: '0.875rem', + [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { + fontSize: '1rem' + } + }), facetValuesContainerTen: { height: 345, padding: theme.spacing(1) @@ -55,6 +61,7 @@ class FacetHeader extends React.Component { } handleMenuButtonClick = event => { + event.stopPropagation() this.setState({ anchorEl: event.currentTarget }) }; @@ -332,6 +339,7 @@ class FacetHeader extends React.Component { <> <Tooltip disableFocusListener title={intl.get('facetBar.filterOptions')}> <IconButton + className='facetMenuButton' aria-label={intl.get('facetBar.filterOptions')} aria-owns={open ? 'facet-option-menu' : undefined} aria-haspopup='true' @@ -361,7 +369,7 @@ class FacetHeader extends React.Component { return ( <div className={classes.headingContainer}> - <Typography variant='body1'>{facetLabel} </Typography> + <Typography className={classes.facetLabel} variant='body1'>{facetLabel}</Typography> <Tooltip title={facetDescription} enterDelay={300} @@ -396,7 +404,8 @@ FacetHeader.propTypes = { clearFacet: PropTypes.func, updateFacetOption: PropTypes.func, facetDescription: PropTypes.string.isRequired, - rootUrl: PropTypes.string.isRequired + rootUrl: PropTypes.string.isRequired, + layoutConfig: PropTypes.object.isRequired } export const FacetHeaderComponent = FacetHeader diff --git a/src/client/components/facet_bar/FacetInfo.js b/src/client/components/facet_bar/FacetInfo.js index 660753a5..50afa37a 100644 --- a/src/client/components/facet_bar/FacetInfo.js +++ b/src/client/components/facet_bar/FacetInfo.js @@ -49,6 +49,15 @@ class FacetInfo extends React.Component { handleRemoveAllFiltersOnClick = () => this.props.clearAllFacets({ facetClass: this.props.facetClass }) + getTypographyVariant = () => { + const { screenSize } = this.props + let variant = 'h6' + if (screenSize === 'xs' || screenSize === 'sm' || screenSize === 'md') { + variant = 'subtitle2' + } + return variant + } + render () { const { classes, facetClass, resultClass, resultCount, someFacetIsFetching, screenSize } = this.props const mobileMode = screenSize === 'xs' || screenSize === 'sm' @@ -90,7 +99,7 @@ class FacetInfo extends React.Component { <div className={classes.root}> {this.props.fetchingResultCount ? <CircularProgress style={{ color: purple[500] }} thickness={5} size={26} /> - : <Typography variant='h6'>{intl.get('facetBar.results')}: {resultCount} {intl.get(`perspectives.${resultClass}.facetResultsType`)}</Typography>} + : <Typography variant={this.getTypographyVariant()}>{intl.get('facetBar.results')}: {resultCount} {intl.get(`perspectives.${resultClass}.facetResultsType`)}</Typography>} {!mobileMode && <Divider className={classes.facetInfoDivider} />} {(activeUriFilters || activeSpatialFilters || @@ -100,7 +109,7 @@ class FacetInfo extends React.Component { ) && <> <div className={classes.headerContainer}> - <Typography variant='h6'>{intl.get('facetBar.activeFilters')}</Typography> + <Typography variant={this.getTypographyVariant()}>{intl.get('facetBar.activeFilters')}</Typography> <Button variant='contained' color='secondary' @@ -128,7 +137,7 @@ class FacetInfo extends React.Component { </div> <Divider className={classes.facetInfoDivider} /> </>} - {!mobileMode && <Typography variant='h6'>{intl.get('facetBar.narrowDownBy')}:</Typography>} + {!mobileMode && <Typography variant={this.getTypographyVariant()}>{intl.get('facetBar.narrowDownBy')}:</Typography>} </div> ) } diff --git a/src/client/components/facet_results/ApexChart.js b/src/client/components/facet_results/ApexChart.js index bdcfe759..d8debd88 100644 --- a/src/client/components/facet_results/ApexChart.js +++ b/src/client/components/facet_results/ApexChart.js @@ -12,6 +12,9 @@ import Typography from '@material-ui/core/Typography' import GeneralDialog from '../main_layout/GeneralDialog' import InstaceList from '../main_layout/InstanceList' +const defaultPadding = 32 +const smallScreenPadding = 8 + const styles = theme => ({ selectContainer: { display: 'flex', @@ -139,7 +142,7 @@ class ApexChart extends React.Component { if (this.isSmallScreen()) { return 'auto' } - const rootHeightReduction = 136 // tabs + padding + const rootHeightReduction = this.props.layoutConfig.tabHeight + 2 * defaultPadding + 1 return `calc(100% - ${rootHeightReduction}px)` } @@ -172,7 +175,7 @@ class ApexChart extends React.Component { height: '100%' } if (pageType === 'facetResults' || pageType === 'instancePage') { - const padding = this.isSmallScreen() ? 8 : 32 + const padding = this.isSmallScreen() ? smallScreenPadding : defaultPadding rootStyle = { height: this.getHeightForRootContainer(), width: `calc(100% - ${2 * padding}px)`, @@ -269,7 +272,8 @@ ApexChart.propTypes = { uri: PropTypes.string, dropdownForResultClasses: PropTypes.bool, facetResultsType: PropTypes.string, - resultClasses: PropTypes.array + resultClasses: PropTypes.array, + layoutConfig: PropTypes.object.isRequired } export const ApexChartComponent = ApexChart diff --git a/src/client/components/facet_results/Deck.js b/src/client/components/facet_results/Deck.js index ca5b4c8f..0aaf8fb5 100644 --- a/src/client/components/facet_results/Deck.js +++ b/src/client/components/facet_results/Deck.js @@ -20,12 +20,12 @@ import { purple } from '@material-ui/core/colors' */ const styles = theme => ({ - root: { + root: props => ({ height: 400, - [theme.breakpoints.up('md')]: { - height: 'calc(100% - 72px)' + [theme.breakpoints.up(props.layoutConfig.hundredPercentHeightBreakPoint)]: { + height: `calc(100% - ${props.layoutConfig.tabHeight}px)` } - }, + }), spinner: { height: 40, width: 40, @@ -298,7 +298,8 @@ Deck.propTypes = { legendTitle: PropTypes.string, showMoreText: PropTypes.string, listHeadingSingleInstance: PropTypes.string, - listHeadingMultipleInstances: PropTypes.string + listHeadingMultipleInstances: PropTypes.string, + layoutConfig: PropTypes.object.isRequired } export const DeckComponent = Deck diff --git a/src/client/components/facet_results/Export.js b/src/client/components/facet_results/Export.js index 4e6775cb..d493e3b0 100644 --- a/src/client/components/facet_results/Export.js +++ b/src/client/components/facet_results/Export.js @@ -8,13 +8,15 @@ import querystring from 'querystring' import intl from 'react-intl-universal' const styles = theme => ({ - root: { - height: 'calc(100% - 72px)', - width: '100%', + root: props => ({ + minHeight: 400, + [theme.breakpoints.up(props.layoutConfig.hundredPercentHeightBreakPoint)]: { + height: `calc(100% - ${props.layoutConfig.tabHeight}px)` + }, display: 'flex', alignItems: 'center', justifyContent: 'center' - }, + }), link: { textDecoration: 'none' }, diff --git a/src/client/components/facet_results/LeafletMap.js b/src/client/components/facet_results/LeafletMap.js index fa42f32f..e032b704 100644 --- a/src/client/components/facet_results/LeafletMap.js +++ b/src/client/components/facet_results/LeafletMap.js @@ -8,7 +8,6 @@ import buffer from '@turf/buffer' import CircularProgress from '@material-ui/core/CircularProgress' import { purple } from '@material-ui/core/colors' import history from '../../History' -import { MAPBOX_ACCESS_TOKEN, MAPBOX_STYLE } from '../../configs/sampo/GeneralConfig' // import { apiUrl } from '../../epics' import 'leaflet/dist/leaflet.css' // Official Leaflet styles @@ -41,27 +40,27 @@ import markerIconOrange from '../../img/markers/marker-icon-orange.png' import markerIconYellow from '../../img/markers/marker-icon-yellow.png' const styles = theme => ({ - leafletContainerfacetResults: { + leafletContainerfacetResults: props => ({ height: 400, - [theme.breakpoints.up('md')]: { - height: 'calc(100% - 72px)' + [theme.breakpoints.up(props.layoutConfig.hundredPercentHeightBreakPoint)]: { + height: `calc(100% - ${props.layoutConfig.tabHeight}px)` }, position: 'relative' - }, - leafletContainerclientFSResults: { + }), + leafletContainerclientFSResults: props => ({ height: 400, - [theme.breakpoints.up('md')]: { - height: 'calc(100% - 72px)' + [theme.breakpoints.up(props.layoutConfig.hundredPercentHeightBreakPoint)]: { + height: `calc(100% - ${props.layoutConfig.tabHeight}px)` }, position: 'relative' - }, - leafletContainerinstancePage: { + }), + leafletContainerinstancePage: props => ({ height: 400, - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up(props.layoutConfig.hundredPercentHeightBreakPoint)]: { height: '100%' }, position: 'relative' - }, + }), leafletContainermobileMapPage: { height: '100%', position: 'relative' @@ -273,7 +272,7 @@ class LeafletMap extends React.Component { initMap = () => { // Base layer(s) - const mapboxBaseLayer = L.tileLayer(`https://api.mapbox.com/styles/v1/mapbox/${MAPBOX_STYLE}/tiles/{z}/{x}/{y}?access_token=${MAPBOX_ACCESS_TOKEN}`, { + const mapboxBaseLayer = L.tileLayer(`https://api.mapbox.com/styles/v1/mapbox/${this.props.mapBoxStyle}/tiles/{z}/{x}/{y}?access_token=${this.props.mapBoxAccessToken}`, { attribution: '© <a href="https://www.mapbox.com/map-feedback/">Mapbox</a> © <a href="http://osm.org/copyright">OpenStreetMap</a> contributors', tileSize: 512, zoomOffset: -1 @@ -341,7 +340,7 @@ class LeafletMap extends React.Component { // initialize layers from external sources if (this.props.showExternalLayers) { const basemaps = { - [intl.get(`leafletMap.basemaps.mapbox.${MAPBOX_STYLE}`)]: mapboxBaseLayer + [intl.get(`leafletMap.basemaps.mapbox.${this.props.mapBoxStyle}`)]: mapboxBaseLayer // [intl.get('leafletMap.basemaps.backgroundMapNLS')]: backgroundMapNLS, // [intl.get('leafletMap.basemaps.topographicalMapNLS')]: topographicalMapNLS, // [intl.get('leafletMap.basemaps.airMapNLS')]: airMapNLS @@ -1015,7 +1014,9 @@ LeafletMap.propTypes = { facetedSearchMode: PropTypes.string, container: PropTypes.string, showError: PropTypes.func, - uri: PropTypes.string + uri: PropTypes.string, + mapBoxStyle: PropTypes.string, + mapBoxAccessToken: PropTypes.string } export const LeafletMapComponent = LeafletMap diff --git a/src/client/components/facet_results/Network.js b/src/client/components/facet_results/Network.js index bd078753..7bd83bf8 100644 --- a/src/client/components/facet_results/Network.js +++ b/src/client/components/facet_results/Network.js @@ -130,7 +130,7 @@ class Network extends React.Component { } render = () => { - const { fetching, pageType } = this.props + const { fetching, pageType, layoutConfig } = this.props const rootStyle = { width: '100%', backgroundColor: '#fff', @@ -140,7 +140,7 @@ class Network extends React.Component { rootStyle.height = 'calc(100% - 1px)' } if (pageType === 'facetResults') { - rootStyle.height = 'calc(100% - 72px)' + rootStyle.height = `calc(100% - ${layoutConfig.tabHeight + 1}px)` } const spinnerContainerStyle = { display: 'flex', @@ -176,7 +176,8 @@ Network.propTypes = { layout: PropTypes.object, preprocess: PropTypes.func, fetching: PropTypes.bool, - fitLayout: PropTypes.bool + fitLayout: PropTypes.bool, + layoutConfig: PropTypes.object.isRequired } export default Network diff --git a/src/client/components/facet_results/ResultTable.js b/src/client/components/facet_results/ResultTable.js index 9461af64..eccdc67c 100644 --- a/src/client/components/facet_results/ResultTable.js +++ b/src/client/components/facet_results/ResultTable.js @@ -19,31 +19,32 @@ import ResultTablePaginationActions from './ResultTablePaginationActions' import history from '../../History' const styles = theme => ({ - tableContainer: { + tableContainer: props => ({ overflow: 'auto', - width: '100%', - height: 'auto', - [theme.breakpoints.up('md')]: { - height: 'calc(100% - 126px)' + [theme.breakpoints.up(props.layoutConfig.hundredPercentHeightBreakPoint)]: { + height: `calc(100% - ${props.layoutConfig.tabHeight + props.layoutConfig.paginationToolbarHeight + 2}px)` }, backgroundColor: theme.palette.background.paper, borderTop: '1px solid rgba(224, 224, 224, 1);' - }, + }), paginationRoot: { display: 'flex', backgroundColor: '#fff', - borderTop: '1px solid rgba(224, 224, 224, 1);' + borderTop: '1px solid rgba(224, 224, 224, 1);', + alignItems: 'center' }, paginationCaption: { minWidth: 110 }, - paginationToolbar: { - [theme.breakpoints.down('xs')]: { + paginationToolbar: props => ({ + '& p': { fontSize: '0.75rem' }, + minHeight: props.layoutConfig.paginationToolbarHeight, + [theme.breakpoints.down(480)]: { display: 'flex', flexWrap: 'wrap', - height: 100 + height: 60 } - }, + }), progressContainer: { width: '100%', height: 'calc(100% - 72px)', diff --git a/src/client/components/facet_results/VirtualizedTable.js b/src/client/components/facet_results/VirtualizedTable.js index bed03ebd..b3b4eb4a 100644 --- a/src/client/components/facet_results/VirtualizedTable.js +++ b/src/client/components/facet_results/VirtualizedTable.js @@ -17,9 +17,11 @@ import { // https://github.com/bvaughn/react-virtualized/blob/master/docs/usingAutoSizer.md const styles = theme => ({ - root: { + root: props => ({ display: 'flex', - height: 'calc(100% - 74px)', + [theme.breakpoints.up(props.layoutConfig.hundredPercentHeightBreakPoint)]: { + height: `calc(100% - ${props.layoutConfig.tabHeight}px)` + }, // width: 'calc(100% - 1px)', flexGrow: 1, borderTop: '1px solid rgb(224, 224, 224)', @@ -27,7 +29,7 @@ const styles = theme => ({ '& a': { textDecoration: 'underline' } - }, + }), resultsInfo: { flexGrow: 0 } diff --git a/src/client/components/main_layout/InfoHeader.js b/src/client/components/main_layout/InfoHeader.js index 5c6d423e..ab6f1e3c 100644 --- a/src/client/components/main_layout/InfoHeader.js +++ b/src/client/components/main_layout/InfoHeader.js @@ -1,64 +1,81 @@ import React from 'react' import PropTypes from 'prop-types' -import { withStyles } from '@material-ui/core/styles' +import { makeStyles } from '@material-ui/core/styles' import Accordion from '@material-ui/core/Accordion' import AccordionSummary from '@material-ui/core/AccordionSummary' import AccordionDetails from '@material-ui/core/AccordionDetails' import ExpandMoreIcon from '@material-ui/icons/ExpandMore' import Typography from '@material-ui/core/Typography' -import Grid from '@material-ui/core/Grid' // import Divider from '@material-ui/core/Divider'; import IconButton from '@material-ui/core/IconButton' import InfoIcon from '@material-ui/icons/InfoOutlined' import intl from 'react-intl-universal' -const styles = theme => ({ +const useStyles = makeStyles(theme => ({ root: { - position: 'absolute', - // marginTop: 64, - paddingTop: theme.spacing(1), - paddingLeft: theme.spacing(1.5), - paddingRight: theme.spacing(1.5), - [theme.breakpoints.down('sm')]: { - marginTop: 56 - }, - [theme.breakpoints.up('sm')]: { - marginTop: 64 - } + marginTop: theme.spacing(0.5), + marginLeft: theme.spacing(0.5), + marginRight: theme.spacing(0.5) }, panel: { width: '100%' }, - summary: { - paddingLeft: theme.spacing(1) - }, + summary: props => ({ + paddingLeft: theme.spacing(1), + [theme.breakpoints.down(props.layoutConfig.reducedHeightBreakpoint)]: { + minHeight: `${props.layoutConfig.infoHeader.reducedHeight.height}px !important` + }, + [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { + minHeight: `${props.layoutConfig.infoHeader.default.height}px !important` + } + }), summaryContent: { display: 'block', - marginBottom: `${theme.spacing(1)}px !important` + marginTop: theme.spacing(0.5), + marginBottom: `${theme.spacing(0.5)}px !important` }, headingContainer: { display: 'flex' }, + heading: { + flexShrink: 1 + }, infoIconButton: { + padding: 0, marginLeft: theme.spacing(0.5) }, - infoIcon: { - fontSize: 32 - }, + infoIcon: props => ({ + [theme.breakpoints.down(props.layoutConfig.reducedHeightBreakpoint)]: { + fontSize: props.layoutConfig.infoHeader.reducedHeight.infoIconFontSize + }, + [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { + fontSize: props.layoutConfig.infoHeader.default.infoIconFontSize + } + }), label: { marginTop: theme.spacing(1), height: 32, overflow: 'auto' }, - content: { + expandedContent: props => ({ + '& p, & ul': { + fontSize: '0.875rem' + }, + height: props.layoutConfig.infoHeader.reducedHeight.expandedContentHeight, + [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { + height: props.layoutConfig.infoHeader.default.expandedContentHeight, + '& p, & ul': { + fontSize: '1rem' + } + }, paddingTop: 0, paddingLeft: theme.spacing(1), paddingBottom: theme.spacing(1), marginBottom: theme.spacing(1), overflow: 'auto', display: 'block' - } -}) + }) +})) /** * A component for instructions for a faceted search perspective or an entity landing page. @@ -79,38 +96,46 @@ const InfoHeader = props => { return label } + const getHeadingVariant = () => { + const { screenSize } = props + let variant = props.layoutConfig.infoHeader.default.headingVariant + if (screenSize === 'xs' || screenSize === 'sm' || screenSize === 'md') { + variant = props.layoutConfig.infoHeader.reducedHeight.headingVariant + } + return variant + } + + const classes = useStyles(props) + return ( - <Grid container spacing={1} className={props.classes.root}> + <div className={classes.root}> <Accordion - className={props.classes.panel} + className={classes.panel} expanded={props.expanded} > <AccordionSummary - className={props.classes.summary} + className={classes.summary} classes={{ - content: props.classes.summaryContent + content: classes.summaryContent }} expandIcon={<ExpandMoreIcon />} aria-controls='panel1a-content' id='panel1a-header' IconButtonProps={{ onClick: handleExpandButtonOnClick }} > - <div className={props.classes.headingContainer}> - <Typography component='h1' variant='h4'> + <div className={classes.headingContainer}> + <Typography component='h1' variant={getHeadingVariant()} className={classes.heading}> {props.pageType === 'facetResults' && intl.get(`perspectives.${props.resultClass}.label`)} {props.pageType === 'instancePage' && intl.get(`perspectives.${props.resultClass}.instancePage.label`)} </Typography> - <IconButton className={props.classes.infoIconButton} onClick={handleExpandButtonOnClick}> - <InfoIcon className={props.classes.infoIcon} /> + <IconButton className={classes.infoIconButton} onClick={handleExpandButtonOnClick}> + <InfoIcon className={classes.infoIcon} /> </IconButton> </div> {props.pageType === 'instancePage' && - <Typography className={props.classes.label} component='h1' variant='h6'>{generateLabel()}</Typography>} + <Typography className={classes.label} component='h1' variant='h6'>{generateLabel()}</Typography>} </AccordionSummary> - <AccordionDetails - className={props.classes.content} - style={{ height: props.descriptionHeight }} - > + <AccordionDetails className={classes.expandedContent}> {props.pageType === 'facetResults' && intl.getHTML(`perspectives.${props.resultClass}.longDescription`)} {props.pageType === 'instancePage' && <> @@ -121,20 +146,17 @@ const InfoHeader = props => { </>} </AccordionDetails> </Accordion> - </Grid> + </div> ) } InfoHeader.propTypes = { - classes: PropTypes.object.isRequired, resultClass: PropTypes.string.isRequired, instanceData: PropTypes.object, pageType: PropTypes.string.isRequired, expanded: PropTypes.bool.isRequired, updateExpanded: PropTypes.func.isRequired, - descriptionHeight: PropTypes.number.isRequired + layoutConfig: PropTypes.object.isRequired } -export const InfoHeaderComponent = InfoHeader - -export default withStyles(styles)(InfoHeader) +export default InfoHeader diff --git a/src/client/components/main_layout/Main.js b/src/client/components/main_layout/Main.js index 37f882b0..7a019ee0 100644 --- a/src/client/components/main_layout/Main.js +++ b/src/client/components/main_layout/Main.js @@ -5,32 +5,33 @@ import Grid from '@material-ui/core/Grid' import Typography from '@material-ui/core/Typography' import { makeStyles } from '@material-ui/core/styles' import MainCard from './MainCard' -import bannerImage from '../../img/main_page/mmm-banner.jpg' const useStyles = makeStyles(theme => ({ - root: { - width: '100%', - marginBottom: theme.spacing(1), - [theme.breakpoints.up('md')]: { - height: 'calc(100% - 72px)', - overflow: 'auto' - } - }, - banner: { - background: `linear-gradient( rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0.45) ), url(${bannerImage})`, + root: props => ({ + [theme.breakpoints.up(props.layoutConfig.hundredPercentHeightBreakPoint)]: { + overflow: 'auto', + height: `calc(100% - ${props.layoutConfig.topBar.reducedHeight + props.layoutConfig.footer.height + theme.spacing(3.5)}px)` + }, + [theme.breakpoints.up(props.layoutConfig.reducedHeightBreakpoint)]: { + overflow: 'auto', + height: `calc(100% - ${props.layoutConfig.topBar.defaultHeight + props.layoutConfig.footer.height + theme.spacing(3.5)}px)` + }, + marginBottom: theme.spacing(5) + }), + banner: props => ({ + background: props.layoutConfig.mainPage.bannerBackround, backgroundRepeat: 'no-repeat', backgroundSize: 'cover', backgroundPosition: 'center', - height: 220, + height: props.layoutConfig.mainPage.bannerReducedHeight, [theme.breakpoints.up('xl')]: { - height: 300 + height: props.layoutConfig.mainPage.bannerDefaultHeight }, - width: '100%', boxShadow: '0 -15px 15px 0px #bdbdbd inset', display: 'flex', alignItems: 'center', justifyContent: 'center' - }, + }), bannerContent: { display: 'inline-block', color: '#fff' @@ -44,9 +45,8 @@ const useStyles = makeStyles(theme => ({ } }, layout: { - width: 'auto', - marginLeft: theme.spacing(3), - marginRight: theme.spacing(3), + marginLeft: theme.spacing(1), + marginRight: theme.spacing(1), [theme.breakpoints.up(800 + theme.spacing(6))]: { width: 800, marginLeft: 'auto', diff --git a/src/client/components/main_layout/MainCard.js b/src/client/components/main_layout/MainCard.js index 6bda297d..8db51c63 100644 --- a/src/client/components/main_layout/MainCard.js +++ b/src/client/components/main_layout/MainCard.js @@ -21,6 +21,10 @@ const useStyles = makeStyles(theme => ({ justifyContent: 'center' }, height: 228, + [theme.breakpoints.down('sm')]: { + height: 170, + maxWidth: 300 + }, [props.perspective.frontPageElement === 'card']: { height: 'inherit', maxWidth: 269, @@ -42,10 +46,7 @@ const useStyles = makeStyles(theme => ({ backgroundPosition: 'center' }, height: '100%', - width: '100%', - [theme.breakpoints.down('xs')]: { - width: '75%' - } + width: '100%' }), cardMedia: { height: 100 diff --git a/src/client/components/main_layout/PerspectiveTabs.js b/src/client/components/main_layout/PerspectiveTabs.js index b9c85339..ab0327cc 100644 --- a/src/client/components/main_layout/PerspectiveTabs.js +++ b/src/client/components/main_layout/PerspectiveTabs.js @@ -7,12 +7,19 @@ import { Link } from 'react-router-dom' import Paper from '@material-ui/core/Paper' import intl from 'react-intl-universal' -const styles = () => ({ +const styles = theme => ({ root: { flexGrow: 1, borderBottomLeftRadius: 0, borderBottomRightRadius: 0 - } + }, + tabRoot: { + paddingTop: theme.spacing(0.5), + paddingBottom: theme.spacing(0.5) + }, + tabLabelIcon: props => ({ + minHeight: props.layoutConfig.tabHeight + }) }) /** @@ -65,6 +72,10 @@ class PerspectiveTabs extends React.Component { > {tabs.map(tab => <Tab + classes={{ + root: classes.tabRoot, + labelIcon: classes.tabLabelIcon + }} key={tab.id} icon={tab.icon} label={intl.get(`tabs.${tab.id}`)} @@ -83,7 +94,8 @@ PerspectiveTabs.propTypes = { classes: PropTypes.object.isRequired, routeProps: PropTypes.object.isRequired, tabs: PropTypes.array.isRequired, - screenSize: PropTypes.string.isRequired + screenSize: PropTypes.string.isRequired, + layoutConfig: PropTypes.object.isRequired } export const PerspectiveTabsComponent = PerspectiveTabs diff --git a/src/client/components/perspectives/sampo/FacetedSearchPerspective.js b/src/client/components/perspectives/sampo/FacetedSearchPerspective.js index 58059076..8998dc5e 100644 --- a/src/client/components/perspectives/sampo/FacetedSearchPerspective.js +++ b/src/client/components/perspectives/sampo/FacetedSearchPerspective.js @@ -139,7 +139,8 @@ FacetedSearchPerspective.propTypes = { /** * Root url of the application. */ - rootUrl: PropTypes.string.isRequired + rootUrl: PropTypes.string.isRequired, + layoutConfig: PropTypes.object.isRequired } export default FacetedSearchPerspective diff --git a/src/client/components/perspectives/sampo/Footer.js b/src/client/components/perspectives/sampo/Footer.js index 3466d28e..8adb70ca 100644 --- a/src/client/components/perspectives/sampo/Footer.js +++ b/src/client/components/perspectives/sampo/Footer.js @@ -2,28 +2,22 @@ import React from 'react' import Paper from '@material-ui/core/Paper' import PropTypes from 'prop-types' import Grid from '@material-ui/core/Grid' -import { withStyles } from '@material-ui/core/styles' +import { makeStyles } from '@material-ui/core/styles' 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 styles = theme => ({ +const useStyles = makeStyles(theme => ({ root: { - position: 'absolute', - [theme.breakpoints.down('sm')]: { - display: 'none' - }, - bottom: 0, - left: 0, + display: 'block', boxShadow: '0 -20px 20px -20px #333', - width: '100%', borderRadius: 0 }, - layout: { - width: 'auto', - // height: 115, for two row footer - marginTop: theme.spacing(1), - marginBottom: theme.spacing(1), + layout: props => ({ + [theme.breakpoints.up(props.layoutConfig.hundredPercentHeightBreakPoint)]: { + height: props.layoutConfig.footer.height + // height: 115, for two row footer + }, marginLeft: theme.spacing(2), marginRight: theme.spacing(2), [theme.breakpoints.up(1500 + theme.spacing(6))]: { @@ -31,7 +25,7 @@ const styles = theme => ({ marginLeft: 'auto', marginRight: 'auto' } - }, + }), logoContainer: { display: 'flex', alignItems: 'center', @@ -49,17 +43,17 @@ const styles = theme => ({ heldigLogo: { height: 33 } -}) +})) /** * A component for creating a footer. The logos are imported inside this component. */ const Footer = props => { - const { classes } = props + const classes = useStyles(props) return ( <Paper className={classes.root}> - <Grid container className={classes.layout}> - <Grid container spacing={3} item xs={12}> + <div className={classes.layout}> + <Grid container spacing={3}> <Grid item xs className={classes.logoContainer}> <a href='https://www.aalto.fi/en/school-of-science' target='_blank' rel='noopener noreferrer'> <img className={classes.aaltoLogo} src={aaltoLogo} alt='logo' /> @@ -76,18 +70,13 @@ const Footer = props => { </a> </Grid> </Grid> - </Grid> + </div> </Paper> ) } Footer.propTypes = { - /** - * Material-UI styles. - */ - classes: PropTypes.object.isRequired + layoutConfig: PropTypes.object.isRequired } -export const FooterComponent = Footer - -export default withStyles(styles)(Footer) +export default Footer diff --git a/src/client/components/perspectives/sampo/InstanceHomePage.js b/src/client/components/perspectives/sampo/InstanceHomePage.js index 6d96e2b8..f01f8bdc 100644 --- a/src/client/components/perspectives/sampo/InstanceHomePage.js +++ b/src/client/components/perspectives/sampo/InstanceHomePage.js @@ -21,11 +21,12 @@ const styles = () => ({ width: '100%', height: '100%' }, - content: { + content: props => ({ + padding: 0, width: '100%', - height: 'calc(100% - 72px)', + height: `calc(100% - ${props.layoutConfig.tabHeight}px)`, overflow: 'auto' - }, + }), spinnerContainer: { display: 'flex', width: '100%', @@ -151,7 +152,7 @@ class InstanceHomePage extends React.Component { } render = () => { - const { classes, perspectiveState, perspectiveConfig, rootUrl, screenSize } = this.props + const { classes, perspectiveState, perspectiveConfig, rootUrl, screenSize, layoutConfig } = this.props const { instanceTableData, fetching } = perspectiveState const resultClass = perspectiveConfig.id const hasTableData = this.hasTableData() @@ -161,6 +162,7 @@ class InstanceHomePage extends React.Component { routeProps={this.props.routeProps} tabs={perspectiveConfig.instancePageTabs} screenSize={screenSize} + layoutConfig={layoutConfig} /> <Paper square className={classes.content}> {fetching && !hasTableData && @@ -188,6 +190,7 @@ class InstanceHomePage extends React.Component { data={instanceTableData} properties={this.getVisibleRows(perspectiveState.properties)} screenSize={screenSize} + layoutConfig={layoutConfig} />} /> <Route @@ -206,6 +209,7 @@ class InstanceHomePage extends React.Component { optimize={1.2} style={cytoscapeStyle} layout={coseLayout} + layoutConfig={layoutConfig} />} /> <Route @@ -224,6 +228,7 @@ class InstanceHomePage extends React.Component { style={cytoscapeStyle} layout={coseLayout} preprocess={preprocess} + layoutConfig={layoutConfig} />} /> <Route @@ -241,6 +246,7 @@ class InstanceHomePage extends React.Component { xaxisTitle='Year' yaxisTitle='Number of letters' resultClass='emloSentReceived' + layoutConfig={layoutConfig} />} /> <Route @@ -261,6 +267,7 @@ class InstanceHomePage extends React.Component { clearGeoJSONLayers={this.props.clearGeoJSONLayers} fetchByURI={this.props.fetchByURI} showError={this.props.showError} + layoutConfig={layoutConfig} />} /> <Route @@ -270,6 +277,7 @@ class InstanceHomePage extends React.Component { sparqlQuery={this.props.sparqlQuery} pageType='instancePage' id={instanceTableData.id} + layoutConfig={layoutConfig} />} /> </>} @@ -359,7 +367,8 @@ InstanceHomePage.propTypes = { /** * Root url of the application. */ - rootUrl: PropTypes.string.isRequired + rootUrl: PropTypes.string.isRequired, + layoutConfig: PropTypes.object.isRequired } export const InstanceHomePageComponent = InstanceHomePage diff --git a/src/client/components/perspectives/sampo/Perspective1.js b/src/client/components/perspectives/sampo/Perspective1.js index e110f258..f81bc0fb 100644 --- a/src/client/components/perspectives/sampo/Perspective1.js +++ b/src/client/components/perspectives/sampo/Perspective1.js @@ -31,6 +31,7 @@ const Perspective1 = props => { routeProps={props.routeProps} tabs={props.perspective.tabs} screenSize={props.screenSize} + layoutConfig={props.layoutConfig} /> <Route exact path={`${rootUrl}/${perspective.id}/faceted-search`} @@ -50,12 +51,15 @@ const Perspective1 = props => { sortResults={props.sortResults} routeProps={routeProps} rootUrl={rootUrl} + layoutConfig={props.layoutConfig} />} /> <Route path={`${rootUrl}/${perspective.id}/faceted-search/production_places`} render={() => <LeafletMap + mapBoxAccessToken={MAPBOX_ACCESS_TOKEN} + mapBoxStyle={MAPBOX_STYLE} center={props.perspectiveState.maps.placesMsProduced.center} zoom={props.perspectiveState.maps.placesMsProduced.zoom} // center={[60.187, 24.821]} @@ -88,6 +92,7 @@ const Perspective1 = props => { // customMapControl layerConfigs={layerConfigs} infoHeaderExpanded={props.perspectiveState.facetedSearchHeaderExpanded} + layoutConfig={props.layoutConfig} // activeLayers={[ // 'WFS_MV_KulttuuriymparistoSuojellut:Muinaisjaannokset_alue', // 'WFS_MV_KulttuuriymparistoSuojellut:Muinaisjaannokset_piste', @@ -112,12 +117,15 @@ const Perspective1 = props => { mapBoxAccessToken={MAPBOX_ACCESS_TOKEN} mapBoxStyle={MAPBOX_STYLE} updateMapBounds={props.updateMapBounds} + layoutConfig={props.layoutConfig} />} /> <Route path={`${rootUrl}/${perspective.id}/faceted-search/last_known_locations`} render={() => <LeafletMap + mapBoxAccessToken={MAPBOX_ACCESS_TOKEN} + mapBoxStyle={MAPBOX_STYLE} center={props.perspectiveState.maps.lastKnownLocations.center} zoom={props.perspectiveState.maps.lastKnownLocations.zoom} results={props.perspectiveState.results} @@ -147,6 +155,7 @@ const Perspective1 = props => { layerControlExpanded={layerControlExpanded} layerConfigs={layerConfigs} infoHeaderExpanded={props.perspectiveState.facetedSearchHeaderExpanded} + layoutConfig={props.layoutConfig} />} /> <Route @@ -180,6 +189,7 @@ const Perspective1 = props => { showTooltips mapBoxAccessToken={MAPBOX_ACCESS_TOKEN} mapBoxStyle={MAPBOX_STYLE} + layoutConfig={props.layoutConfig} />} /> <Route @@ -202,6 +212,7 @@ const Perspective1 = props => { stroke={{ width: 2 }} resultClass='productionTimespanLineChart' facetClass='perspective1' + layoutConfig={props.layoutConfig} />} /> <Route @@ -237,6 +248,7 @@ const Perspective1 = props => { }} resultClass='eventLineChart' facetClass='perspective1' + layoutConfig={props.layoutConfig} />} /> <Route @@ -256,6 +268,7 @@ const Perspective1 = props => { layout={coseLayout} preprocess={preprocess} pageType='facetResults' + layoutConfig={props.layoutConfig} />} /> <Route @@ -268,6 +281,7 @@ const Perspective1 = props => { pageType='facetResults' fetchPaginatedResults={props.fetchPaginatedResults} updatePage={props.updatePage} + layoutConfig={props.layoutConfig} />} /> </> @@ -362,7 +376,8 @@ Perspective1.propTypes = { /** * Root url of the application. */ - rootUrl: PropTypes.string.isRequired + rootUrl: PropTypes.string.isRequired, + layoutConfig: PropTypes.object.isRequired } export default Perspective1 diff --git a/src/client/components/perspectives/sampo/Perspective2.js b/src/client/components/perspectives/sampo/Perspective2.js index 119eaac1..a125b74f 100644 --- a/src/client/components/perspectives/sampo/Perspective2.js +++ b/src/client/components/perspectives/sampo/Perspective2.js @@ -13,6 +13,7 @@ const Perspective2 = props => { routeProps={props.routeProps} tabs={props.perspective.tabs} screenSize={props.screenSize} + layoutConfig={props.layoutConfig} /> <Route exact path={`${rootUrl}/${perspective.id}/faceted-search`} @@ -32,6 +33,7 @@ const Perspective2 = props => { sortResults={props.sortResults} routeProps={routeProps} rootUrl={rootUrl} + layoutConfig={props.layoutConfig} />} /> <Route @@ -44,6 +46,7 @@ const Perspective2 = props => { pageType='facetResults' fetchPaginatedResults={props.fetchPaginatedResults} updatePage={props.updatePage} + layoutConfig={props.layoutConfig} />} /> </> @@ -138,7 +141,8 @@ Perspective2.propTypes = { /** * Root url of the application. */ - rootUrl: PropTypes.string.isRequired + rootUrl: PropTypes.string.isRequired, + layoutConfig: PropTypes.object.isRequired } export default Perspective2 diff --git a/src/client/components/perspectives/sampo/Perspective3.js b/src/client/components/perspectives/sampo/Perspective3.js index 3fa7f134..5fb6d5b2 100644 --- a/src/client/components/perspectives/sampo/Perspective3.js +++ b/src/client/components/perspectives/sampo/Perspective3.js @@ -5,6 +5,10 @@ import PerspectiveTabs from '../../main_layout/PerspectiveTabs' import ResultTable from '../../facet_results/ResultTable' import Export from '../../facet_results/Export' import LeafletMap from '../../facet_results/LeafletMap' +import { + MAPBOX_ACCESS_TOKEN, + MAPBOX_STYLE +} from '../../../configs/sampo/GeneralConfig' import { layerConfigs, createPopUpContentMMM } from '../../../configs/sampo/Leaflet/LeafletConfig' const Perspective3 = props => { @@ -37,12 +41,15 @@ const Perspective3 = props => { sortResults={props.sortResults} routeProps={routeProps} rootUrl={rootUrl} + layoutConfig={props.layoutConfig} />} /> <Route path={`${rootUrl}/${perspective.id}/faceted-search/map`} render={() => <LeafletMap + mapBoxAccessToken={MAPBOX_ACCESS_TOKEN} + mapBoxStyle={MAPBOX_STYLE} center={props.perspectiveState.maps.placesEvents.center} zoom={props.perspectiveState.maps.placesEvents.zoom} results={props.perspectiveState.results} @@ -71,6 +78,7 @@ const Perspective3 = props => { layerControlExpanded={layerControlExpanded} layerConfigs={layerConfigs} infoHeaderExpanded={props.perspectiveState.facetedSearchHeaderExpanded} + layoutConfig={props.layoutConfig} />} /> <Route @@ -83,6 +91,7 @@ const Perspective3 = props => { pageType='facetResults' fetchPaginatedResults={props.fetchPaginatedResults} updatePage={props.updatePage} + layoutConfig={props.layoutConfig} />} /> </> @@ -177,7 +186,8 @@ Perspective3.propTypes = { /** * Root url of the application. */ - rootUrl: PropTypes.string.isRequired + rootUrl: PropTypes.string.isRequired, + layoutConfig: PropTypes.object.isRequired } export default Perspective3 diff --git a/src/client/components/perspectives/sampo/TopBar.js b/src/client/components/perspectives/sampo/TopBar.js index eac950ff..0015a85a 100644 --- a/src/client/components/perspectives/sampo/TopBar.js +++ b/src/client/components/perspectives/sampo/TopBar.js @@ -17,31 +17,34 @@ 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, feedbackLink } from '../../../configs/sampo/GeneralConfig' -const useStyles = makeStyles((theme) => ({ +const useStyles = makeStyles(theme => ({ grow: { flexGrow: 1 }, - toolbar: { + 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: { + }), + sectionDesktop: props => ({ display: 'none', - [theme.breakpoints.up('lg')]: { + [theme.breakpoints.up(props.layoutConfig.topBar.mobileMenuBreakpoint)]: { display: 'flex' } - }, + }), link: { textDecoration: 'none' }, - sectionMobile: { + sectionMobile: props => ({ display: 'flex', - [theme.breakpoints.up('lg')]: { + [theme.breakpoints.up(props.layoutConfig.topBar.mobileMenuBreakpoint)]: { display: 'none' } - }, + }), homeButtonText: { whiteSpace: 'nowrap', [theme.breakpoints.down('sm')]: { @@ -61,12 +64,12 @@ const useStyles = makeStyles((theme) => ({ marginRight: theme.spacing(1), borderLeft: '2px solid white' }, - secoLogo: { + secoLogo: props => ({ marginLeft: theme.spacing(1), - [theme.breakpoints.down('md')]: { + [theme.breakpoints.down(props.layoutConfig.topBar.mobileMenuBreakpoint)]: { display: 'none' } - } + }) })) /** @@ -77,7 +80,7 @@ const TopBar = props => { const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React.useState(null) const isMobileMenuOpen = Boolean(mobileMoreAnchorEl) const { perspectives, currentLocale, availableLocales, rootUrl } = props - const classes = useStyles() + const classes = useStyles(props) const handleMobileMenuOpen = event => setMobileMoreAnchorEl(event.currentTarget) const handleMobileMenuClose = () => setMobileMoreAnchorEl(null) const clientFSMode = props.location.pathname.indexOf('clientFS') !== -1 @@ -166,7 +169,7 @@ const TopBar = props => { <Divider /> {renderMobileMenuItem({ id: 'feedback', - externalUrl: feedbackLink, + externalUrl: props.layoutConfig.topBar.feedbackLink, label: intl.get('topBar.feedback') })} {/* <MenuItem @@ -212,8 +215,8 @@ const TopBar = props => { {/* 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}> + <AppBar position='static'> + <Toolbar className={classes.topBarToolbar}> <Button component={AdapterLink} to='/'> <Typography className={classes.homeButtonText} variant='h6'>{intl.get('appTitle.short')}</Typography> </Button> @@ -230,7 +233,7 @@ const TopBar = props => { <div className={classes.appBarDivider} /> {renderDesktopTopMenuItem({ id: 'feedback', - externalUrl: feedbackLink, + externalUrl: props.layoutConfig.topBar.feedbackLink, label: intl.get('topBar.feedback') })} <TopBarInfoButton rootUrl={props.rootUrl} /> @@ -243,7 +246,7 @@ const TopBar = props => { > {intl.get('topBar.instructions')} </Button> - {showLanguageButton && + {props.layoutConfig.topBar.showLanguageButton && <TopBarLanguageButton currentLocale={currentLocale} availableLocales={availableLocales} @@ -260,7 +263,7 @@ const TopBar = props => { <Button><img src={secoLogo} /></Button> </a> <div className={classes.sectionMobile}> - {showLanguageButton && + {props.layoutConfig.topBar.showLanguageButton && <TopBarLanguageButton currentLocale={currentLocale} availableLocales={availableLocales} @@ -314,7 +317,8 @@ TopBar.propTypes = { /** * Root url of the application. */ - rootUrl: PropTypes.string.isRequired + rootUrl: PropTypes.string.isRequired, + layoutConfig: PropTypes.object.isRequired } export default TopBar diff --git a/src/client/components/perspectives/sampo/client_fs/ClientFSMain.js b/src/client/components/perspectives/sampo/client_fs/ClientFSMain.js index a79f7549..4a1c82cc 100644 --- a/src/client/components/perspectives/sampo/client_fs/ClientFSMain.js +++ b/src/client/components/perspectives/sampo/client_fs/ClientFSMain.js @@ -5,20 +5,12 @@ import Typography from '@material-ui/core/Typography' import Paper from '@material-ui/core/Paper' import intl from 'react-intl-universal' import bgImage from '../../../../img/main_page/bg2.jpg' -import Footer from '../Footer' const styles = theme => ({ - root: { + paper: { height: '100%', - // width: '100%', display: 'flex', - // alignItems: 'center', justifyContent: 'center', - // paddingTop: theme.spacing(3), - // paddingLeft: theme.spacing(3), - // paddingRight: theme.spacing(3), - // borderBottomLeftRadius: 0, - // borderBottomRightRadius: 0, backgroundImage: `url(${bgImage})`, backgroundPosition: 'center', backgroundRepeat: 'no-repeat', @@ -48,30 +40,27 @@ const styles = theme => ({ const ClientFSMain = props => { const { classes } = props return ( - <> - <Paper className={classes.root}> - <div className={classes.content}> - <div className={classes.textContainer}> - <Typography className={classes.frontPageHeading} component='h1' variant='h3' align='center' color='textPrimary' gutterBottom> - {intl.getHTML('appTitle.long')} - </Typography> - <Typography className={classes.frontPageText} variant='h5' align='left' color='textPrimary' paragraph> - {intl.get('appDescription1')} - </Typography> - <Typography className={classes.frontPageText} variant='h5' align='left' color='textPrimary' paragraph> - {intl.get('appDescription2')} - </Typography> - <Typography className={classes.frontPageText} variant='h5' align='left' color='textPrimary' paragraph> - {intl.get('appDescription3')} - </Typography> - <Typography className={classes.frontPageText} variant='h5' align='left' color='textPrimary' paragraph> - {intl.get('appDescription4')} - </Typography> - </div> + <Paper className={classes.paper}> + <div className={classes.content}> + <div className={classes.textContainer}> + <Typography className={classes.frontPageHeading} component='h1' variant='h3' align='center' color='textPrimary' gutterBottom> + {intl.getHTML('appTitle.long')} + </Typography> + <Typography className={classes.frontPageText} variant='h5' align='left' color='textPrimary' paragraph> + {intl.get('appDescription1')} + </Typography> + <Typography className={classes.frontPageText} variant='h5' align='left' color='textPrimary' paragraph> + {intl.get('appDescription2')} + </Typography> + <Typography className={classes.frontPageText} variant='h5' align='left' color='textPrimary' paragraph> + {intl.get('appDescription3')} + </Typography> + <Typography className={classes.frontPageText} variant='h5' align='left' color='textPrimary' paragraph> + {intl.get('appDescription4')} + </Typography> </div> - </Paper> - <Footer /> - </> + </div> + </Paper> ) } diff --git a/src/client/components/perspectives/sampo/client_fs/ClientFSPerspective.js b/src/client/components/perspectives/sampo/client_fs/ClientFSPerspective.js index a381f1b0..6feea1e7 100644 --- a/src/client/components/perspectives/sampo/client_fs/ClientFSPerspective.js +++ b/src/client/components/perspectives/sampo/client_fs/ClientFSPerspective.js @@ -9,11 +9,14 @@ import ResultInfo from '../../../facet_results/ResultInfo' import VirtualizedTable from '../../../facet_results/VirtualizedTable' import Pie from '../../../facet_results/Pie.js' import CSVButton from '../../../facet_results/CSVButton' -import Footer from '../Footer' +import { + MAPBOX_ACCESS_TOKEN, + MAPBOX_STYLE +} from '../../../../configs/sampo/GeneralConfig' import { createPopUpContentNameSampo, layerConfigs } from '../../../../configs/sampo/Leaflet/LeafletConfig' const ClientFSPerspective = props => { - const { rootUrl, perspective, screenSize, clientFSState } = props + const { rootUrl, perspective, screenSize, clientFSState, layoutConfig } = props const { maps } = clientFSState const { clientFSMapClusters, clientFSMapMarkers } = maps // console.log(clientFSMapClusters) @@ -26,6 +29,7 @@ const ClientFSPerspective = props => { routeProps={props.routeProps} tabs={perspective.tabs} screenSize={props.screenSize} + layoutConfig={layoutConfig} /> <Route exact path={`${rootUrl}/${perspective.id}/federated-search`} @@ -39,12 +43,15 @@ const ClientFSPerspective = props => { clientFSState={props.clientFSState} clientFSSortResults={props.clientFSSortResults} perspectiveID={perspective.id} + layoutConfig={layoutConfig} />} /> <Route path={`${rootUrl}/${perspective.id}/federated-search/map_clusters`} render={() => <LeafletMap + mapBoxAccessToken={MAPBOX_ACCESS_TOKEN} + mapBoxStyle={MAPBOX_STYLE} center={clientFSMapClusters.center} zoom={clientFSMapClusters.zoom} results={props.clientFSResults} @@ -65,6 +72,7 @@ const ClientFSPerspective = props => { layerControlExpanded={layerControlExpanded} layerConfigs={layerConfigs} updateMapBounds={props.updateMapBounds} + layoutConfig={layoutConfig} />} /> <Route @@ -75,6 +83,8 @@ const ClientFSPerspective = props => { } else { return ( <LeafletMap + mapBoxAccessToken={MAPBOX_ACCESS_TOKEN} + mapBoxStyle={MAPBOX_STYLE} center={clientFSMapMarkers.center} zoom={clientFSMapMarkers.zoom} results={props.clientFSResults} @@ -95,6 +105,7 @@ const ClientFSPerspective = props => { layerControlExpanded={layerControlExpanded} layerConfigs={layerConfigs} updateMapBounds={props.updateMapBounds} + layoutConfig={layoutConfig} /> ) } @@ -105,17 +116,17 @@ const ClientFSPerspective = props => { render={() => <Pie data={props.clientFSResults} - groupBy={props.clientFS.groupBy} - groupByLabel={props.clientFS.groupByLabel} - query={props.clientFS.query} + groupBy={props.clientFSState.groupBy} + groupByLabel={props.clientFSState.groupByLabel} + query={props.clientFSState.query} + layoutConfig={layoutConfig} />} /> <Route path={`${rootUrl}/${perspective.id}/federated-search/download`} render={() => - <CSVButton results={props.clientFSResults} />} + <CSVButton results={props.clientFSResults} layoutConfig={layoutConfig} />} /> - <Footer /> </> ) } diff --git a/src/client/configs/sampo/GeneralConfig.js b/src/client/configs/sampo/GeneralConfig.js index d424c816..7c251412 100644 --- a/src/client/configs/sampo/GeneralConfig.js +++ b/src/client/configs/sampo/GeneralConfig.js @@ -1,9 +1,9 @@ +import bannerImage from '../../img/main_page/mmm-banner.jpg' + export const rootUrl = '' export const defaultLocale = 'en' -export const showLanguageButton = true - export const readTranslationsFromGoogleSheets = false export const MAPBOX_ACCESS_TOKEN = 'pk.eyJ1IjoiZWtrb25lbiIsImEiOiJja2FkbGxiY2owMDZkMnFxcGVqNTZ0dmk2In0.6keLTN8VveJkM5y4_OFmUw' // https://docs.mapbox.com/accounts/overview/tokens/ @@ -28,4 +28,38 @@ export const SLIDER_DURATION = { doubleSpeed: 300 } -export const feedbackLink = 'https://link.webropolsurveys.com/' +export const layoutConfig = { + hundredPercentHeightBreakPoint: 'md', + reducedHeightBreakpoint: 'lg', + tabHeight: 58, + paginationToolbarHeight: 37, + topBar: { + showLanguageButton: true, + feedbackLink: 'https://link.webropolsurveys.com/', + reducedHeight: 44, + defaultHeight: 64, + mobileMenuBreakpoint: 1360 + }, + mainPage: { + bannerBackround: `linear-gradient( rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0.45) ), url(${bannerImage})`, + bannerDefaultHeight: 300, + bannerReducedHeight: 220 + }, + infoHeader: { + default: { + height: 49, + expandedContentHeight: 160, + headingVariant: 'h4', + infoIconFontSize: 40 + }, + reducedHeight: { + height: 40, + expandedContentHeight: 100, + headingVariant: 'h6', + infoIconFontSize: 32 + } + }, + footer: { + height: 64 + } +} diff --git a/src/client/configs/sampo/Leaflet/LeafletConfig.js b/src/client/configs/sampo/Leaflet/LeafletConfig.js index 0e997a8e..6629d360 100644 --- a/src/client/configs/sampo/Leaflet/LeafletConfig.js +++ b/src/client/configs/sampo/Leaflet/LeafletConfig.js @@ -215,6 +215,9 @@ const createArchealogicalSiteColor = feature => { } /* + FHA spatial data general documentation: + https://www.museovirasto.fi/en/services-and-guidelines/data-systems/kulttuuriympaeristoen-tietojaerjestelmae/kulttuuriympaeristoen-paikkatietoaineistot + FHA WFS services: https://kartta.nba.fi/arcgis/rest/services/WFS/MV_KulttuuriymparistoSuojellut/MapServer https://kartta.nba.fi/arcgis/rest/services/WFS/MV_Kulttuuriymparisto/MapServer/ diff --git a/src/client/configs/sampo/PerspectiveConfig.js b/src/client/configs/sampo/PerspectiveConfig.js index 6b09b29c..f0aaf623 100644 --- a/src/client/configs/sampo/PerspectiveConfig.js +++ b/src/client/configs/sampo/PerspectiveConfig.js @@ -19,7 +19,6 @@ export const perspectiveConfig = [ { id: 'perspective1', frontPageImage: manuscriptsImage, - perspectiveDescHeight: 160, defaultActiveFacets: new Set([]), tabs: [ { @@ -89,7 +88,6 @@ export const perspectiveConfig = [ { id: 'perspective2', frontPageImage: worksImage, - perspectiveDescHeight: 160, defaultActiveFacets: new Set(['prefLabel']), tabs: [ { @@ -119,7 +117,6 @@ export const perspectiveConfig = [ { id: 'perspective3', frontPageImage: eventsImage, - perspectiveDescHeight: 160, defaultActiveFacets: new Set(['prefLabel']), tabs: [ { @@ -157,7 +154,6 @@ export const perspectiveConfig = [ id: 'finds', isHidden: true, frontPageImage: null, - perspectiveDescHeight: 160, defaultActiveFacets: new Set(['prefLabel']), tabs: [ { @@ -198,7 +194,7 @@ export const perspectiveConfig = [ id: 'emloActors', isHidden: true, frontPageImage: null, - perspectiveDescHeight: 160, + defaultActiveFacets: new Set(['prefLabel']), tabs: [ { @@ -244,7 +240,6 @@ export const perspectiveConfig = [ id: 'emloLetters', isHidden: true, frontPageImage: null, - perspectiveDescHeight: 160, defaultActiveFacets: new Set(['prefLabel']), tabs: [ { @@ -285,7 +280,6 @@ export const perspectiveConfig = [ id: 'emloPlaces', isHidden: true, frontPageImage: null, - perspectiveDescHeight: 160, defaultActiveFacets: new Set(['prefLabel']), tabs: [ { @@ -316,7 +310,6 @@ export const perspectiveConfig = [ id: 'hellerau', isHidden: true, frontPageImage: null, - perspectiveDescHeight: 160, defaultActiveFacets: new Set(['prefLabel']), tabs: [ { diff --git a/src/client/containers/SemanticPortal.js b/src/client/containers/SemanticPortal.js index 85296f25..bfe4f6fb 100644 --- a/src/client/containers/SemanticPortal.js +++ b/src/client/containers/SemanticPortal.js @@ -33,7 +33,7 @@ import Footer from '../components/perspectives/sampo/Footer' import KnowledgeGraphMetadataTable from '../components/perspectives/sampo/KnowledgeGraphMetadataTable' import { perspectiveConfig } from '../configs/sampo/PerspectiveConfig' import { perspectiveConfigOnlyInfoPages } from '../configs/sampo/PerspectiveConfigOnlyInfoPages' -import { rootUrl } from '../configs/sampo/GeneralConfig' +import { rootUrl, layoutConfig } from '../configs/sampo/GeneralConfig' // ** Portal specific components and configs end ** import { @@ -73,93 +73,66 @@ import { filterResults } from '../selectors' const useStyles = makeStyles(theme => ({ root: { - flexGrow: 1, - // Set app height for different screen sizes - height: 'auto', - [theme.breakpoints.up('md')]: { - height: '100%' - }, /* Background color of the app. In order to use both 'auto' and '100%' heights, bg-color needs to be defined also in index.html (for #app and #root elements) */ - backgroundColor: '#bdbdbd' - }, - flex: { - flexGrow: 1 - }, - appFrame: { - height: '100%', - zIndex: 1, - overflow: 'hidden', - position: 'relative', - display: 'flex', - width: '100%' - }, - mainContainer: { - height: 'auto', - overflow: 'auto', - [theme.breakpoints.up('md')]: { - height: 'calc(100% - 64px)' // 100% - app bar - padding - }, - [theme.breakpoints.down('sm')]: { - marginTop: 56 // app bar - }, - [theme.breakpoints.up('sm')]: { - marginTop: 64 // app bar + backgroundColor: '#bdbdbd', + [theme.breakpoints.up(layoutConfig.hundredPercentHeightBreakPoint)]: { + overflow: 'hidden', + height: '100%' } }, mainContainerClientFS: { - height: 'auto', - [theme.breakpoints.up('md')]: { - height: 'calc(100% - 144px)' // 100% - app bar - padding * 2 - }, - [theme.breakpoints.down('sm')]: { - marginTop: 64 // app bar + marginTop: theme.spacing(1), + marginBottom: theme.spacing(3), + [theme.breakpoints.up(layoutConfig.hundredPercentHeightBreakPoint)]: { + height: `calc(100% - ${layoutConfig.topBar.reducedHeight + layoutConfig.footer.height + theme.spacing(0.5)}px)`, + marginBottom: theme.spacing(1) }, - [theme.breakpoints.up('sm')]: { - marginTop: 72 // app bar + padding + [theme.breakpoints.up(layoutConfig.reducedHeightBreakpoint)]: { + height: `calc(100% - ${layoutConfig.topBar.defaultHeight + layoutConfig.footer.height + theme.spacing(0.5)}px)`, + marginBottom: theme.spacing(1) } }, textPageContainer: { - width: '100%', - paddingBottom: theme.spacing(1), - paddingLeft: theme.spacing(1), - paddingRight: theme.spacing(1), - [theme.breakpoints.up('md')]: { - height: 'calc(100% - 80px)' - }, - [theme.breakpoints.down('sm')]: { - marginTop: 64 // app bar + padding + 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('sm')]: { - marginTop: 72 // app bar + padding + [theme.breakpoints.up(layoutConfig.reducedHeightBreakpoint)]: { + height: `calc(100% - ${layoutConfig.topBar.defaultHeight + theme.spacing(1.5)}px)` } }, perspectiveContainer: { - height: 'auto', - [theme.breakpoints.up('md')]: { - height: 'calc(100% - 130px)' + margin: theme.spacing(0.5), + width: `calc(100% - ${theme.spacing(1)}px)`, + [theme.breakpoints.up(layoutConfig.hundredPercentHeightBreakPoint)]: { + height: `calc(100% - ${layoutConfig.topBar.reducedHeight + layoutConfig.infoHeader.reducedHeight.height + theme.spacing(1.5)}px)` }, - padding: theme.spacing(1), - [theme.breakpoints.down('sm')]: { - marginTop: 126 // app bar + header - }, - [theme.breakpoints.up('sm')]: { - marginTop: 130 // app bar + header + [theme.breakpoints.up(layoutConfig.reducedHeightBreakpoint)]: { + height: `calc(100% - ${layoutConfig.topBar.defaultHeight + layoutConfig.infoHeader.default.height + theme.spacing(1.5)}px)` } }, perspectiveContainerHeaderExpanded: { - height: 'auto', - [theme.breakpoints.up('md')]: { - height: 'calc(100% - 316px)' + margin: theme.spacing(0.5), + width: `calc(100% - ${theme.spacing(1)}px)`, + [theme.breakpoints.up(layoutConfig.hundredPercentHeightBreakPoint)]: { + height: `calc(100% - ${ + layoutConfig.topBar.reducedHeight + + layoutConfig.infoHeader.reducedHeight.height + + layoutConfig.infoHeader.reducedHeight.expandedContentHeight + + theme.spacing(3.5) + }px)` }, - padding: theme.spacing(1), - [theme.breakpoints.down('sm')]: { - marginTop: 308 // app bar + header - }, - [theme.breakpoints.up('sm')]: { - marginTop: 316 // app bar + header + [theme.breakpoints.up(layoutConfig.reducedHeightBreakpoint)]: { + height: `calc(100% - ${ + layoutConfig.topBar.defaultHeight + + layoutConfig.infoHeader.default.height + + layoutConfig.infoHeader.default.expandedContentHeight + + theme.spacing(3.5) + }px)` } }, // perspective container is divided into two columns: @@ -168,22 +141,22 @@ const useStyles = makeStyles(theme => ({ [theme.breakpoints.up('md')]: { height: '100%' }, + [theme.breakpoints.down('sm')]: { + paddingRight: '0px !important' + }, overflow: 'auto', + paddingLeft: '0px !important', paddingTop: '0px !important', paddingBottom: '0px !important' }, facetBarContainerClientFS: { - height: 'auto', - width: '100%', - [theme.breakpoints.up('md')]: { - height: '100%', - overflow: 'auto' - }, - [theme.breakpoints.down('md')]: { - marginBottom: theme.spacing(1) - }, + overflow: 'auto', paddingLeft: theme.spacing(0.5), - paddingRight: theme.spacing(0.5) + paddingRight: theme.spacing(0.5), + [theme.breakpoints.up(layoutConfig.hundredPercentHeightBreakPoint)]: { + minHeight: 'initial', + height: `calc(100% - ${theme.spacing(2)}px)` + } }, resultsContainer: { height: 'auto', @@ -192,60 +165,58 @@ const useStyles = makeStyles(theme => ({ }, paddingTop: '0px !important', paddingBottom: '0px !important', + paddingRight: '0px !important', [theme.breakpoints.down('sm')]: { - marginTop: theme.spacing(1) + paddingLeft: '0px !important', + marginBottom: theme.spacing(1), + marginTop: theme.spacing(0.5) } }, resultsContainerClientFS: { - height: 800, - [theme.breakpoints.down('md')]: { - marginBottom: 8, - width: 'calc(100% - 2px)' - }, - [theme.breakpoints.up('md')]: { - height: '100%' + minHeight: 500, + [theme.breakpoints.up(layoutConfig.hundredPercentHeightBreakPoint)]: { + minHeight: 'initial', + height: `calc(100% - ${theme.spacing(2)}px)` }, - paddingTop: '0px !important', paddingBottom: '0px !important', paddingRight: theme.spacing(0.5), paddingLeft: theme.spacing(0.5) - // [theme.breakpoints.down('sm')]: { - // marginTop: theme.spacing(1) - // } }, instancePageContainer: { - height: 'auto', - [theme.breakpoints.up('md')]: { - height: 'calc(100% - 170px)' - }, - padding: theme.spacing(1), - [theme.breakpoints.down('sm')]: { - marginTop: 164 + margin: theme.spacing(0.5), + width: `calc(100% - ${theme.spacing(1)}px)`, + [theme.breakpoints.up(layoutConfig.hundredPercentHeightBreakPoint)]: { + height: `calc(100% - ${layoutConfig.topBar.reducedHeight + 2 * layoutConfig.infoHeader.reducedHeight.height + theme.spacing(1.5)}px)` }, - [theme.breakpoints.up('sm')]: { - marginTop: 170 + [theme.breakpoints.up(layoutConfig.reducedHeightBreakpoint)]: { + height: `calc(100% - ${layoutConfig.topBar.defaultHeight + 89 + theme.spacing(1.5)}px)` } }, instancePageContainerHeaderExpanded: { - height: 'auto', - [theme.breakpoints.up('md')]: { - height: 'calc(100% - 354px)' + margin: theme.spacing(0.5), + width: `calc(100% - ${theme.spacing(1)}px)`, + [theme.breakpoints.up(layoutConfig.hundredPercentHeightBreakPoint)]: { + height: `calc(100% - ${ + layoutConfig.topBar.reducedHeight + + 2 * layoutConfig.infoHeader.reducedHeight.height + + layoutConfig.infoHeader.reducedHeight.expandedContentHeight + + theme.spacing(3.5) + }px)` }, - padding: theme.spacing(1), - [theme.breakpoints.down('sm')]: { - marginTop: 348 - }, - [theme.breakpoints.up('sm')]: { - marginTop: 354 + [theme.breakpoints.up(layoutConfig.reducedHeightBreakpoint)]: { + height: `calc(100% - ${ + layoutConfig.topBar.defaultHeight + + 89 + + layoutConfig.infoHeader.default.expandedContentHeight + + theme.spacing(3.5) + }px)` } }, instancePageContent: { - height: 'auto', - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up(layoutConfig.hundredPercentHeightBreakPoint)]: { height: '100%' }, - paddingTop: '0px !important', - paddingBottom: '0px !important' + padding: '0px !important' } })) @@ -280,118 +251,178 @@ const SemanticPortal = props => { return ( <MuiPickersUtilsProvider libInstance={moment} utils={MomentUtils} locale={props.options.currentLocale}> <div className={classes.root}> - <div className={classes.appFrame}> - <Message error={error} /> - <> - <TopBar - rootUrl={rootUrlWithLang} - search={props.fullTextSearch} - fetchFullTextResults={props.fetchFullTextResults} - clearResults={props.clearResults} - perspectives={perspectiveConfig} - currentLocale={props.options.currentLocale} - availableLocales={props.options.availableLocales} - loadLocales={props.loadLocales} - xsScreen={xsScreen} - location={props.location} - /> - <Route exact path={`${rootUrl}/`}> - <Redirect to={rootUrlWithLang} /> - </Route> - <Route - exact path={`${rootUrlWithLang}/`} - render={() => - <Grid container spacing={1} className={classes.mainContainer}> - <Main - perspectives={perspectiveConfig} + <Message error={error} /> + <> + <TopBar + rootUrl={rootUrlWithLang} + search={props.fullTextSearch} + fetchFullTextResults={props.fetchFullTextResults} + clearResults={props.clearResults} + perspectives={perspectiveConfig} + currentLocale={props.options.currentLocale} + availableLocales={props.options.availableLocales} + loadLocales={props.loadLocales} + xsScreen={xsScreen} + location={props.location} + layoutConfig={layoutConfig} + /> + <Route exact path={`${rootUrl}/`}> + <Redirect to={rootUrlWithLang} /> + </Route> + <Route + exact path={`${rootUrlWithLang}/`} + render={() => + <> + <Main + perspectives={perspectiveConfig} + screenSize={screenSize} + rootUrl={rootUrlWithLang} + layoutConfig={layoutConfig} + /> + <Footer layoutConfig={layoutConfig} /> + </>} + /> + {/* https://stackoverflow.com/a/41024944 */} + <Route + path={`${rootUrlWithLang}/`} render={({ location }) => { + if (typeof window.ga === 'function') { + window.ga('set', 'page', location.pathname + location.search) + window.ga('send', 'pageview') + } + return null + }} + /> + {/* route for full text search results */} + <Route + path={`${rootUrlWithLang}/full-text-search`} + render={routeProps => + <Grid container spacing={1} className={classes.mainContainer}> + <Grid item xs={12} className={classes.resultsContainer}> + <FullTextSearch + fullTextSearch={props.fullTextSearch} + sortFullTextResults={props.sortFullTextResults} + routeProps={routeProps} screenSize={screenSize} rootUrl={rootUrlWithLang} + layoutConfig={layoutConfig} /> - <Footer /> - </Grid>} - /> - {/* https://stackoverflow.com/a/41024944 */} - <Route - path={`${rootUrlWithLang}/`} render={({ location }) => { - if (typeof window.ga === 'function') { - window.ga('set', 'page', location.pathname + location.search) - window.ga('send', 'pageview') - } - return null - }} - /> - {/* route for full text search results */} - <Route - path={`${rootUrlWithLang}/full-text-search`} - render={routeProps => - <Grid container spacing={1} className={classes.mainContainer}> - <Grid item xs={12} className={classes.resultsContainer}> - <FullTextSearch - fullTextSearch={props.fullTextSearch} - sortFullTextResults={props.sortFullTextResults} - routeProps={routeProps} - screenSize={screenSize} - rootUrl={rootUrlWithLang} + </Grid> + </Grid>} + /> + {/* routes for faceted search perspectives */} + {perspectiveConfig.map(perspective => { + if (!has(perspective, 'externalUrl') && perspective.id !== 'placesClientFS') { + return ( + <React.Fragment key={perspective.id}> + <Route + path={`${rootUrlWithLang}/${perspective.id}/faceted-search`} + render={routeProps => { + return ( + <> + <InfoHeader + resultClass={perspective.id} + pageType='facetResults' + expanded={props[perspective.id].facetedSearchHeaderExpanded} + updateExpanded={props.updatePerspectiveHeaderExpanded} + screenSize={screenSize} + layoutConfig={layoutConfig} + /> + <Grid + container spacing={1} className={props[perspective.id].facetedSearchHeaderExpanded + ? classes.perspectiveContainerHeaderExpanded + : classes.perspectiveContainer} + > + <Grid item xs={12} md={3} className={classes.facetBarContainer}> + <FacetBar + facetedSearchMode='serverFS' + facetData={props[`${perspective.id}Facets`]} + facetDataConstrainSelf={has(props, `${perspective.id}FacetsConstrainSelf`) + ? props[`${perspective.id}FacetsConstrainSelf`] + : null} + facetResults={props[`${perspective.id}`]} + facetClass={perspective.id} + resultClass={perspective.id} + fetchingResultCount={props[perspective.id].fetchingResultCount} + resultCount={props[perspective.id].resultCount} + fetchFacet={props.fetchFacet} + fetchFacetConstrainSelf={props.fetchFacetConstrainSelf} + fetchResults={props.fetchResults} + clearFacet={props.clearFacet} + clearAllFacets={props.clearAllFacets} + fetchResultCount={props.fetchResultCount} + updateFacetOption={props.updateFacetOption} + showError={props.showError} + defaultActiveFacets={perspective.defaultActiveFacets} + rootUrl={rootUrlWithLang} + screenSize={screenSize} + layoutConfig={layoutConfig} + /> + </Grid> + <Grid item xs={12} md={9} className={classes.resultsContainer}> + <FacetedSearchPerspective + perspectiveState={props[`${perspective.id}`]} + perspectiveConfig={perspective} + facetState={props[`${perspective.id}Facets`]} + facetConstrainSelfState={has(props, `${perspective.id}FacetsConstrainSelf`) + ? props[`${perspective.id}FacetsConstrainSelf`] + : null} + leafletMapState={props.leafletMap} + fetchPaginatedResults={props.fetchPaginatedResults} + fetchResults={props.fetchResults} + fetchInstanceAnalysis={props.fetchInstanceAnalysis} + fetchFacetConstrainSelf={props.fetchFacetConstrainSelf} + fetchGeoJSONLayers={props.fetchGeoJSONLayers} + fetchGeoJSONLayersBackend={props.fetchGeoJSONLayersBackend} + clearGeoJSONLayers={props.clearGeoJSONLayers} + fetchByURI={props.fetchByURI} + updatePage={props.updatePage} + updateRowsPerPage={props.updateRowsPerPage} + updateFacetOption={props.updateFacetOption} + updateMapBounds={props.updateMapBounds} + sortResults={props.sortResults} + showError={props.showError} + routeProps={routeProps} + perspective={perspective} + animationValue={props.animationValue} + animateMap={props.animateMap} + screenSize={screenSize} + rootUrl={rootUrlWithLang} + layoutConfig={layoutConfig} + /> + </Grid> + </Grid> + </> + ) + }} + /> + <Switch> + <Redirect + from={`/${perspective.id}/page/:id`} + to={`${rootUrlWithLang}/${perspective.id}/page/:id`} /> - </Grid> - </Grid>} - /> - {/* routes for faceted search perspectives */} - {perspectiveConfig.map(perspective => { - if (!has(perspective, 'externalUrl') && perspective.id !== 'placesClientFS') { - return ( - <React.Fragment key={perspective.id}> <Route - path={`${rootUrlWithLang}/${perspective.id}/faceted-search`} + path={`${rootUrlWithLang}/${perspective.id}/page/:id`} render={routeProps => { return ( <> <InfoHeader resultClass={perspective.id} - pageType='facetResults' - expanded={props[perspective.id].facetedSearchHeaderExpanded} + pageType='instancePage' + instanceData={props[perspective.id].instanceTableData} + expanded={props[perspective.id].instancePageHeaderExpanded} updateExpanded={props.updatePerspectiveHeaderExpanded} - descriptionHeight={perspective.perspectiveDescHeight} screenSize={screenSize} + layoutConfig={layoutConfig} /> <Grid - container spacing={1} className={props[perspective.id].facetedSearchHeaderExpanded - ? classes.perspectiveContainerHeaderExpanded - : classes.perspectiveContainer} + container spacing={1} className={props[perspective.id].instancePageHeaderExpanded + ? classes.instancePageContainerHeaderExpanded + : classes.instancePageContainer} > - <Grid item xs={12} md={3} className={classes.facetBarContainer}> - <FacetBar - facetedSearchMode='serverFS' - facetData={props[`${perspective.id}Facets`]} - facetDataConstrainSelf={has(props, `${perspective.id}FacetsConstrainSelf`) - ? props[`${perspective.id}FacetsConstrainSelf`] - : null} - facetResults={props[`${perspective.id}`]} - facetClass={perspective.id} - resultClass={perspective.id} - fetchingResultCount={props[perspective.id].fetchingResultCount} - resultCount={props[perspective.id].resultCount} - fetchFacet={props.fetchFacet} - fetchFacetConstrainSelf={props.fetchFacetConstrainSelf} - fetchResults={props.fetchResults} - clearFacet={props.clearFacet} - clearAllFacets={props.clearAllFacets} - fetchResultCount={props.fetchResultCount} - updateFacetOption={props.updateFacetOption} - showError={props.showError} - defaultActiveFacets={perspective.defaultActiveFacets} - rootUrl={rootUrlWithLang} - screenSize={screenSize} - /> - </Grid> - <Grid item xs={12} md={9} className={classes.resultsContainer}> - <FacetedSearchPerspective + <Grid item xs={12} className={classes.instancePageContent}> + <InstanceHomePage perspectiveState={props[`${perspective.id}`]} perspectiveConfig={perspective} - facetState={props[`${perspective.id}Facets`]} - facetConstrainSelfState={has(props, `${perspective.id}FacetsConstrainSelf`) - ? props[`${perspective.id}FacetsConstrainSelf`] - : null} leafletMapState={props.leafletMap} fetchPaginatedResults={props.fetchPaginatedResults} fetchResults={props.fetchResults} @@ -413,6 +444,7 @@ const SemanticPortal = props => { animateMap={props.animateMap} screenSize={screenSize} rootUrl={rootUrlWithLang} + layoutConfig={layoutConfig} /> </Grid> </Grid> @@ -420,130 +452,76 @@ const SemanticPortal = props => { ) }} /> - <Switch> - <Redirect - from={`/${perspective.id}/page/:id`} - to={`${rootUrlWithLang}/${perspective.id}/page/:id`} - /> - <Route - path={`${rootUrlWithLang}/${perspective.id}/page/:id`} - render={routeProps => { - return ( - <> - <InfoHeader - resultClass={perspective.id} - pageType='instancePage' - instanceData={props[perspective.id].instanceTableData} - expanded={props[perspective.id].instancePageHeaderExpanded} - updateExpanded={props.updatePerspectiveHeaderExpanded} - descriptionHeight={perspective.perspectiveDescHeight} - screenSize={screenSize} - /> - <Grid - container spacing={1} className={props[perspective.id].instancePageHeaderExpanded - ? classes.instancePageContainerHeaderExpanded - : classes.instancePageContainer} - > - <Grid item xs={12} className={classes.instancePageContent}> - <InstanceHomePage - perspectiveState={props[`${perspective.id}`]} - perspectiveConfig={perspective} - leafletMapState={props.leafletMap} - fetchPaginatedResults={props.fetchPaginatedResults} - fetchResults={props.fetchResults} - fetchInstanceAnalysis={props.fetchInstanceAnalysis} - fetchFacetConstrainSelf={props.fetchFacetConstrainSelf} - fetchGeoJSONLayers={props.fetchGeoJSONLayers} - fetchGeoJSONLayersBackend={props.fetchGeoJSONLayersBackend} - clearGeoJSONLayers={props.clearGeoJSONLayers} - fetchByURI={props.fetchByURI} - updatePage={props.updatePage} - updateRowsPerPage={props.updateRowsPerPage} - updateFacetOption={props.updateFacetOption} - updateMapBounds={props.updateMapBounds} - sortResults={props.sortResults} - showError={props.showError} - routeProps={routeProps} - perspective={perspective} - animationValue={props.animationValue} - animateMap={props.animateMap} - screenSize={screenSize} - rootUrl={rootUrlWithLang} - /> - </Grid> - </Grid> - </> - ) - }} + </Switch> + </React.Fragment> + ) + } + })} + {/* create routes for classes that have only info pages and no faceted search perspective */} + {perspectiveConfigOnlyInfoPages.map(perspective => + <Switch key={perspective.id}> + <Redirect + from={`${rootUrl}/${perspective.id}/page/:id`} + to={`${rootUrlWithLang}/${perspective.id}/page/:id`} + /> + <Route + path={`${rootUrlWithLang}/${perspective.id}/page/:id`} + render={routeProps => { + return ( + <> + <InfoHeader + resultClass={perspective.id} + pageType='instancePage' + instanceData={props[perspective.id].instanceTableData} + expanded={props[perspective.id].instancePageHeaderExpanded} + updateExpanded={props.updatePerspectiveHeaderExpanded} + screenSize={screenSize} + layoutConfig={layoutConfig} /> - </Switch> - </React.Fragment> - ) - } - })} - {/* create routes for classes that have only info pages and no faceted search perspective */} - {perspectiveConfigOnlyInfoPages.map(perspective => - <Switch key={perspective.id}> - <Redirect - from={`${rootUrl}/${perspective.id}/page/:id`} - to={`${rootUrlWithLang}/${perspective.id}/page/:id`} - /> - <Route - path={`${rootUrlWithLang}/${perspective.id}/page/:id`} - render={routeProps => { - return ( - <> - <InfoHeader - resultClass={perspective.id} - pageType='instancePage' - instanceData={props[perspective.id].instanceTableData} - expanded={props[perspective.id].instancePageHeaderExpanded} - updateExpanded={props.updatePerspectiveHeaderExpanded} - descriptionHeight={perspective.perspectiveDescHeight} - screenSize={screenSize} - /> - <Grid - container spacing={1} className={props[perspective.id].instancePageHeaderExpanded - ? classes.instancePageContainerHeaderExpanded - : classes.instancePageContainer} - > - <Grid item xs={12} className={classes.instancePageContent}> - <InstanceHomePage - perspectiveState={props[`${perspective.id}`]} - perspectiveConfig={perspective} - leafletMapState={props.leafletMap} - fetchPaginatedResults={props.fetchPaginatedResults} - fetchResults={props.fetchResults} - fetchInstanceAnalysis={props.fetchInstanceAnalysis} - fetchFacetConstrainSelf={props.fetchFacetConstrainSelf} - fetchGeoJSONLayers={props.fetchGeoJSONLayers} - fetchGeoJSONLayersBackend={props.fetchGeoJSONLayersBackend} - clearGeoJSONLayers={props.clearGeoJSONLayers} - fetchByURI={props.fetchByURI} - updatePage={props.updatePage} - updateRowsPerPage={props.updateRowsPerPage} - updateFacetOption={props.updateFacetOption} - updateMapBounds={props.updateMapBounds} - sortResults={props.sortResults} - showError={props.showError} - routeProps={routeProps} - perspective={perspective} - animationValue={props.animationValue} - animateMap={props.animateMap} - screenSize={screenSize} - rootUrl={rootUrlWithLang} - /> - </Grid> + <Grid + container spacing={1} className={props[perspective.id].instancePageHeaderExpanded + ? classes.instancePageContainerHeaderExpanded + : classes.instancePageContainer} + > + <Grid item xs={12} className={classes.instancePageContent}> + <InstanceHomePage + perspectiveState={props[`${perspective.id}`]} + perspectiveConfig={perspective} + leafletMapState={props.leafletMap} + fetchPaginatedResults={props.fetchPaginatedResults} + fetchResults={props.fetchResults} + fetchInstanceAnalysis={props.fetchInstanceAnalysis} + fetchFacetConstrainSelf={props.fetchFacetConstrainSelf} + fetchGeoJSONLayers={props.fetchGeoJSONLayers} + fetchGeoJSONLayersBackend={props.fetchGeoJSONLayersBackend} + clearGeoJSONLayers={props.clearGeoJSONLayers} + fetchByURI={props.fetchByURI} + updatePage={props.updatePage} + updateRowsPerPage={props.updateRowsPerPage} + updateFacetOption={props.updateFacetOption} + updateMapBounds={props.updateMapBounds} + sortResults={props.sortResults} + showError={props.showError} + routeProps={routeProps} + perspective={perspective} + animationValue={props.animationValue} + animateMap={props.animateMap} + screenSize={screenSize} + rootUrl={rootUrlWithLang} + layoutConfig={layoutConfig} + /> </Grid> - </> - ) - }} - /> - </Switch> - )} - <Route - path={`${rootUrlWithLang}/clientFSPlaces/federated-search`} - render={routeProps => + </Grid> + </> + ) + }} + /> + </Switch> + )} + <Route + path={`${rootUrlWithLang}/clientFSPlaces/federated-search`} + render={routeProps => + <> <Grid container className={classes.mainContainerClientFS}> <Grid item sm={12} md={4} lg={3} className={classes.facetBarContainerClientFS}> <FacetBar @@ -566,6 +544,7 @@ const SemanticPortal = props => { screenSize={screenSize} showError={props.showError} rootUrl={rootUrlWithLang} + layoutConfig={layoutConfig} /> </Grid> <Grid item sm={12} md={8} lg={9} className={classes.resultsContainerClientFS}> @@ -585,42 +564,45 @@ const SemanticPortal = props => { clearGeoJSONLayers={props.clearGeoJSONLayers} showError={props.showError} rootUrl={rootUrlWithLang} + layoutConfig={layoutConfig} />} </Grid> - </Grid>} - /> - {/* create routes for info buttons */} - {/* <Route + </Grid> + <Footer layoutConfig={layoutConfig} /> + </>} + + /> + {/* create routes for info buttons */} + {/* <Route path={`${rootUrlWithLang}/feedback`} render={() => <div className={classNames(classes.mainContainer, classes.textPageContainer)}> <TextPage>{intl.getHTML('feedback')}</TextPage> </div>} /> */} - <Route - path={`${rootUrlWithLang}/about`} - render={() => - <div className={classNames(classes.mainContainer, classes.textPageContainer)}> - <TextPage> - {intl.getHTML('aboutThePortalPartOne')} - <KnowledgeGraphMetadataTable - resultClass='perspective1KnowledgeGraphMetadata' - fetchKnowledgeGraphMetadata={props.fetchKnowledgeGraphMetadata} - knowledgeGraphMetadata={props.perspective1.knowledgeGraphMetadata} - /> - {intl.getHTML('aboutThePortalPartTwo')} - </TextPage> - </div>} - /> - <Route - path={`${rootUrlWithLang}/instructions`} - render={() => - <div className={classNames(classes.mainContainer, classes.textPageContainer)}> - <TextPage>{intl.getHTML('instructions')}</TextPage> - </div>} - /> - </> - </div> + <Route + path={`${rootUrlWithLang}/about`} + render={() => + <div className={classNames(classes.mainContainer, classes.textPageContainer)}> + <TextPage> + {intl.getHTML('aboutThePortalPartOne')} + <KnowledgeGraphMetadataTable + resultClass='perspective1KnowledgeGraphMetadata' + fetchKnowledgeGraphMetadata={props.fetchKnowledgeGraphMetadata} + knowledgeGraphMetadata={props.perspective1.knowledgeGraphMetadata} + /> + {intl.getHTML('aboutThePortalPartTwo')} + </TextPage> + </div>} + /> + <Route + path={`${rootUrlWithLang}/instructions`} + render={() => + <div className={classNames(classes.mainContainer, classes.textPageContainer)}> + <TextPage>{intl.getHTML('instructions')}</TextPage> + </div>} + /> + </> </div> </MuiPickersUtilsProvider> ) diff --git a/src/client/index.css b/src/client/index.css index 2e081c3d..c3b05f83 100644 --- a/src/client/index.css +++ b/src/client/index.css @@ -1,20 +1,15 @@ -html { - height: 100%; -} - body { - height: 100%; margin: 0; - min-width: 300px; } -fieldset, .opacity-slider { - outline: 0 !important; +@media screen and (min-width: 960px) { + html, body, #root, #app { + height: 100%; + } } -#root, #app { - height: 100%; - background-color: #bdbdbd; +fieldset, .opacity-slider { + outline: 0 !important; } a, a:visited, a:hover, a:active { -- GitLab