350 open graph react #360

Merged
bones7242 merged 30 commits from 350-open-graph-react into master 2018-02-24 17:55:00 +01:00
14 changed files with 141 additions and 35 deletions
Showing only changes of commit 14740341e3 - Show all commits

View file

@ -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
} }

View 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));
});
};

View file

@ -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",

View file

@ -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,

View file

@ -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);
}; };

View file

@ -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);
}; };

View file

@ -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);
} }

View file

@ -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>
); );
}; };

View file

@ -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
View 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;

View file

@ -1,3 +1,5 @@
import 'cross-fetch/polyfill';
/** /**
* Parses the JSON returned by a network request * Parses the JSON returned by a network request
* *

View file

@ -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) => {

View file

@ -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

View file

@ -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: '/',