From 1a7b716820b8c103e2366f69611b9a901a67123c Mon Sep 17 00:00:00 2001 From: David Jay Date: Mon, 14 Nov 2016 15:51:17 -0500 Subject: [PATCH 1/5] Updating stream endpoint to expect asset_url and to return asset. --- routes/api/stream/index.js | 26 ++++++++++++++++-------- tests/routes/api/stream/index.js | 35 +++++++++++++++++--------------- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/routes/api/stream/index.js b/routes/api/stream/index.js index 3f49d48fc..db1d2bc36 100644 --- a/routes/api/stream/index.js +++ b/routes/api/stream/index.js @@ -3,35 +3,45 @@ const express = require('express'); const Comment = require('../../../models/comment'); const User = require('../../../models/user'); const Action = require('../../../models/action'); +const Asset = require('../../../models/asset'); const Setting = require('../../../models/setting'); const router = express.Router(); -// Find all the comments by a specific asset_id. +// Find all the comments by a specific asset_url. // . if pre: get the comments that are accepted. // . if post: get the comments that are new and accepted. router.get('/', (req, res, next) => { - const commentsPromise = Setting.getModerationSetting().then(({moderation}) => { + + // Get the asset_id for this url (or create it if it doesn't exist) + Promise.all([ + Asset.findOrCreateByUrl(req.query.asset_url), + Setting.getModerationSetting() + ]) + .then(([asset, {moderation}]) => { + // Get the sitewide moderation setting and return the appropriate comments switch(moderation){ case 'pre': - return Comment.findAcceptedByAssetId(req.query.asset_id); + return Promise.all([Comment.findAcceptedByAssetId(asset.id), asset]); case 'post': - return Comment.findAcceptedAndNewByAssetId(req.query.asset_id); + return Promise.all([Comment.findAcceptedAndNewByAssetId(asset.id), asset]); default: throw new Error('Moderation setting not found.'); } - }); - + }) // Get all the users and actions for those comments. - commentsPromise.then(comments => { + .then(([comments, asset]) => { return Promise.all([ + [asset], comments, User.findByIdArray(comments.map((comment) => comment.author_id)), Action.getActionSummaries(comments.map((comment) => comment.id)) ]); - }).then(([comments, users, actions]) => { + }) + .then(([assets, comments, users, actions]) => { res.json({ + assets, comments, users, actions diff --git a/tests/routes/api/stream/index.js b/tests/routes/api/stream/index.js index c967cb932..009184b6b 100644 --- a/tests/routes/api/stream/index.js +++ b/tests/routes/api/stream/index.js @@ -11,6 +11,7 @@ chai.use(require('chai-http')); const Action = require('../../../../models/action'); const User = require('../../../../models/user'); const Comment = require('../../../../models/comment'); +const Asset = require('../../../../models/asset'); const Setting = require('../../../../models/setting'); @@ -21,14 +22,12 @@ describe('api/stream: routes', () => { const comments = [{ id: 'abc', body: 'comment 10', - asset_id: 'asset', author_id: '', parent_id: '', status: 'accepted' }, { id: 'def', body: 'comment 20', - asset_id: 'asset', author_id: '', parent_id: '', status: '' @@ -66,29 +65,33 @@ describe('api/stream: routes', () => { beforeEach(() => { - return User - .createLocalUsers(users) - .then(users => { + return Promise.all([ + User.createLocalUsers(users), + Asset.findOrCreateByUrl('http://test.com') + ]) + .then(([users, asset]) => { - comments[0].author_id = users[0].id; - comments[1].author_id = users[1].id; - - return Promise.all([ - Comment.create(comments), - Action.create(actions), - Setting.create(settings) - ]); + comments[0].author_id = users[0].id; + comments[1].author_id = users[1].id; - }); + comments[0].asset_id = asset.id; + comments[1].asset_id = asset.id; + return Promise.all([ + Comment.create(comments), + Action.create(actions), + Setting.create(settings) + ]); + }); }); - it('should return a stream with comments, users and actions', () => { + it('should return a stream with comments, users and actions for an existing asset', () => { return chai.request(app) .get('/api/v1/stream') - .query({'asset_id': 'asset'}) + .query({'asset_url': 'http://test.com'}) .then(res => { expect(res).to.have.status(200); + expect(res.body.assets.length).to.equal(1); expect(res.body.comments.length).to.equal(1); expect(res.body.users.length).to.equal(1); expect(res.body.actions.length).to.equal(1); From 688fbd0bf68aa2e0c0290e4bf415e5ca4b93c330 Mon Sep 17 00:00:00 2001 From: David Jay Date: Mon, 14 Nov 2016 16:40:04 -0500 Subject: [PATCH 2/5] Sending asset_url to backend and retreiving stream with asset. --- .../coral-embed-stream/src/CommentStream.js | 22 +++++-------------- client/coral-framework/store/actions/items.js | 11 +++++----- .../CommentCount.js | 2 +- routes/api/stream/index.js | 2 +- .../coral-framework/store/itemActions.spec.js | 15 ++++++++----- 5 files changed, 21 insertions(+), 31 deletions(-) diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index 9a1910105..5fb48d0a0 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -76,28 +76,16 @@ class CommentStream extends Component { componentDidMount () { // Set up messaging between embedded Iframe an parent component // Using recommended Pym init code which violates .eslint standards - new Pym.Child({polling: 500}); - this.props.getStream('assetTest'); + const pym = new Pym.Child({polling: 100}); + console.log(pym); + this.props.getStream('http://www.test.com'); } render () { - if (Object.keys(this.props.items).length === 0) { - // Loading mock asset - this.props.postItem({ - comments: [], - url: 'http://coralproject.net' - }, 'asset', 'assetTest'); - - // Loading mock user - this.props.postItem({name: 'Ban Ki-Moon'}, 'user', 'user_8989') - .then((id) => { - this.props.setLoggedInUser(id); - }); - } // TODO: Replace teststream id with id from params - const rootItemId = 'assetTest'; + const rootItemId = this.props.items.assets && Object.keys(this.props.items.assets)[0]; const rootItem = this.props.items.assets && this.props.items.assets[rootItemId]; return
{ @@ -117,7 +105,7 @@ class CommentStream extends Component { reply={false}/>
{ - rootItem.comments.map((commentId) => { + rootItem.comments && rootItem.comments.map((commentId) => { const comment = this.props.items.comments[commentId]; return

diff --git a/client/coral-framework/store/actions/items.js b/client/coral-framework/store/actions/items.js index 648a1d95e..eea3315b0 100644 --- a/client/coral-framework/store/actions/items.js +++ b/client/coral-framework/store/actions/items.js @@ -77,9 +77,9 @@ export const appendItemArray = (id, property, value, add_to_front, item_type) => * @dispatches * A set of items to the item store */ -export function getStream (assetId) { +export function getStream (assetUrl) { return (dispatch) => { - return fetch(`/api/v1/stream?asset_id=${assetId}`) + return fetch(`/api/v1/stream?asset_url=${encodeURIComponent(assetUrl)}`) .then( response => { return response.ok ? response.json() : Promise.reject(`${response.status} ${response.statusText}`); @@ -95,6 +95,8 @@ export function getStream (assetId) { } } + const assetId = json.assets[0].id; + /* Sort comments by date*/ json.comments.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()); const rels = json.comments.reduce((h, item) => { @@ -112,10 +114,7 @@ export function getStream (assetId) { return h; }, {rootComments: [], childComments: {}}); - dispatch(addItem({ - id: assetId, - comments: rels.rootComments, - }, 'assets')); + dispatch(updateItem(assetId, 'comments', rels.rootComments, 'assets')); const childKeys = Object.keys(rels.childComments); for (let i = 0; i < childKeys.length; i++ ) { diff --git a/client/coral-plugin-comment-count/CommentCount.js b/client/coral-plugin-comment-count/CommentCount.js index 6786d5c74..7a27c1982 100644 --- a/client/coral-plugin-comment-count/CommentCount.js +++ b/client/coral-plugin-comment-count/CommentCount.js @@ -5,7 +5,7 @@ const name = 'coral-plugin-comment-count'; const CommentCount = ({items, id}) => { let count = 0; - if (items.assets[id]) { + if (items.assets[id] && items.assets[id].comments) { count += items.assets[id].comments.length; } const itemKeys = Object.keys(items.comments); diff --git a/routes/api/stream/index.js b/routes/api/stream/index.js index db1d2bc36..b093f0d31 100644 --- a/routes/api/stream/index.js +++ b/routes/api/stream/index.js @@ -16,7 +16,7 @@ router.get('/', (req, res, next) => { // Get the asset_id for this url (or create it if it doesn't exist) Promise.all([ - Asset.findOrCreateByUrl(req.query.asset_url), + Asset.findOrCreateByUrl(decodeURIComponent(req.query.asset_url)), Setting.getModerationSetting() ]) .then(([asset, {moderation}]) => { diff --git a/tests/client/coral-framework/store/itemActions.spec.js b/tests/client/coral-framework/store/itemActions.spec.js index 33fe15cab..d6ce0c970 100644 --- a/tests/client/coral-framework/store/itemActions.spec.js +++ b/tests/client/coral-framework/store/itemActions.spec.js @@ -18,8 +18,11 @@ describe('itemActions', () => { }); describe('getStream', () => { - const rootId = '1234'; + const assetUrl = 'http://www.test.com'; const response = { + assets: [{ + id: '1234', url: assetUrl + }], comments: [ {body: 'stuff', id: '123'}, {body: 'morestuff', id: '456'} @@ -42,17 +45,17 @@ describe('itemActions', () => { it('should get an stream from an asset_id and send the appropriate dispatches', () => { fetchMock.get('*', JSON.stringify(response)); - return actions.getStream(rootId)(store.dispatch) + return actions.getStream(assetUrl)(store.dispatch) .then((res) => { - expect(fetchMock.calls().matched[0][0]).to.equal('/api/v1/stream?asset_id=1234'); + expect(fetchMock.calls().matched[0][0]).to.equal('/api/v1/stream?asset_url=http%3A%2F%2Fwww.test.com'); expect(res).to.deep.equal(response); - expect(store.getActions()[0]).to.deep.equal({ + expect(store.getActions()[1]).to.deep.equal({ type: actions.ADD_ITEM, item: response.comments[0], item_type: 'comments', id: '123' }); - expect(store.getActions()[1]).to.deep.equal({ + expect(store.getActions()[2]).to.deep.equal({ type: actions.ADD_ITEM, item: response.comments[1], item_type: 'comments', @@ -62,7 +65,7 @@ describe('itemActions', () => { }); it('should handle an error', () => { fetchMock.get('*', 404); - return actions.getStream(rootId)(store.dispatch) + return actions.getStream(assetUrl)(store.dispatch) .catch((err) => { expect(err).to.be.truthy; }); From 16fa3e46f56af90ebf12f5e8fa1508070d94649b Mon Sep 17 00:00:00 2001 From: David Jay Date: Mon, 14 Nov 2016 16:51:54 -0500 Subject: [PATCH 3/5] Loading comment stream based on parent URL. --- client/coral-embed-stream/src/CommentStream.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index 5fb48d0a0..aa58b5103 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -77,8 +77,7 @@ class CommentStream extends Component { // Set up messaging between embedded Iframe an parent component // Using recommended Pym init code which violates .eslint standards const pym = new Pym.Child({polling: 100}); - console.log(pym); - this.props.getStream('http://www.test.com'); + this.props.getStream(pym.parentUrl); } render () { From 14405b22aaa44b32e404fb93eaa92c29d8f94c36 Mon Sep 17 00:00:00 2001 From: David Jay Date: Mon, 14 Nov 2016 20:02:01 -0500 Subject: [PATCH 4/5] Stripping out protocol and query from asset url. --- client/coral-embed-stream/src/CommentStream.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index aa58b5103..06253b72f 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -77,7 +77,8 @@ class CommentStream extends Component { // Set up messaging between embedded Iframe an parent component // Using recommended Pym init code which violates .eslint standards const pym = new Pym.Child({polling: 100}); - this.props.getStream(pym.parentUrl); + const path = /https?\:\/\/([^?]+)/.exec(pym.parentUrl)[1]; + this.props.getStream(path); } render () { From 4fd41704c090d57f4bf903489db464de0f608891 Mon Sep 17 00:00:00 2001 From: David Jay Date: Tue, 15 Nov 2016 12:31:30 -0500 Subject: [PATCH 5/5] Moving preview to embed code. --- views/embed-stream.ejs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/views/embed-stream.ejs b/views/embed-stream.ejs index 47bda6bee..36f7ce43b 100644 --- a/views/embed-stream.ejs +++ b/views/embed-stream.ejs @@ -17,7 +17,12 @@ -
- +
+ + +
+