updated Seo component to pull site info from state
This commit is contained in:
parent
e3279ed414
commit
1cac864100
9 changed files with 114 additions and 92 deletions
|
@ -3,18 +3,19 @@ function SiteConfig () {
|
|||
googleId: 'default',
|
||||
};
|
||||
this.assetDefaults = {
|
||||
title : 'Spee.ch',
|
||||
description: 'An asset published on Spee.ch',
|
||||
thumbnail : 'https://spee.ch/assets/img/video_thumb_default.png',
|
||||
description: 'Open-source, decentralized image and video sharing.',
|
||||
title : 'Spee.ch',
|
||||
};
|
||||
this.auth = {
|
||||
sessionKey: 'default',
|
||||
};
|
||||
this.details = {
|
||||
description: 'Open-source, decentralized image and video sharing.',
|
||||
host : 'default',
|
||||
port : 3000,
|
||||
title : 'Spee.ch',
|
||||
host : 'default',
|
||||
description: 'Open-source, decentralized image and video sharing.',
|
||||
twitter : '@spee_ch',
|
||||
};
|
||||
this.publishing = {
|
||||
additionalClaimAddresses: [],
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class Preview extends React.Component {
|
||||
class PublishPreview extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -53,10 +53,10 @@ class Preview extends React.Component {
|
|||
}
|
||||
};
|
||||
|
||||
Preview.propTypes = {
|
||||
PublishPreview.propTypes = {
|
||||
dimPreview: PropTypes.bool.isRequired,
|
||||
file : PropTypes.object.isRequired,
|
||||
thumbnail : PropTypes.object,
|
||||
};
|
||||
|
||||
export default Preview;
|
||||
export default PublishPreview;
|
|
@ -1,32 +1,16 @@
|
|||
import React from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import View from './view';
|
||||
|
||||
import { createPageTitle } from 'utils/pageTitle';
|
||||
import { createMetaTags } from 'utils/metaTags';
|
||||
import { createCanonicalLink } from 'utils/canonicalLink';
|
||||
|
||||
class SEO extends React.Component {
|
||||
render () {
|
||||
let { pageTitle, asset, channel, pageUri } = this.props;
|
||||
pageTitle = createPageTitle(pageTitle);
|
||||
const metaTags = createMetaTags(asset, channel);
|
||||
const canonicalLink = createCanonicalLink(asset, channel, pageUri);
|
||||
return (
|
||||
<Helmet
|
||||
title={pageTitle}
|
||||
meta={metaTags}
|
||||
link={[{rel: 'canonical', href: canonicalLink}]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
const mapStateToProps = ({ site }) => {
|
||||
const { defaultDescription, defaultThumbnail, description: siteDescription, host: siteHost, title: siteTitle, twitter: siteTwitter } = site;
|
||||
return {
|
||||
defaultDescription,
|
||||
defaultThumbnail,
|
||||
siteDescription,
|
||||
siteHost,
|
||||
siteTitle,
|
||||
siteTwitter,
|
||||
};
|
||||
};
|
||||
|
||||
SEO.propTypes = {
|
||||
pageTitle: PropTypes.string,
|
||||
pageUri : PropTypes.string,
|
||||
channel : PropTypes.object,
|
||||
asset : PropTypes.object,
|
||||
};
|
||||
|
||||
export default SEO;
|
||||
export default connect(mapStateToProps, null)(View);
|
||||
|
|
38
react/components/SEO/view.jsx
Normal file
38
react/components/SEO/view.jsx
Normal file
|
@ -0,0 +1,38 @@
|
|||
import React from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { createPageTitle } from 'utils/pageTitle';
|
||||
import { createMetaTags } from 'utils/metaTags';
|
||||
import { createCanonicalLink } from 'utils/canonicalLink';
|
||||
|
||||
class SEO extends React.Component {
|
||||
render () {
|
||||
// props from state
|
||||
const { defaultDescription, defaultThumbnail, siteDescription, siteHost, siteTitle, siteTwitter } = this.props;
|
||||
// props from parent
|
||||
const { asset, channel, pageUri } = this.props;
|
||||
let { pageTitle } = this.props;
|
||||
// create page title, tags, and canonical link
|
||||
pageTitle = createPageTitle(siteTitle, pageTitle);
|
||||
const metaTags = createMetaTags(siteDescription, siteHost, siteTitle, siteTwitter, asset, channel, defaultDescription, defaultThumbnail);
|
||||
const canonicalLink = createCanonicalLink(asset, channel, pageUri, siteHost);
|
||||
// render results
|
||||
return (
|
||||
<Helmet
|
||||
title={pageTitle}
|
||||
meta={metaTags}
|
||||
link={[{rel: 'canonical', href: canonicalLink}]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
SEO.propTypes = {
|
||||
pageTitle: PropTypes.string,
|
||||
pageUri : PropTypes.string,
|
||||
channel : PropTypes.object,
|
||||
asset : PropTypes.object,
|
||||
};
|
||||
|
||||
export default SEO;
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { validateFile } from 'utils/file';
|
||||
import Preview from 'components/Preview';
|
||||
import PublishPreview from 'components/PublishPreview';
|
||||
|
||||
class Dropzone extends React.Component {
|
||||
constructor (props) {
|
||||
|
@ -87,7 +87,7 @@ class Dropzone extends React.Component {
|
|||
<div id='preview-dropzone' className={'row row--padded row--tall dropzone' + (this.state.dragOver ? ' dropzone--drag-over' : '')} onDrop={this.handleDrop} onDragOver={this.handleDragOver} onDragEnd={this.handleDragEnd} onDragEnter={this.handleDragEnter} onDragLeave={this.handleDragLeave} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} onClick={this.handleClick}>
|
||||
{this.props.file ? (
|
||||
<div>
|
||||
<Preview
|
||||
<PublishPreview
|
||||
dimPreview={this.state.dimPreview}
|
||||
file={this.props.file}
|
||||
thumbnail={this.props.thumbnail}
|
||||
|
|
|
@ -1,18 +1,29 @@
|
|||
const siteConfig = require('../../config/siteConfig.js');
|
||||
|
||||
const {
|
||||
analytics: { googleId: googleAnalyticsId },
|
||||
assetDefaults: { thumbnail: defaultThumbnail },
|
||||
details: { title, host },
|
||||
analytics: {
|
||||
googleId: googleAnalyticsId,
|
||||
},
|
||||
assetDefaults: {
|
||||
thumbnail: defaultThumbnail,
|
||||
description: defaultDescription,
|
||||
},
|
||||
details: {
|
||||
description,
|
||||
host,
|
||||
title,
|
||||
twitter,
|
||||
},
|
||||
} = siteConfig;
|
||||
|
||||
const initialState = {
|
||||
description,
|
||||
googleAnalyticsId,
|
||||
host,
|
||||
title,
|
||||
defaults: {
|
||||
defaultThumbnail,
|
||||
},
|
||||
twitter,
|
||||
defaultDescription,
|
||||
defaultThumbnail,
|
||||
};
|
||||
|
||||
export default function (state = initialState, action) {
|
||||
|
|
|
@ -1,37 +1,29 @@
|
|||
const { details: { host } } = require('../../config/siteConfig.js');
|
||||
|
||||
const createBasicCanonicalLink = (page) => {
|
||||
if (!page) {
|
||||
return `${host}`;
|
||||
};
|
||||
return `${host}/${page}`;
|
||||
const createBasicCanonicalLink = (page, siteHost) => {
|
||||
return `${siteHost}/${page}`;
|
||||
};
|
||||
|
||||
const createAssetCanonicalLink = (asset) => {
|
||||
const createAssetCanonicalLink = (asset, siteHost) => {
|
||||
let channelName, certificateId, name, claimId;
|
||||
if (asset.claimData) {
|
||||
({ channelName, certificateId, name, claimId } = asset.claimData);
|
||||
};
|
||||
if (channelName) {
|
||||
return `${host}/${channelName}:${certificateId}/${name}`;
|
||||
return `${siteHost}/${channelName}:${certificateId}/${name}`;
|
||||
};
|
||||
return `${host}/${claimId}/${name}`;
|
||||
return `${siteHost}/${claimId}/${name}`;
|
||||
};
|
||||
|
||||
const createChannelCanonicalLink = (channel) => {
|
||||
const createChannelCanonicalLink = (channel, siteHost) => {
|
||||
const { name, longId } = channel;
|
||||
return `${host}/${name}:${longId}`;
|
||||
return `${siteHost}/${name}:${longId}`;
|
||||
};
|
||||
|
||||
export const createCanonicalLink = (asset, channel, page) => {
|
||||
export const createCanonicalLink = (asset, channel, page, siteHost) => {
|
||||
if (asset) {
|
||||
return createAssetCanonicalLink(asset);
|
||||
return createAssetCanonicalLink(asset, siteHost);
|
||||
}
|
||||
if (channel) {
|
||||
return createChannelCanonicalLink(channel);
|
||||
return createChannelCanonicalLink(channel, siteHost);
|
||||
}
|
||||
if (page) {
|
||||
return createBasicCanonicalLink(page);
|
||||
}
|
||||
return createBasicCanonicalLink();
|
||||
return createBasicCanonicalLink(page, siteHost);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
const { details: { title, host, description }, assetDefaults: { thumbnail: defaultThumbnail, description: defaultDescription } } = require('../../config/siteConfig.js');
|
||||
|
||||
const determineOgThumbnailContentType = (thumbnail) => {
|
||||
if (thumbnail) {
|
||||
const fileExt = thumbnail.substring(thumbnail.lastIndexOf('.'));
|
||||
|
@ -20,35 +18,35 @@ const determineOgThumbnailContentType = (thumbnail) => {
|
|||
return '';
|
||||
};
|
||||
|
||||
const createBasicMetaTags = () => {
|
||||
const createBasicMetaTags = (siteHost, siteDescription, siteTitle, siteTwitter) => {
|
||||
return [
|
||||
{property: 'og:title', content: title},
|
||||
{property: 'og:url', content: host},
|
||||
{property: 'og:site_name', content: title},
|
||||
{property: 'og:description', content: description},
|
||||
{property: 'twitter:site', content: '@spee_ch'},
|
||||
{property: 'og:title', content: siteTitle},
|
||||
{property: 'og:url', content: siteHost},
|
||||
{property: 'og:site_name', content: siteTitle},
|
||||
{property: 'og:description', content: siteDescription},
|
||||
{property: 'twitter:site', content: siteTwitter},
|
||||
{property: 'twitter:card', content: 'summary'},
|
||||
];
|
||||
};
|
||||
|
||||
const createChannelMetaTags = (channel) => {
|
||||
const createChannelMetaTags = (siteTitle, siteHost, siteTwitter, channel) => {
|
||||
const { name, longId } = channel;
|
||||
return [
|
||||
{property: 'og:title', content: `${name} on ${title}`},
|
||||
{property: 'og:url', content: `${host}/${name}:${longId}`},
|
||||
{property: 'og:site_name', content: title},
|
||||
{property: 'og:description', content: `${name}, a channel on ${title}`},
|
||||
{property: 'twitter:site', content: '@spee_ch'},
|
||||
{property: 'og:title', content: `${name} on ${siteTitle}`},
|
||||
{property: 'og:url', content: `${siteHost}/${name}:${longId}`},
|
||||
{property: 'og:site_name', content: siteTitle},
|
||||
{property: 'og:description', content: `${name}, a channel on ${siteTitle}`},
|
||||
{property: 'twitter:site', content: siteTwitter},
|
||||
{property: 'twitter:card', content: 'summary'},
|
||||
];
|
||||
};
|
||||
|
||||
const createAssetMetaTags = (asset) => {
|
||||
const createAssetMetaTags = (siteHost, siteTitle, siteTwitter, asset, defaultDescription, defaultThumbnail) => {
|
||||
const { claimData } = asset;
|
||||
const { contentType } = claimData;
|
||||
const embedUrl = `${host}/${claimData.claimId}/${claimData.name}`;
|
||||
const showUrl = `${host}/${claimData.claimId}/${claimData.name}`;
|
||||
const source = `${host}/${claimData.claimId}/${claimData.name}.${claimData.fileExt}`;
|
||||
const embedUrl = `${siteHost}/${claimData.claimId}/${claimData.name}`;
|
||||
const showUrl = `${siteHost}/${claimData.claimId}/${claimData.name}`;
|
||||
const source = `${siteHost}/${claimData.claimId}/${claimData.name}.${claimData.fileExt}`;
|
||||
const ogTitle = claimData.title || claimData.name;
|
||||
const ogDescription = claimData.description || defaultDescription;
|
||||
const ogThumbnailContentType = determineOgThumbnailContentType(claimData.thumbnail);
|
||||
|
@ -56,11 +54,11 @@ const createAssetMetaTags = (asset) => {
|
|||
const metaTags = [
|
||||
{property: 'og:title', content: ogTitle},
|
||||
{property: 'og:url', content: showUrl},
|
||||
{property: 'og:site_name', content: title},
|
||||
{property: 'og:site_name', content: siteTitle},
|
||||
{property: 'og:description', content: ogDescription},
|
||||
{property: 'og:image:width', content: 600},
|
||||
{property: 'og:image:height', content: 315},
|
||||
{property: 'twitter:site', content: '@spee_ch'},
|
||||
{property: 'twitter:site', content: siteTwitter},
|
||||
];
|
||||
if (contentType === 'video/mp4' || contentType === 'video/webm') {
|
||||
metaTags.push({property: 'og:video', content: source});
|
||||
|
@ -85,12 +83,12 @@ const createAssetMetaTags = (asset) => {
|
|||
return metaTags;
|
||||
};
|
||||
|
||||
export const createMetaTags = (asset, channel) => {
|
||||
export const createMetaTags = (siteDescription, siteHost, siteTitle, siteTwitter, asset, channel, defaultDescription, defaultThumbnail) => {
|
||||
if (asset) {
|
||||
return createAssetMetaTags(asset);
|
||||
return createAssetMetaTags(siteHost, siteTitle, siteTwitter, asset, defaultDescription, defaultThumbnail);
|
||||
};
|
||||
if (channel) {
|
||||
return createChannelMetaTags(channel);
|
||||
return createChannelMetaTags(siteHost, siteTitle, siteTwitter, channel);
|
||||
};
|
||||
return createBasicMetaTags();
|
||||
return createBasicMetaTags(siteDescription, siteHost, siteTitle, siteTwitter);
|
||||
};
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
const { details: { title } } = require('../../config/siteConfig.js');
|
||||
|
||||
export const createPageTitle = (pageTitle) => {
|
||||
export const createPageTitle = (siteTitle, pageTitle) => {
|
||||
if (!pageTitle) {
|
||||
return `${title}`;
|
||||
return `${siteTitle}`;
|
||||
}
|
||||
return `${title} - ${pageTitle}`;
|
||||
return `${siteTitle} - ${pageTitle}`;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue