added react-helmet and dynamic title and canonical url tags
This commit is contained in:
parent
b4ef61ae85
commit
d24331d001
12 changed files with 123 additions and 49 deletions
|
@ -12,6 +12,8 @@ import { call } from 'redux-saga/effects';
|
||||||
import { handleShowPageUri } from '../react/sagas/show_uri';
|
import { handleShowPageUri } from '../react/sagas/show_uri';
|
||||||
import { onHandleShowPageUri } from '../react/actions/show';
|
import { onHandleShowPageUri } from '../react/actions/show';
|
||||||
|
|
||||||
|
import Helmet from 'react-helmet';
|
||||||
|
|
||||||
const returnSagaWithParams = (saga, params) => {
|
const returnSagaWithParams = (saga, params) => {
|
||||||
return function * () {
|
return function * () {
|
||||||
yield call(saga, params);
|
yield call(saga, params);
|
||||||
|
@ -49,6 +51,9 @@ module.exports = (req, res) => {
|
||||||
</Provider>
|
</Provider>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// get head tags from helmet
|
||||||
|
const helmet = Helmet.renderStatic();
|
||||||
|
|
||||||
// check for a redirect
|
// check for a redirect
|
||||||
if (context.url) {
|
if (context.url) {
|
||||||
console.log('REDIRECTING:', context.url);
|
console.log('REDIRECTING:', context.url);
|
||||||
|
@ -61,6 +66,6 @@ module.exports = (req, res) => {
|
||||||
const preloadedState = store.getState();
|
const preloadedState = store.getState();
|
||||||
|
|
||||||
// send the rendered page back to the client
|
// send the rendered page back to the client
|
||||||
res.send(renderFullPage(html, preloadedState));
|
res.send(renderFullPage(helmet, html, preloadedState));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
const { site } = require('../config/speechConfig.js');
|
module.exports = (helmet, html, preloadedState) => {
|
||||||
|
|
||||||
module.exports = (html, preloadedState) => {
|
|
||||||
// take the html and preloadedState and return the full page
|
// take the html and preloadedState and return the full page
|
||||||
return `
|
return `
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
@ -9,7 +7,10 @@ module.exports = (html, preloadedState) => {
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no">
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
<title>${site.title}</title>
|
<!--helmet-->
|
||||||
|
${helmet.title.toString()}
|
||||||
|
${helmet.link.toString()}
|
||||||
|
<!--style sheets-->
|
||||||
<link rel="stylesheet" href="/assets/css/reset.css" type="text/css">
|
<link rel="stylesheet" href="/assets/css/reset.css" type="text/css">
|
||||||
<link rel="stylesheet" href="/assets/css/general.css" type="text/css">
|
<link rel="stylesheet" href="/assets/css/general.css" type="text/css">
|
||||||
<link rel="stylesheet" href="/assets/css/mediaQueries.css" type="text/css">
|
<link rel="stylesheet" href="/assets/css/mediaQueries.css" type="text/css">
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
"react": "^16.2.0",
|
"react": "^16.2.0",
|
||||||
"react-dom": "^16.2.0",
|
"react-dom": "^16.2.0",
|
||||||
"react-ga": "^2.4.1",
|
"react-ga": "^2.4.1",
|
||||||
|
"react-helmet": "^5.2.0",
|
||||||
"react-redux": "^5.0.6",
|
"react-redux": "^5.0.6",
|
||||||
"react-router-dom": "^4.2.2",
|
"react-router-dom": "^4.2.2",
|
||||||
"redux": "^3.7.2",
|
"redux": "^3.7.2",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import Request from 'utils/request';
|
import request from 'utils/request';
|
||||||
import request from '../utils/request';
|
|
||||||
const { site: { host } } = require('../../config/speechConfig.js');
|
const { site: { host } } = require('../../config/speechConfig.js');
|
||||||
|
|
||||||
export function getChannelData (name, id) {
|
export function getChannelData (name, id) {
|
||||||
|
@ -12,6 +11,6 @@ export function getChannelData (name, id) {
|
||||||
export function getChannelClaims (name, longId, page) {
|
export function getChannelClaims (name, longId, page) {
|
||||||
console.log('getting channel claims for channel:', name, longId);
|
console.log('getting channel claims for channel:', name, longId);
|
||||||
if (!page) page = 1;
|
if (!page) page = 1;
|
||||||
const url = `${host}/api/channel/claims/${name}/${longId}/${page}`;
|
const url = `/api/channel/claims/${name}/${longId}/${page}`;
|
||||||
return Request(url);
|
return Request(url);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Route, Switch } from 'react-router-dom';
|
import { Route, Switch } from 'react-router-dom';
|
||||||
import PublishPage from 'components/PublishPage';
|
import HomePage from 'components/HomePage';
|
||||||
import AboutPage from 'components/AboutPage';
|
import AboutPage from 'components/AboutPage';
|
||||||
import LoginPage from 'containers/LoginPage';
|
import LoginPage from 'containers/LoginPage';
|
||||||
import ShowPage from 'containers/ShowPage';
|
import ShowPage from 'containers/ShowPage';
|
||||||
|
@ -9,7 +9,7 @@ import FourOhFourPage from 'components/FourOhFourPage';
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path='/' component={PublishPage} />
|
<Route exact path='/' component={HomePage} />
|
||||||
<Route exact path='/about' component={AboutPage} />
|
<Route exact path='/about' component={AboutPage} />
|
||||||
<Route exact path='/login' component={LoginPage} />
|
<Route exact path='/login' component={LoginPage} />
|
||||||
<Route exact path='/:identifier/:claim' component={ShowPage} />
|
<Route exact path='/:identifier/:claim' component={ShowPage} />
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import NavBar from 'containers/NavBar';
|
import NavBar from 'containers/NavBar';
|
||||||
|
import Helmet from 'react-helmet';
|
||||||
|
|
||||||
|
const { site: { title, host } } = require('../../../config/speechConfig.js');
|
||||||
|
|
||||||
class AboutPage extends React.Component {
|
class AboutPage extends React.Component {
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<Helmet>
|
||||||
|
<title>{title} - About</title>
|
||||||
|
<link rel='canonical' href={`${host}/about`} />
|
||||||
|
</Helmet>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<div className='row row--padded'>
|
<div className='row row--padded'>
|
||||||
<div className='column column--5 column--med-10 align-content-top'>
|
<div className='column column--5 column--med-10 align-content-top'>
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import NavBar from 'containers/NavBar';
|
import NavBar from 'containers/NavBar';
|
||||||
|
import Helmet from 'react-helmet';
|
||||||
|
const { site: { title, host } } = require('../../../config/speechConfig.js');
|
||||||
|
|
||||||
class FourOhForPage extends React.Component {
|
class FourOhForPage extends React.Component {
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<Helmet>
|
||||||
|
<title>{title} - 404</title>
|
||||||
|
<link rel='canonical' href={`${host}/404`} />
|
||||||
|
</Helmet>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<div className='row row--padded'>
|
<div className='row row--padded'>
|
||||||
<h2>404</h2>
|
<h2>404</h2>
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Helmet from 'react-helmet';
|
||||||
import NavBar from 'containers/NavBar';
|
import NavBar from 'containers/NavBar';
|
||||||
import PublishTool from 'containers/PublishTool';
|
import PublishTool from 'containers/PublishTool';
|
||||||
|
|
||||||
class PublishPage extends React.Component {
|
const { site: { title, host } } = require('../../../config/speechConfig.js');
|
||||||
|
|
||||||
|
class HomePage extends React.Component {
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<div className={'row row--tall flex-container--column'}>
|
<div className={'row row--tall flex-container--column'}>
|
||||||
|
<Helmet>
|
||||||
|
<title>{title}</title>
|
||||||
|
<link rel='canonical' href={`${host}/`} />
|
||||||
|
</Helmet>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<div className={'row row--tall row--padded flex-container--column'}>
|
<div className={'row row--tall row--padded flex-container--column'}>
|
||||||
<PublishTool />
|
<PublishTool />
|
||||||
|
@ -15,4 +22,4 @@ class PublishPage extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PublishPage;
|
export default HomePage;
|
|
@ -1,27 +1,42 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Helmet from 'react-helmet';
|
||||||
import NavBar from 'containers/NavBar';
|
import NavBar from 'containers/NavBar';
|
||||||
import ErrorPage from 'components/ErrorPage';
|
import ErrorPage from 'components/ErrorPage';
|
||||||
import AssetTitle from 'components/AssetTitle';
|
import AssetTitle from 'components/AssetTitle';
|
||||||
import AssetDisplay from 'components/AssetDisplay';
|
import AssetDisplay from 'components/AssetDisplay';
|
||||||
import AssetInfo from 'components/AssetInfo';
|
import AssetInfo from 'components/AssetInfo';
|
||||||
|
|
||||||
|
const { site: { title, host } } = require('../../../config/speechConfig.js');
|
||||||
|
|
||||||
class ShowAssetDetails extends React.Component {
|
class ShowAssetDetails extends React.Component {
|
||||||
render () {
|
render () {
|
||||||
const { asset } = this.props;
|
const { asset } = this.props;
|
||||||
|
let channelName, certificateId, name, claimId;
|
||||||
|
if (asset.claimData) {
|
||||||
|
({ channelName, certificateId, name, claimId } = asset.claimData);
|
||||||
|
};
|
||||||
if (asset) {
|
if (asset) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<NavBar/>
|
<Helmet>
|
||||||
<div className="row row--tall row--padded">
|
<title>{title} - {name} - details</title>
|
||||||
<div className="column column--10">
|
{channelName ? (
|
||||||
|
<link rel='canonical' href={`${host}/${channelName}:${certificateId}/${name}`} />
|
||||||
|
) : (
|
||||||
|
<link rel='canonical' href={`${host}/${claimId}/${name}`} />
|
||||||
|
)}
|
||||||
|
</Helmet>
|
||||||
|
<NavBar />
|
||||||
|
<div className='row row--tall row--padded'>
|
||||||
|
<div className='column column--10'>
|
||||||
<AssetTitle />
|
<AssetTitle />
|
||||||
</div>
|
</div>
|
||||||
<div className="column column--5 column--sml-10 align-content-top">
|
<div className='column column--5 column--sml-10 align-content-top'>
|
||||||
<div className="row row--padded">
|
<div className='row row--padded'>
|
||||||
<AssetDisplay />
|
<AssetDisplay />
|
||||||
</div>
|
</div>
|
||||||
</div><div className="column column--5 column--sml-10 align-content-top">
|
</div><div className='column column--5 column--sml-10 align-content-top'>
|
||||||
<div className="row row--padded">
|
<div className='row row--padded'>
|
||||||
<AssetInfo />
|
<AssetInfo />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -31,7 +46,7 @@ class ShowAssetDetails extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<ErrorPage error={'loading asset data...'}/>
|
<ErrorPage error={'loading asset data...'} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,19 +1,38 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Helmet from 'react-helmet';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import AssetDisplay from 'components/AssetDisplay';
|
import AssetDisplay from 'components/AssetDisplay';
|
||||||
|
|
||||||
|
const { site: { title, host } } = require('../../../config/speechConfig.js');
|
||||||
|
|
||||||
class ShowLite extends React.Component {
|
class ShowLite extends React.Component {
|
||||||
render () {
|
render () {
|
||||||
const { asset } = this.props;
|
const { asset } = this.props;
|
||||||
|
if (asset) {
|
||||||
|
let channelName, certificateId, name, claimId, fileExt;
|
||||||
|
if (asset.claimData) {
|
||||||
|
({ channelName, certificateId, name, claimId, fileExt } = asset.claimData);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className="row row--tall flex-container--column flex-container--center-center">
|
<div className='row row--tall flex-container--column flex-container--center-center'>
|
||||||
{ (asset) &&
|
<Helmet>
|
||||||
|
<title>{title} - {name}</title>
|
||||||
|
{channelName ? (
|
||||||
|
<link rel='canonical' href={`${host}/${channelName}:${certificateId}/${name}.${fileExt}`} />
|
||||||
|
) : (
|
||||||
|
<link rel='canonical' href={`${host}/${claimId}/${name}.${fileExt}`} />
|
||||||
|
)}
|
||||||
|
</Helmet>
|
||||||
<div>
|
<div>
|
||||||
<AssetDisplay />
|
<AssetDisplay />
|
||||||
<Link id="asset-boilerpate" className="link--primary fine-print" to={`/${asset.claimId}/${asset.name}`}>hosted via Spee.ch</Link>
|
<Link id='asset-boilerpate' className='link--primary fine-print' to={`/${claimId}/${name}`}>hosted
|
||||||
|
via Spee.ch</Link>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
</div>
|
return (
|
||||||
|
<p>loading asset data...</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Helmet from 'react-helmet';
|
||||||
import ErrorPage from 'components/ErrorPage';
|
import ErrorPage from 'components/ErrorPage';
|
||||||
import NavBar from 'containers/NavBar';
|
import NavBar from 'containers/NavBar';
|
||||||
import ChannelClaimsDisplay from 'containers/ChannelClaimsDisplay';
|
import ChannelClaimsDisplay from 'containers/ChannelClaimsDisplay';
|
||||||
|
|
||||||
|
const { site: { title, host } } = require('../../../config/speechConfig.js');
|
||||||
|
|
||||||
class ShowChannel extends React.Component {
|
class ShowChannel extends React.Component {
|
||||||
render () {
|
render () {
|
||||||
const { channel } = this.props;
|
const { channel } = this.props;
|
||||||
|
@ -10,14 +13,18 @@ class ShowChannel extends React.Component {
|
||||||
const { name, longId, shortId } = channel;
|
const { name, longId, shortId } = channel;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<NavBar/>
|
<Helmet>
|
||||||
<div className="row row--tall row--padded">
|
<title>{title} - {name}</title>
|
||||||
<div className="column column--10">
|
<link rel='canonical' href={`${host}/${name}:${longId}`} />
|
||||||
|
</Helmet>
|
||||||
|
<NavBar />
|
||||||
|
<div className='row row--tall row--padded'>
|
||||||
|
<div className='column column--10'>
|
||||||
<h2>channel name: {name || 'loading...'}</h2>
|
<h2>channel name: {name || 'loading...'}</h2>
|
||||||
<p className={'fine-print'}>full channel id: {longId || 'loading...'}</p>
|
<p className={'fine-print'}>full channel id: {longId || 'loading...'}</p>
|
||||||
<p className={'fine-print'}>short channel id: {shortId || 'loading...'}</p>
|
<p className={'fine-print'}>short channel id: {shortId || 'loading...'}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="column column--10">
|
<div className='column column--10'>
|
||||||
<ChannelClaimsDisplay />
|
<ChannelClaimsDisplay />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,7 +32,7 @@ class ShowChannel extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<ErrorPage error={'loading channel data...'}/>
|
<ErrorPage error={'loading channel data...'} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
|
import Helmet from 'react-helmet';
|
||||||
import NavBar from 'containers/NavBar';
|
import NavBar from 'containers/NavBar';
|
||||||
import ChannelLoginForm from 'containers/ChannelLoginForm';
|
import ChannelLoginForm from 'containers/ChannelLoginForm';
|
||||||
import ChannelCreateForm from 'containers/ChannelCreateForm';
|
import ChannelCreateForm from 'containers/ChannelCreateForm';
|
||||||
|
|
||||||
class PublishPage extends React.Component {
|
const { site: { title, host } } = require('../../../config/speechConfig.js');
|
||||||
|
|
||||||
|
class LoginPage extends React.Component {
|
||||||
componentWillReceiveProps (newProps) {
|
componentWillReceiveProps (newProps) {
|
||||||
// re-route the user to the homepage if the user is logged in
|
// re-route the user to the homepage if the user is logged in
|
||||||
if (newProps.loggedInChannelName !== this.props.loggedInChannelName) {
|
if (newProps.loggedInChannelName !== this.props.loggedInChannelName) {
|
||||||
|
@ -15,17 +18,21 @@ class PublishPage extends React.Component {
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<NavBar/>
|
<Helmet>
|
||||||
<div className="row row--padded">
|
<title>{title} - Login</title>
|
||||||
<div className="column column--5 column--med-10 align-content-top">
|
<link rel='canonical' href={`${host}/login`} />
|
||||||
<div className="column column--8 column--med-10">
|
</Helmet>
|
||||||
<p>Channels allow you to publish and group content under an identity. You can create a channel for yourself, or share one with like-minded friends. You can create 1 channel, or 100, so whether you're <a className="link--primary" target="_blank" href="/@catalonia2017:43dcf47163caa21d8404d9fe9b30f78ef3e146a8">documenting important events</a>, or making a public repository for <a className="link--primary" target="_blank" href="/@catGifs">cat gifs</a> (password: '1234'), try creating a channel for it!</p>
|
<NavBar />
|
||||||
|
<div className='row row--padded'>
|
||||||
|
<div className='column column--5 column--med-10 align-content-top'>
|
||||||
|
<div className='column column--8 column--med-10'>
|
||||||
|
<p>Channels allow you to publish and group content under an identity. You can create a channel for yourself, or share one with like-minded friends. You can create 1 channel, or 100, so whether you're <a className='link--primary' target='_blank' href='/@catalonia2017:43dcf47163caa21d8404d9fe9b30f78ef3e146a8'>documenting important events</a>, or making a public repository for <a className='link--primary' target='_blank' href='/@catGifs'>cat gifs</a> (password: '1234'), try creating a channel for it!</p>
|
||||||
</div>
|
</div>
|
||||||
</div><div className="column column--5 column--med-10 align-content-top">
|
</div><div className='column column--5 column--med-10 align-content-top'>
|
||||||
<div className="column column--8 column--med-10">
|
<div className='column column--8 column--med-10'>
|
||||||
<h3 className="h3--no-bottom">Log in to an existing channel:</h3>
|
<h3 className='h3--no-bottom'>Log in to an existing channel:</h3>
|
||||||
<ChannelLoginForm />
|
<ChannelLoginForm />
|
||||||
<h3 className="h3--no-bottom">Create a brand new channel:</h3>
|
<h3 className='h3--no-bottom'>Create a brand new channel:</h3>
|
||||||
<ChannelCreateForm />
|
<ChannelCreateForm />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -35,4 +42,4 @@ class PublishPage extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withRouter(PublishPage);
|
export default withRouter(LoginPage);
|
||||||
|
|
Loading…
Reference in a new issue