implemented basica channel content request routes

This commit is contained in:
bill bittner 2018-01-30 11:46:22 -08:00
parent fa5c811dab
commit 091d073d01
12 changed files with 215 additions and 125 deletions

View file

@ -53,7 +53,7 @@ module.exports = {
}); });
}); });
}, },
getChannelViewData (channelName, channelClaimId, query) { getChannelViewData (channelName, channelClaimId, page) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// 1. get the long channel Id (make sure channel exists) // 1. get the long channel Id (make sure channel exists)
db.Certificate.getLongChannelId(channelName, channelClaimId) db.Certificate.getLongChannelId(channelName, channelClaimId)
@ -69,7 +69,7 @@ module.exports = {
return resolve(NO_CHANNEL); return resolve(NO_CHANNEL);
} }
// 3. format the data for the view, including pagination // 3. format the data for the view, including pagination
let paginatedChannelViewData = returnPaginatedChannelViewData(channelName, longChannelClaimId, shortChannelClaimId, channelClaimsArray, query); let paginatedChannelViewData = returnPaginatedChannelViewData(channelName, longChannelClaimId, shortChannelClaimId, channelClaimsArray, page);
// 4. return all the channel information and contents // 4. return all the channel information and contents
resolve(paginatedChannelViewData); resolve(paginatedChannelViewData);
}) })

View file

@ -1,9 +1,9 @@
const CLAIMS_PER_PAGE = 10; const CLAIMS_PER_PAGE = 10;
module.exports = { module.exports = {
returnPaginatedChannelViewData (channelName, longChannelClaimId, shortChannelClaimId, claims, query) { returnPaginatedChannelViewData (channelName, longChannelClaimId, shortChannelClaimId, claims, page) {
const totalPages = module.exports.determineTotalPages(claims); const totalPages = module.exports.determineTotalPages(claims);
const paginationPage = module.exports.getPageFromQuery(query); const paginationPage = module.exports.getPageFromQuery(page);
const viewData = { const viewData = {
channelName : channelName, channelName : channelName,
longChannelClaimId : longChannelClaimId, longChannelClaimId : longChannelClaimId,
@ -17,9 +17,9 @@ module.exports = {
}; };
return viewData; return viewData;
}, },
getPageFromQuery (query) { getPageFromQuery (page) {
if (query.p) { if (page) {
return parseInt(query.p); return parseInt(page);
} }
return 1; return 1;
}, },

View file

@ -100,7 +100,7 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => {
}; };
Certificate.getShortChannelIdFromLongChannelId = function (longChannelId, channelName) { Certificate.getShortChannelIdFromLongChannelId = function (longChannelId, channelName) {
logger.debug(`finding short channel id for ${channelName}:${longChannelId}`); logger.debug(`getShortChannelIdFromLongChannelId ${channelName}:${longChannelId}`);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this this
.findAll({ .findAll({
@ -122,6 +122,7 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => {
}; };
Certificate.getLongChannelIdFromShortChannelId = function (channelName, channelClaimId) { Certificate.getLongChannelIdFromShortChannelId = function (channelName, channelClaimId) {
logger.debug(`getLongChannelIdFromShortChannelId(${channelName}, ${channelClaimId})`);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this this
.findAll({ .findAll({
@ -170,6 +171,7 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => {
}; };
Certificate.validateLongChannelId = function (name, claimId) { Certificate.validateLongChannelId = function (name, claimId) {
logger.debug(`validateLongChannelId(${name}, ${claimId})`);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.findOne({ this.findOne({
where: {name, claimId}, where: {name, claimId},

View file

@ -1,9 +1,9 @@
import React from 'react'; import React from 'react';
const AssetDisplay = () => { const AssetDisplay = ({claimName, claimId}) => {
return ( return (
<div> <div>
<p>display asset here</p> <p>display {claimName}#{claimId} here</p>
</div> </div>
); );
}; };

View file

@ -1,9 +1,10 @@
import React from 'react'; import React from 'react';
const AssetTitle = () => { const AssetTitle = ({claimId}) => {
return ( return (
<div> <div>
<p>Show asset info here</p> <p>Show asset info here</p>
<p>claimId: {claimId}</p>
</div> </div>
); );
}; };

View file

@ -0,0 +1,12 @@
import React from 'react';
const AssetPreview = ({asset}) => {
console.log('asset display info:', asset);
return (
<div>
<p>Preview Asset here</p>
</div>
);
};
export default AssetPreview;

View file

@ -1,37 +1,82 @@
import React from 'react'; import React from 'react';
import NavBar from 'containers/NavBar'; import NavBar from 'containers/NavBar';
import AssetPreview from 'components/AssetPreview';
import request from 'utils/request';
class ShowChannel extends React.Component { class ShowChannel extends React.Component {
constructor (props) {
super(props);
this.state = {
error : null,
channelName : null,
claims : null,
currentPage : null,
longChannelClaimId : null,
nextPage : null,
previousPage : null,
shortChannelClaimId: null,
totalPages : null,
totalResults : null,
};
this.updateChannelData = this.updateChannelData.bind(this);
}
componentDidMount () { componentDidMount () {
console.log(this.props); console.log(this.props);
this.updateChannelData(1);
}
updateChannelData (page) {
const that = this;
const channelName = this.props.channelName;
const channelClaimId = this.props.channelClaimId || 'none';
const url = `/api/channel-get-content/${channelName}/${channelClaimId}/${page}`;
return request(url)
.then(({ success, message, data }) => {
console.log('get channel data response:', data);
if (!success) {
return this.setState({error: message});
}
that.setState({
channelName : data.channelName,
claims : data.claims,
currentPage : data.currentPage,
longChannelClaimId : data.longChannelClaimId,
nextPage : data.nextPage,
previousPage : data.previousPage,
shortChannelClaimId: data.shortChannelClaimId,
totalPages : data.totalPages,
totalResults : data.totalResults,
});
})
.catch((error) => {
that.setState({error: error.message});
});
} }
render () { render () {
return ( return (
<div> <div>
<NavBar/> <NavBar/>
{this.state.error ? (
<div className="row row--tall row--padded"> <div className="row row--tall row--padded">
<div className="column column--10"> <div className="column column--10">
<h2>channelName: {this.props.channelName}</h2> <p>{this.state.error}</p>
<h2>channelClaimId: {this.props.channelClaimId}</h2>
</div> </div>
<div class="row row--padded"> </div>
<div class="row"> ) : (
<div className="row row--tall row--padded">
{((this.props.totalPages === 0) && <div className="column column--10">
<p>There is no content in {this.props.channelName}:{this.props.longChannelClaimId} yet. Upload some! <h2>channel name: {this.props.channelName}</h2>
</p>)} <p>full channel id: {this.state.longChannelClaimId ? this.state.longChannelClaimId : 'loading...'}</p>
<p>short channel id: {this.state.shortChannelClaimId ? this.state.shortChannelClaimId : 'loading...'}</p>
{((this.props.totalPages >= 1) && <p># of claims in channel: {this.state.totalResults ? this.state.totalResults : 'loading...' }</p>
<div> </div>
<p>Below are the contents for {this.channelName}:{this.longChannelClaimId}</p> <div className="column column--10">
<div> <div>
{/* claims here */} {/* claims here */}
</div> {this.state.claims && this.state.claims.map((claim, index) => <AssetPreview claim={claim} key={index} />)}
</div>)}
</div> </div>
</div> </div>
</div> </div>
)}
</div> </div>
); );
} }
@ -39,9 +84,7 @@ class ShowChannel extends React.Component {
// required props // required props
// channelName // channelName
// channelLongClaimId // channelClaimId
// channelShortClaimId
// totalPages
// claims
export default ShowChannel; export default ShowChannel;

View file

@ -14,15 +14,18 @@ class ShowDetailsPage extends React.Component {
<NavBar/> <NavBar/>
<div className="row row--tall row--padded"> <div className="row row--tall row--padded">
<div className="column column--10"> <div className="column column--10">
<AssetTitle title={'test title'}/> <AssetTitle title={this.props.claimName}/>
</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
claimName={this.props.claimName}
claimId={this.props.claimId}
/>
</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 claimId={this.props.claimId}/>
</div> </div>
</div> </div>
</div> </div>
@ -31,4 +34,11 @@ class ShowDetailsPage extends React.Component {
} }
}; };
// required props
// isChannel
// channelName
// channelClaimId
// claimId
// claimName
export default ShowDetailsPage; export default ShowDetailsPage;

View file

@ -5,7 +5,10 @@ class ShowLitePage extends React.Component {
render () { render () {
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">
<AssetDisplay /> <AssetDisplay
claimName={this.props.claimName}
claimId={this.props.claimId}
/>
</div> </div>
); );
} }

View file

@ -9,6 +9,9 @@ const { createPublishParams, parsePublishApiRequestBody, parsePublishApiRequestF
const errorHandlers = require('../helpers/errorHandlers.js'); const errorHandlers = require('../helpers/errorHandlers.js');
const { sendGoogleAnalyticsTiming } = require('../helpers/statsHelpers.js'); const { sendGoogleAnalyticsTiming } = require('../helpers/statsHelpers.js');
const { authenticateIfNoUserToken } = require('../auth/authentication.js'); const { authenticateIfNoUserToken } = require('../auth/authentication.js');
const { getChannelViewData } = require('../controllers/serveController.js');
const NO_CHANNEL = 'NO_CHANNEL';
module.exports = (app) => { module.exports = (app) => {
// route to run a claim_list request on the daemon // route to run a claim_list request on the daemon
@ -185,4 +188,21 @@ module.exports = (app) => {
errorHandlers.handleApiError(originalUrl, ip, error, res); errorHandlers.handleApiError(originalUrl, ip, error, res);
}); });
}); });
app.get('/api/channel-get-content/:name/:longId/:page', ({ ip, originalUrl, body, params }, res) => {
const channelName = params.name;
let channelClaimId = params.longId;
if (channelClaimId === 'none') channelClaimId = null;
const page = params.page;
getChannelViewData(channelName, channelClaimId, page)
.then(data => {
if (data === NO_CHANNEL) {
return res.status(200).json({success: false, message: 'No matching channel was found'});
}
res.status(200).json({success: true, data});
})
.catch(error => {
logger.error('api error getting channel contents', error);
errorHandlers.handleApiError(originalUrl, ip, error, res);
});
});
}; };

View file

@ -1,5 +1,5 @@
const logger = require('winston'); const logger = require('winston');
const { getClaimId, getChannelViewData, getLocalFileRecord } = require('../controllers/serveController.js'); const { getClaimId, getLocalFileRecord } = require('../controllers/serveController.js');
const serveHelpers = require('../helpers/serveHelpers.js'); const serveHelpers = require('../helpers/serveHelpers.js');
const { handleRequestError } = require('../helpers/errorHandlers.js'); const { handleRequestError } = require('../helpers/errorHandlers.js');
const { postToStats } = require('../helpers/statsHelpers.js'); const { postToStats } = require('../helpers/statsHelpers.js');
@ -25,25 +25,6 @@ function isValidShortIdOrClaimId (input) {
return (isValidClaimId(input) || isValidShortId(input)); return (isValidClaimId(input) || isValidShortId(input));
} }
function sendChannelInfoAndContentToClient (channelPageData, res) {
if (channelPageData === NO_CHANNEL) {
res.status(200).render('noChannel');
} else {
res.status(200).render('channel', channelPageData);
}
}
function showChannelPageToClient (channelName, channelClaimId, originalUrl, ip, query, res) {
// 1. retrieve the channel contents
getChannelViewData(channelName, channelClaimId, query)
.then(channelViewData => {
sendChannelInfoAndContentToClient(channelViewData, res);
})
.catch(error => {
handleRequestError(originalUrl, ip, error, res);
});
}
function clientAcceptsHtml ({accept}) { function clientAcceptsHtml ({accept}) {
return accept && accept.match(/text\/html/); return accept && accept.match(/text\/html/);
} }
@ -75,31 +56,31 @@ function determineResponseType (isServeRequest, headers) {
return responseType; return responseType;
} }
function showAssetToClient (claimId, name, res) { // function showAssetToClient (claimId, name, res) {
return Promise // return Promise
.all([db.Claim.resolveClaim(name, claimId), db.Claim.getShortClaimIdFromLongClaimId(claimId, name)]) // .all([db.Claim.resolveClaim(name, claimId), db.Claim.getShortClaimIdFromLongClaimId(claimId, name)])
.then(([claimInfo, shortClaimId]) => { // .then(([claimInfo, shortClaimId]) => {
// logger.debug('claimInfo:', claimInfo); // // logger.debug('claimInfo:', claimInfo);
// logger.debug('shortClaimId:', shortClaimId); // // logger.debug('shortClaimId:', shortClaimId);
return serveHelpers.showFile(claimInfo, shortClaimId, res); // return serveHelpers.showFile(claimInfo, shortClaimId, res);
}) // })
.catch(error => { // .catch(error => {
throw error; // throw error;
}); // });
} // }
//
function showLiteAssetToClient (claimId, name, res) { // function showLiteAssetToClient (claimId, name, res) {
return Promise // return Promise
.all([db.Claim.resolveClaim(name, claimId), db.Claim.getShortClaimIdFromLongClaimId(claimId, name)]) // .all([db.Claim.resolveClaim(name, claimId), db.Claim.getShortClaimIdFromLongClaimId(claimId, name)])
.then(([claimInfo, shortClaimId]) => { // .then(([claimInfo, shortClaimId]) => {
// logger.debug('claimInfo:', claimInfo); // // logger.debug('claimInfo:', claimInfo);
// logger.debug('shortClaimId:', shortClaimId); // // logger.debug('shortClaimId:', shortClaimId);
return serveHelpers.showFileLite(claimInfo, shortClaimId, res); // return serveHelpers.showFileLite(claimInfo, shortClaimId, res);
}) // })
.catch(error => { // .catch(error => {
throw error; // throw error;
}); // });
} // }
function serveAssetToClient (claimId, name, res) { function serveAssetToClient (claimId, name, res) {
return getLocalFileRecord(claimId, name) return getLocalFileRecord(claimId, name)
@ -115,19 +96,6 @@ function serveAssetToClient (claimId, name, res) {
}); });
} }
function showOrServeAsset (responseType, claimId, claimName, res) {
switch (responseType) {
case SHOW:
return showAssetToClient(claimId, claimName, res);
case SHOWLITE:
return showLiteAssetToClient(claimId, claimName, res);
case SERVE:
return serveAssetToClient(claimId, claimName, res);
default:
break;
}
}
function flipClaimNameAndIdForBackwardsCompatibility (identifier, name) { function flipClaimNameAndIdForBackwardsCompatibility (identifier, name) {
// this is a patch for backwards compatability with '/name/claim_id' url format // this is a patch for backwards compatability with '/name/claim_id' url format
if (isValidShortIdOrClaimId(name) && !isValidShortIdOrClaimId(identifier)) { if (isValidShortIdOrClaimId(name) && !isValidShortIdOrClaimId(identifier)) {
@ -161,20 +129,26 @@ module.exports = (app) => {
let responseType = determineResponseType(isServeRequest, headers); let responseType = determineResponseType(isServeRequest, headers);
// log the request data for debugging // log the request data for debugging
logRequestData(responseType, claimName, channelName, claimId); logRequestData(responseType, claimName, channelName, claimId);
// if a serve request, serve, otherwise send the react app
if (responseType === SERVE) {
// get the claim Id and then serve/show the asset // get the claim Id and then serve/show the asset
getClaimId(channelName, channelClaimId, claimName, claimId) getClaimId(channelName, channelClaimId, claimName, claimId)
.then(fullClaimId => { .then(fullClaimId => {
if (fullClaimId === NO_CLAIM) { if (fullClaimId === NO_CLAIM) {
return res.status(200).render('noClaim'); return res.status(200).json({success: false, message: 'no claim id could be found'});
} else if (fullClaimId === NO_CHANNEL) { } else if (fullClaimId === NO_CHANNEL) {
return res.status(200).render('noChannel'); return res.status(200).json({success: false, message: 'no channel id could be found'});
} }
showOrServeAsset(responseType, fullClaimId, claimName, res); serveAssetToClient(fullClaimId, claimName, res);
postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success'); // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');
}) })
.catch(error => { .catch(error => {
handleRequestError(originalUrl, ip, error, res); handleRequestError(originalUrl, ip, error, res);
// postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');
}); });
} else {
res.status(200).render('index');
}
}); });
// route to serve the winning asset at a claim or a channel page // route to serve the winning asset at a claim or a channel page
app.get('/:identifier', ({ headers, ip, originalUrl, params, query }, res) => { app.get('/:identifier', ({ headers, ip, originalUrl, params, query }, res) => {
@ -188,7 +162,6 @@ module.exports = (app) => {
// log the request data for debugging // log the request data for debugging
logRequestData(null, null, channelName, null); logRequestData(null, null, channelName, null);
// handle showing the channel page // handle showing the channel page
// showChannelPageToClient(channelName, channelClaimId, originalUrl, ip, query, res);
return res.status(200).render('index'); return res.status(200).render('index');
} else { } else {
let claimName, isServeRequest; let claimName, isServeRequest;
@ -200,18 +173,24 @@ module.exports = (app) => {
let responseType = determineResponseType(isServeRequest, headers); let responseType = determineResponseType(isServeRequest, headers);
// log the request data for debugging // log the request data for debugging
logRequestData(responseType, claimName, null, null); logRequestData(responseType, claimName, null, null);
// if a serve request, serve, otherwise send the react app
if (responseType === SERVE) {
// get the claim Id and then serve/show the asset // get the claim Id and then serve/show the asset
getClaimId(null, null, claimName, null) getClaimId(null, null, claimName, null)
.then(fullClaimId => { .then(fullClaimId => {
if (fullClaimId === NO_CLAIM) { if (fullClaimId === NO_CLAIM) {
return res.status(200).render('index'); return res.status(200).render('index');
} }
showOrServeAsset(responseType, fullClaimId, claimName, res); serveAssetToClient(fullClaimId, claimName, res);
postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success'); // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');
}) })
.catch(error => { .catch(error => {
handleRequestError(originalUrl, ip, error, res); handleRequestError(originalUrl, ip, error, res);
// postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');
}); });
} else {
res.status(200).render('index');
}
} }
}); });
}; };

View file

@ -84,6 +84,26 @@ describe('end-to-end', function () {
}); });
}); });
describe('channel data request from client', function () {
const url = '/@test';
const urlWithShortClaimId = '/@test:3';
const urlWithMediumClaimId = '/@test:3b5bc6b6819172c6';
const urlWithLongClaimId = '/@test:3b5bc6b6819172c6e2f3f90aa855b14a956b4a82';
describe(url, function () {
it('should pass the tests I write here');
});
describe(urlWithShortClaimId, function () {
it('should pass the tests I write here');
});
describe(urlWithMediumClaimId, function () {
it('should pass the tests I write here');
});
describe(urlWithLongClaimId, function () {
it('should pass the tests I write here');
});
});
describe('publish requests', function () { describe('publish requests', function () {
const publishUrl = '/api/claim-publish'; const publishUrl = '/api/claim-publish';
const filePath = './test/mock-data/bird.jpeg'; const filePath = './test/mock-data/bird.jpeg';