mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-26 06:47:17 +10:00
203 lines
5.3 KiB
JavaScript
203 lines
5.3 KiB
JavaScript
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) => <meta key={i} {...metaProps} />);
|
|
|
|
// 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 (
|
|
<div className={classes}>
|
|
<Helmet
|
|
htmlAttributes={{
|
|
lang: intl.locale,
|
|
}}
|
|
>
|
|
<title>{title}</title>
|
|
<link rel="canonical" href={canonicalURL(pathWithSearch)} />
|
|
{metaTags}
|
|
<script type="application/ld+json">
|
|
{schemaJSONString}
|
|
</script>
|
|
|
|
</Helmet>
|
|
{authInfoError
|
|
? <div style={{ color: 'red' }}>
|
|
<FormattedMessage id="PageLayout.authInfoFailed" />
|
|
</div>
|
|
: null}
|
|
{logoutError
|
|
? <div style={{ color: 'red' }}>
|
|
<FormattedMessage id="PageLayout.logoutFailed" />
|
|
</div>
|
|
: null}
|
|
<div className={css.content}>
|
|
{children}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
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;
|