import React, { Component, PropTypes } from 'react'; import Helmet from 'react-helmet'; import { withRouter } from 'react-router-dom'; import { FormattedMessage, injectIntl, intlShape } from 'react-intl'; import classNames from 'classnames'; import { canonicalURL, metaTagProps } from '../../util/seo'; import facebookImage from '../../assets/saunatimeFacebook-1200x630.jpg'; import twitterImage from '../../assets/saunatimeTwitter-600x314.jpg'; import css from './PageLayout.css'; const scrollToTop = () => { // Todo: this might need fine tuning later window.scrollTo(0, 0); }; class PageLayoutComponent extends Component { componentDidMount() { this.historyUnlisten = this.props.history.listen(() => scrollToTop()); } componentWillUnmount() { if (this.historyUnlisten) { this.historyUnlisten(); } } render() { const { className, rootClassName, authInfoError, children, history, intl, logoutError, scrollingDisabled, contentType, description, facebookImages, published, schema, tags, title, twitterHandle, twitterImages, updated, } = this.props; // TODO: use FlashMessages for auth errors /* eslint-disable no-console */ if (authInfoError && console && console.error) { console.error(authInfoError); } if (logoutError && console && console.error) { console.error(logoutError); } /* eslint-enable no-console */ const classes = classNames(rootClassName || css.root, className, { [css.scrollingDisabled]: scrollingDisabled, }); const { pathname, search = '' } = history.location; const pathWithSearch = `${pathname}${search}`; const schemaTitle = intl.formatMessage({ id: 'PageLayout.schemaTitle' }); const schemaDescription = intl.formatMessage({ id: 'PageLayout.schemaDescription' }); const metaTitle = title || schemaTitle; const metaDescription = description || schemaDescription; const facebookImgs = facebookImages || [ { name: 'facebook', url: facebookImage, width: 1200, height: 630 }, ]; const twitterImgs = twitterImages || [ { name: 'twitter', url: twitterImage, width: 600, height: 314 }, ]; const metaToHead = metaTagProps({ contentType, description: metaDescription, facebookImages: facebookImgs, twitterImages: twitterImgs, published, tags, title: metaTitle, twitterHandle, updated, url: canonicalURL(pathWithSearch), }); // eslint-disable-next-line react/no-array-index-key const metaTags = metaToHead.map((metaProps, i) => ); // Schema for search engines (helps them to understand what this page is about) // http://schema.org // We are using JSON-LD format const schemaJSONString = schema || JSON.stringify({ '@context': 'http://schema.org', '@type': 'WebPage', description: schemaDescription, name: schemaTitle, }); return (
{title} {metaTags} {authInfoError ?
: null} {logoutError ?
: null}
{children}
); } } const { any, arrayOf, bool, func, instanceOf, number, shape, string } = PropTypes; PageLayoutComponent.defaultProps = { className: null, rootClassName: null, children: null, authInfoError: null, logoutError: null, scrollingDisabled: false, contentType: 'website', description: null, facebookImages: null, twitterImages: null, published: null, schema: null, tags: null, twitterHandle: null, updated: null, }; PageLayoutComponent.propTypes = { className: string, rootClassName: string, children: any, authInfoError: instanceOf(Error), logoutError: instanceOf(Error), scrollingDisabled: bool, // SEO related props contentType: string, // og:type description: string, // page description facebookImages: arrayOf( shape({ width: number.isRequired, height: number.isRequired, url: string.isRequired, }) ), twitterImages: arrayOf( shape({ width: number.isRequired, height: number.isRequired, url: string.isRequired, }) ), published: string, // article:published_time schema: string, // http://schema.org tags: string, // article:tag title: string.isRequired, // page title twitterHandle: string, // twitter handle updated: string, // article:modified_time // from withRouter history: shape({ listen: func.isRequired, }).isRequired, // from injectIntl intl: intlShape.isRequired, }; const PageLayout = injectIntl(withRouter(PageLayoutComponent)); PageLayout.displayName = 'PageLayout'; export default PageLayout;