350 open graph react #360
14 changed files with 141 additions and 35 deletions
|
@ -3,7 +3,7 @@ import { renderToString } from 'react-dom/server';
|
||||||
import { createStore } from 'redux';
|
import { createStore } from 'redux';
|
||||||
import Reducer from '../react/reducers';
|
import Reducer from '../react/reducers';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import StaticRouter from 'react-router-dom/StaticRouter';
|
import { StaticRouter } from 'react-router-dom';
|
||||||
import GAListener from '../react/components/GAListener';
|
import GAListener from '../react/components/GAListener';
|
||||||
import App from '../react/app';
|
import App from '../react/app';
|
||||||
import renderFullPage from './renderFullPage.js';
|
import renderFullPage from './renderFullPage.js';
|
||||||
|
@ -28,7 +28,7 @@ module.exports = (req, res) => {
|
||||||
// check for a redirect
|
// check for a redirect
|
||||||
if (context.url) {
|
if (context.url) {
|
||||||
// Somewhere a `<Redirect>` was rendered
|
// Somewhere a `<Redirect>` was rendered
|
||||||
res.redirect(301, context.url);
|
return res.redirect(301, context.url);
|
||||||
} else {
|
} else {
|
||||||
// we're good, send the response
|
// we're good, send the response
|
||||||
}
|
}
|
68
helpers/handleShowRender.jsx
Normal file
68
helpers/handleShowRender.jsx
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { renderToString } from 'react-dom/server';
|
||||||
|
import { createStore, applyMiddleware } from 'redux';
|
||||||
|
import Reducer from '../react/reducers';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import { StaticRouter, matchPath } from 'react-router-dom';
|
||||||
|
import GAListener from '../react/components/GAListener';
|
||||||
|
import App from '../react/app';
|
||||||
|
import renderFullPage from './renderFullPage';
|
||||||
|
import routes from '../react/routes';
|
||||||
|
import createSagaMiddleware from 'redux-saga';
|
||||||
|
import rootSaga from '../react/sagas';
|
||||||
|
|
||||||
|
module.exports = (req, res) => {
|
||||||
|
let context = {};
|
||||||
|
|
||||||
|
// create and apply middleware
|
||||||
|
const sagaMiddleware = createSagaMiddleware();
|
||||||
|
const middleware = applyMiddleware(sagaMiddleware);
|
||||||
|
|
||||||
|
// create a new Redux store instance
|
||||||
|
const store = createStore(Reducer, middleware);
|
||||||
|
|
||||||
|
// run the saga middlweare
|
||||||
|
sagaMiddleware.run(rootSaga);
|
||||||
|
|
||||||
|
// get data as promises
|
||||||
|
const promises = [];
|
||||||
|
routes.some(route => {
|
||||||
|
const match = matchPath(req.path, route);
|
||||||
|
if (match) {
|
||||||
|
let fetchData = route.component.fetchData;
|
||||||
|
if (fetchData instanceof Function) {
|
||||||
|
promises.push(fetchData(store, match));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
console.log('promises', promises);
|
||||||
|
|
||||||
|
// after promises have resolved, render the component
|
||||||
|
Promise.all(promises).then(data => {
|
||||||
|
console.log('data:', data);
|
||||||
|
// render component to a string
|
||||||
|
const html = renderToString(
|
||||||
|
<Provider store={store}>
|
||||||
|
<StaticRouter location={req.url} context={context}>
|
||||||
|
<GAListener>
|
||||||
|
<App />
|
||||||
|
</GAListener>
|
||||||
|
</StaticRouter>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
|
||||||
|
// check for a redirect
|
||||||
|
if (context.url) {
|
||||||
|
console.log('REDIRECTING:', context.url);
|
||||||
|
return res.redirect(301, context.url);
|
||||||
|
} else {
|
||||||
|
console.log(`we're good, send the response`, html);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the initial state from our Redux store
|
||||||
|
const preloadedState = store.getState();
|
||||||
|
|
||||||
|
// send the rendered page back to the client
|
||||||
|
res.send(renderFullPage(html, preloadedState));
|
||||||
|
});
|
||||||
|
};
|
|
@ -35,11 +35,13 @@
|
||||||
"config": "^1.26.1",
|
"config": "^1.26.1",
|
||||||
"connect-multiparty": "^2.0.0",
|
"connect-multiparty": "^2.0.0",
|
||||||
"cookie-session": "^2.0.0-beta.3",
|
"cookie-session": "^2.0.0-beta.3",
|
||||||
|
"cross-fetch": "^1.1.1",
|
||||||
"express": "^4.15.2",
|
"express": "^4.15.2",
|
||||||
"express-handlebars": "^3.0.0",
|
"express-handlebars": "^3.0.0",
|
||||||
"form-data": "^2.3.1",
|
"form-data": "^2.3.1",
|
||||||
"helmet": "^3.8.1",
|
"helmet": "^3.8.1",
|
||||||
"mysql2": "^1.3.5",
|
"mysql2": "^1.3.5",
|
||||||
|
"node-fetch": "^2.0.0",
|
||||||
"passport": "^0.4.0",
|
"passport": "^0.4.0",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
"prop-types": "^15.6.0",
|
"prop-types": "^15.6.0",
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { CHANNEL, ASSET_LITE, ASSET_DETAILS } from 'constants/show_request_types
|
||||||
|
|
||||||
// basic request parsing
|
// basic request parsing
|
||||||
export function handleShowPageUri (params) {
|
export function handleShowPageUri (params) {
|
||||||
|
console.log('dispatching handleShowpageUri');
|
||||||
return {
|
return {
|
||||||
type: actions.HANDLE_SHOW_URI,
|
type: actions.HANDLE_SHOW_URI,
|
||||||
data: params,
|
data: params,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import Request from 'utils/request';
|
import Request from 'utils/request';
|
||||||
|
const { site: { host } } = require('../../config/speechConfig.js');
|
||||||
|
|
||||||
export function getLongClaimId (name, modifier) {
|
export function getLongClaimId (name, modifier) {
|
||||||
// console.log('getting long claim id for asset:', name, modifier);
|
// console.log('getting long claim id for asset:', name, modifier);
|
||||||
|
@ -15,25 +16,23 @@ export function getLongClaimId (name, modifier) {
|
||||||
body['claimName'] = name;
|
body['claimName'] = name;
|
||||||
const params = {
|
const params = {
|
||||||
method : 'POST',
|
method : 'POST',
|
||||||
headers: new Headers({
|
headers: { 'Content-Type': 'application/json' },
|
||||||
'Content-Type': 'application/json',
|
body : JSON.stringify(body),
|
||||||
}),
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
};
|
};
|
||||||
// create url
|
// create url
|
||||||
const url = `/api/claim/long-id`;
|
const url = `${host}/api/claim/long-id`;
|
||||||
// return the request promise
|
// return the request promise
|
||||||
return Request(url, params);
|
return Request(url, params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getShortId (name, claimId) {
|
export function getShortId (name, claimId) {
|
||||||
// console.log('getting short id for asset:', name, claimId);
|
// console.log('getting short id for asset:', name, claimId);
|
||||||
const url = `/api/claim/short-id/${claimId}/${name}`;
|
const url = `${host}/api/claim/short-id/${claimId}/${name}`;
|
||||||
return Request(url);
|
return Request(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getClaimData (name, claimId) {
|
export function getClaimData (name, claimId) {
|
||||||
// console.log('getting claim data for asset:', name, claimId);
|
// console.log('getting claim data for asset:', name, claimId);
|
||||||
const url = `/api/claim/data/${name}/${claimId}`;
|
const url = `${host}/api/claim/data/${name}/${claimId}`;
|
||||||
return Request(url);
|
return Request(url);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
import Request from 'utils/request';
|
import Request from 'utils/request';
|
||||||
import request from '../utils/request';
|
import request from '../utils/request';
|
||||||
|
const { site: { host } } = require('../../config/speechConfig.js');
|
||||||
|
|
||||||
export function getChannelData (name, id) {
|
export function getChannelData (name, id) {
|
||||||
console.log('getting channel data for channel:', name, id);
|
console.log('getting channel data for channel:', name, id);
|
||||||
if (!id) id = 'none';
|
if (!id) id = 'none';
|
||||||
const url = `/api/channel/data/${name}/${id}`;
|
const url = `${host}/api/channel/data/${name}/${id}`;
|
||||||
return request(url);
|
return request(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
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 = `/api/channel/claims/${name}/${longId}/${page}`;
|
const url = `${host}/api/channel/claims/${name}/${longId}/${page}`;
|
||||||
return Request(url);
|
return Request(url);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import Request from 'utils/request';
|
import Request from 'utils/request';
|
||||||
|
const { site: { host } } = require('../../config/speechConfig.js');
|
||||||
|
|
||||||
export function checkFileAvailability (name, claimId) {
|
export function checkFileAvailability (name, claimId) {
|
||||||
const url = `/api/file/availability/${name}/${claimId}`;
|
const url = `${host}/api/file/availability/${name}/${claimId}`;
|
||||||
return Request(url);
|
return Request(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function triggerClaimGet (name, claimId) {
|
export function triggerClaimGet (name, claimId) {
|
||||||
const url = `/api/claim/get/${name}/${claimId}`;
|
const url = `${host}/api/claim/get/${name}/${claimId}`;
|
||||||
return Request(url);
|
return Request(url);
|
||||||
}
|
}
|
||||||
|
|
15
react/app.js
15
react/app.js
|
@ -1,20 +1,13 @@
|
||||||
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 routes from './routes';
|
||||||
import AboutPage from 'components/AboutPage';
|
|
||||||
import LoginPage from 'containers/LoginPage';
|
|
||||||
import ShowPage from 'containers/ShowPage';
|
|
||||||
import FourOhFourPage from 'components/FourOhFourPage';
|
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path='/' component={PublishPage} />
|
{routes.map((route, index) => (
|
||||||
<Route exact path='/about' component={AboutPage} />
|
<Route key={index}{...route} />
|
||||||
<Route exact path='/login' component={LoginPage} />
|
))}
|
||||||
<Route exact path='/:identifier/:claim' component={ShowPage} />
|
|
||||||
<Route exact path='/:claim' component={ShowPage} />
|
|
||||||
<Route component={FourOhFourPage} />
|
|
||||||
</Switch>
|
</Switch>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,15 @@ import ErrorPage from 'components/ErrorPage';
|
||||||
import ShowAssetLite from 'components/ShowAssetLite';
|
import ShowAssetLite from 'components/ShowAssetLite';
|
||||||
import ShowAssetDetails from 'components/ShowAssetDetails';
|
import ShowAssetDetails from 'components/ShowAssetDetails';
|
||||||
import ShowChannel from 'components/ShowChannel';
|
import ShowChannel from 'components/ShowChannel';
|
||||||
|
import { handleShowPageUri } from 'actions/show';
|
||||||
|
|
||||||
import { CHANNEL, ASSET_LITE, ASSET_DETAILS } from 'constants/show_request_types';
|
import { CHANNEL, ASSET_LITE, ASSET_DETAILS } from 'constants/show_request_types';
|
||||||
|
|
||||||
class ShowPage extends React.Component {
|
class ShowPage extends React.Component {
|
||||||
|
static fetchData (store, match) {
|
||||||
|
console.log('the store:', store);
|
||||||
|
return store.dispatch(handleShowPageUri(match.params));
|
||||||
|
}
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
this.props.handleShowPageUri(this.props.match.params);
|
this.props.handleShowPageUri(this.props.match.params);
|
||||||
}
|
}
|
||||||
|
|
33
react/routes.js
Normal file
33
react/routes.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import PublishPage from 'components/PublishPage';
|
||||||
|
import AboutPage from 'components/AboutPage';
|
||||||
|
import LoginPage from 'containers/LoginPage';
|
||||||
|
import ShowPage from 'containers/ShowPage';
|
||||||
|
import FourOhFourPage from 'components/FourOhFourPage';
|
||||||
|
|
||||||
|
const routes = [
|
||||||
|
{ path : '/',
|
||||||
|
exact : true,
|
||||||
|
component: PublishPage,
|
||||||
|
},
|
||||||
|
{ path : '/about',
|
||||||
|
exact : true,
|
||||||
|
component: AboutPage,
|
||||||
|
},
|
||||||
|
{ path : '/login',
|
||||||
|
exact : true,
|
||||||
|
component: LoginPage,
|
||||||
|
},
|
||||||
|
{ path : '/:identifier/:claim',
|
||||||
|
exact : true,
|
||||||
|
component: ShowPage,
|
||||||
|
},
|
||||||
|
{ path : '/:claim',
|
||||||
|
exact : true,
|
||||||
|
component: ShowPage,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: FourOhFourPage,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default routes;
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'cross-fetch/polyfill';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the JSON returned by a network request
|
* Parses the JSON returned by a network request
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
const { site } = require('../config/speechConfig.js');
|
const { site } = require('../config/speechConfig.js');
|
||||||
const handleRender = require('../helpers/handleRender.jsx');
|
const handlePageRender = require('../helpers/handlePageRender.jsx');
|
||||||
|
|
||||||
module.exports = (app) => {
|
module.exports = (app) => {
|
||||||
// route for the home page
|
// route for the home page
|
||||||
app.get('/', (req, res) => {
|
app.get('/', (req, res) => {
|
||||||
handleRender(req, res);
|
handlePageRender(req, res);
|
||||||
});
|
});
|
||||||
// route to display login page
|
// route to display login page
|
||||||
app.get('/login', (req, res) => {
|
app.get('/login', (req, res) => {
|
||||||
handleRender(req, res);
|
handlePageRender(req, res);
|
||||||
});
|
});
|
||||||
// route to show 'about' page
|
// route to show 'about' page
|
||||||
app.get('/about', (req, res) => {
|
app.get('/about', (req, res) => {
|
||||||
handleRender(req, res);
|
handlePageRender(req, res);
|
||||||
});
|
});
|
||||||
// route to display a list of the trending images
|
// route to display a list of the trending images
|
||||||
app.get('/trending', (req, res) => {
|
app.get('/trending', (req, res) => {
|
||||||
res.status(301).redirect('/popular');
|
res.status(301).redirect('/popular');
|
||||||
});
|
});
|
||||||
app.get('/popular', (req, res) => {
|
app.get('/popular', (req, res) => {
|
||||||
handleRender(req, res);
|
handlePageRender(req, res);
|
||||||
});
|
});
|
||||||
// route to display a list of the trending images
|
// route to display a list of the trending images
|
||||||
app.get('/new', (req, res) => {
|
app.get('/new', (req, res) => {
|
||||||
handleRender(req, res);
|
handlePageRender(req, res);
|
||||||
});
|
});
|
||||||
// route to send embedable video player (for twitter)
|
// route to send embedable video player (for twitter)
|
||||||
app.get('/embed/:claimId/:name', ({ params }, res) => {
|
app.get('/embed/:claimId/:name', ({ params }, res) => {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
const { sendGAServeEvent } = require('../helpers/googleAnalytics');
|
const { sendGAServeEvent } = require('../helpers/googleAnalytics');
|
||||||
|
|
||||||
const { determineResponseType, flipClaimNameAndIdForBackwardsCompatibility, logRequestData, getClaimIdAndServeAsset } = require('../helpers/serveHelpers.js');
|
const { determineResponseType, flipClaimNameAndIdForBackwardsCompatibility, logRequestData, getClaimIdAndServeAsset } = require('../helpers/serveHelpers.js');
|
||||||
const lbryUri = require('../helpers/lbryUri.js');
|
const lbryUri = require('../helpers/lbryUri.js');
|
||||||
|
const handleShowRender = require('../helpers/handleShowRender.jsx');
|
||||||
const SERVE = 'SERVE';
|
const SERVE = 'SERVE';
|
||||||
|
|
||||||
module.exports = (app) => {
|
module.exports = (app) => {
|
||||||
// route to serve a specific asset using the channel or claim id
|
// route to serve a specific asset using the channel or claim id
|
||||||
app.get('/:identifier/:claim', ({ headers, ip, originalUrl, params }, res) => {
|
app.get('/:identifier/:claim', (req, res) => {
|
||||||
|
const { headers, ip, originalUrl, params } = req;
|
||||||
// decide if this is a show request
|
// decide if this is a show request
|
||||||
let hasFileExtension;
|
let hasFileExtension;
|
||||||
try {
|
try {
|
||||||
|
@ -17,7 +17,8 @@ module.exports = (app) => {
|
||||||
}
|
}
|
||||||
let responseType = determineResponseType(hasFileExtension, headers);
|
let responseType = determineResponseType(hasFileExtension, headers);
|
||||||
if (responseType !== SERVE) {
|
if (responseType !== SERVE) {
|
||||||
return res.status(200).render('index');
|
// return res.status(200).render('index');
|
||||||
|
return handleShowRender(req, res);
|
||||||
}
|
}
|
||||||
// handle serve request
|
// handle serve request
|
||||||
// send google analytics
|
// send google analytics
|
||||||
|
|
|
@ -41,7 +41,7 @@ module.exports = [
|
||||||
__dirname: false,
|
__dirname: false,
|
||||||
},
|
},
|
||||||
externals: [nodeExternals()],
|
externals: [nodeExternals()],
|
||||||
entry : ['./server.js'],
|
entry : ['babel-polyfill', 'whatwg-fetch', './server.js'],
|
||||||
output : {
|
output : {
|
||||||
path : Path.resolve(__dirname),
|
path : Path.resolve(__dirname),
|
||||||
publicPath: '/',
|
publicPath: '/',
|
||||||
|
|
Loading…
Reference in a new issue