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) => {
// 1. get the long channel Id (make sure channel exists)
db.Certificate.getLongChannelId(channelName, channelClaimId)
@ -69,7 +69,7 @@ module.exports = {
return resolve(NO_CHANNEL);
}
// 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
resolve(paginatedChannelViewData);
})

View file

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

View file

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

View file

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

View file

@ -1,9 +1,10 @@
import React from 'react';
const AssetTitle = () => {
const AssetTitle = ({claimId}) => {
return (
<div>
<p>Show asset info here</p>
<p>claimId: {claimId}</p>
</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 NavBar from 'containers/NavBar';
import AssetPreview from 'components/AssetPreview';
import request from 'utils/request';
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 () {
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 () {
return (
<div>
<NavBar/>
{this.state.error ? (
<div className="row row--tall row--padded">
<div className="column column--10">
<h2>channelName: {this.props.channelName}</h2>
<h2>channelClaimId: {this.props.channelClaimId}</h2>
<p>{this.state.error}</p>
</div>
<div class="row row--padded">
<div class="row">
{((this.props.totalPages === 0) &&
<p>There is no content in {this.props.channelName}:{this.props.longChannelClaimId} yet. Upload some!
</p>)}
{((this.props.totalPages >= 1) &&
<div>
<p>Below are the contents for {this.channelName}:{this.longChannelClaimId}</p>
</div>
) : (
<div className="row row--tall row--padded">
<div className="column column--10">
<h2>channel name: {this.props.channelName}</h2>
<p>full channel id: {this.state.longChannelClaimId ? this.state.longChannelClaimId : 'loading...'}</p>
<p>short channel id: {this.state.shortChannelClaimId ? this.state.shortChannelClaimId : 'loading...'}</p>
<p># of claims in channel: {this.state.totalResults ? this.state.totalResults : 'loading...' }</p>
</div>
<div className="column column--10">
<div>
{/* claims here */}
</div>
</div>)}
{this.state.claims && this.state.claims.map((claim, index) => <AssetPreview claim={claim} key={index} />)}
</div>
</div>
</div>
)}
</div>
);
}
@ -39,9 +84,7 @@ class ShowChannel extends React.Component {
// required props
// channelName
// channelLongClaimId
// channelShortClaimId
// totalPages
// claims
// channelClaimId
export default ShowChannel;

View file

@ -14,15 +14,18 @@ class ShowDetailsPage extends React.Component {
<NavBar/>
<div className="row row--tall row--padded">
<div className="column column--10">
<AssetTitle title={'test title'}/>
<AssetTitle title={this.props.claimName}/>
</div>
<div className="column column--5 column--sml-10 align-content-top">
<div className="row row--padded">
<AssetDisplay/>
<AssetDisplay
claimName={this.props.claimName}
claimId={this.props.claimId}
/>
</div>
</div><div className="column column--5 column--sml-10 align-content-top">
<div className="row row--padded">
<AssetInfo />
<AssetInfo claimId={this.props.claimId}/>
</div>
</div>
</div>
@ -31,4 +34,11 @@ class ShowDetailsPage extends React.Component {
}
};
// required props
// isChannel
// channelName
// channelClaimId
// claimId
// claimName
export default ShowDetailsPage;

View file

@ -5,7 +5,10 @@ class ShowLitePage extends React.Component {
render () {
return (
<div className="row row--tall flex-container--column flex-container--center-center">
<AssetDisplay />
<AssetDisplay
claimName={this.props.claimName}
claimId={this.props.claimId}
/>
</div>
);
}

View file

@ -9,6 +9,9 @@ const { createPublishParams, parsePublishApiRequestBody, parsePublishApiRequestF
const errorHandlers = require('../helpers/errorHandlers.js');
const { sendGoogleAnalyticsTiming } = require('../helpers/statsHelpers.js');
const { authenticateIfNoUserToken } = require('../auth/authentication.js');
const { getChannelViewData } = require('../controllers/serveController.js');
const NO_CHANNEL = 'NO_CHANNEL';
module.exports = (app) => {
// route to run a claim_list request on the daemon
@ -185,4 +188,21 @@ module.exports = (app) => {
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 { getClaimId, getChannelViewData, getLocalFileRecord } = require('../controllers/serveController.js');
const { getClaimId, getLocalFileRecord } = require('../controllers/serveController.js');
const serveHelpers = require('../helpers/serveHelpers.js');
const { handleRequestError } = require('../helpers/errorHandlers.js');
const { postToStats } = require('../helpers/statsHelpers.js');
@ -25,25 +25,6 @@ function isValidShortIdOrClaimId (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}) {
return accept && accept.match(/text\/html/);
}
@ -75,31 +56,31 @@ function determineResponseType (isServeRequest, headers) {
return responseType;
}
function showAssetToClient (claimId, name, res) {
return Promise
.all([db.Claim.resolveClaim(name, claimId), db.Claim.getShortClaimIdFromLongClaimId(claimId, name)])
.then(([claimInfo, shortClaimId]) => {
// logger.debug('claimInfo:', claimInfo);
// logger.debug('shortClaimId:', shortClaimId);
return serveHelpers.showFile(claimInfo, shortClaimId, res);
})
.catch(error => {
throw error;
});
}
function showLiteAssetToClient (claimId, name, res) {
return Promise
.all([db.Claim.resolveClaim(name, claimId), db.Claim.getShortClaimIdFromLongClaimId(claimId, name)])
.then(([claimInfo, shortClaimId]) => {
// logger.debug('claimInfo:', claimInfo);
// logger.debug('shortClaimId:', shortClaimId);
return serveHelpers.showFileLite(claimInfo, shortClaimId, res);
})
.catch(error => {
throw error;
});
}
// function showAssetToClient (claimId, name, res) {
// return Promise
// .all([db.Claim.resolveClaim(name, claimId), db.Claim.getShortClaimIdFromLongClaimId(claimId, name)])
// .then(([claimInfo, shortClaimId]) => {
// // logger.debug('claimInfo:', claimInfo);
// // logger.debug('shortClaimId:', shortClaimId);
// return serveHelpers.showFile(claimInfo, shortClaimId, res);
// })
// .catch(error => {
// throw error;
// });
// }
//
// function showLiteAssetToClient (claimId, name, res) {
// return Promise
// .all([db.Claim.resolveClaim(name, claimId), db.Claim.getShortClaimIdFromLongClaimId(claimId, name)])
// .then(([claimInfo, shortClaimId]) => {
// // logger.debug('claimInfo:', claimInfo);
// // logger.debug('shortClaimId:', shortClaimId);
// return serveHelpers.showFileLite(claimInfo, shortClaimId, res);
// })
// .catch(error => {
// throw error;
// });
// }
function serveAssetToClient (claimId, name, res) {
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) {
// this is a patch for backwards compatability with '/name/claim_id' url format
if (isValidShortIdOrClaimId(name) && !isValidShortIdOrClaimId(identifier)) {
@ -161,20 +129,26 @@ module.exports = (app) => {
let responseType = determineResponseType(isServeRequest, headers);
// log the request data for debugging
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
getClaimId(channelName, channelClaimId, claimName, claimId)
.then(fullClaimId => {
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) {
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);
postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');
serveAssetToClient(fullClaimId, claimName, res);
// postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');
})
.catch(error => {
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
app.get('/:identifier', ({ headers, ip, originalUrl, params, query }, res) => {
@ -188,7 +162,6 @@ module.exports = (app) => {
// log the request data for debugging
logRequestData(null, null, channelName, null);
// handle showing the channel page
// showChannelPageToClient(channelName, channelClaimId, originalUrl, ip, query, res);
return res.status(200).render('index');
} else {
let claimName, isServeRequest;
@ -200,18 +173,24 @@ module.exports = (app) => {
let responseType = determineResponseType(isServeRequest, headers);
// log the request data for debugging
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
getClaimId(null, null, claimName, null)
.then(fullClaimId => {
if (fullClaimId === NO_CLAIM) {
return res.status(200).render('index');
}
showOrServeAsset(responseType, fullClaimId, claimName, res);
postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');
serveAssetToClient(fullClaimId, claimName, res);
// postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');
})
.catch(error => {
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 () {
const publishUrl = '/api/claim-publish';
const filePath = './test/mock-data/bird.jpeg';