);
}
diff --git a/client/coral-admin/src/containers/CommentStream/CommentStream.js b/client/coral-admin/src/containers/CommentStream/CommentStream.js
index b1e002549..113a7bc86 100644
--- a/client/coral-admin/src/containers/CommentStream/CommentStream.js
+++ b/client/coral-admin/src/containers/CommentStream/CommentStream.js
@@ -40,7 +40,7 @@ class CommentStream extends React.Component {
}
// Render the comment box along with the CommentList
- render ({comments}, {snackbar, snackbarMsg}) {
+ render ({comments, users}, {snackbar, snackbarMsg}) {
return (
@@ -48,6 +48,7 @@ class CommentStream extends React.Component {
singleView={false}
commentIds={comments.get('ids')}
comments={comments.get('byId')}
+ users={users.get('byId')}
onClickAction={this.onClickAction}
actions={['flag']}
loading={comments.loading} />
@@ -57,4 +58,4 @@ class CommentStream extends React.Component {
}
}
-export default connect(({comments}) => ({comments}))(CommentStream);
+export default connect(({comments, users}) => ({comments, users}))(CommentStream);
diff --git a/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js b/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js
index a4d82fddc..e5670d169 100644
--- a/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js
+++ b/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js
@@ -61,7 +61,7 @@ class ModerationQueue extends React.Component {
// Render the tabbed lists moderation queues
render () {
- const {comments} = this.props;
+ const {comments, users} = this.props;
const {activeTab, singleView, modalOpen} = this.state;
return (
@@ -82,10 +82,11 @@ class ModerationQueue extends React.Component {
commentIds={
comments.get('ids')
.filter(id => !comments.get('byId')
- .get(id)
- .get('status'))
+ .get(id)
+ .get('status'))
}
comments={comments.get('byId')}
+ users={users.get('byId')}
onClickAction={(action, id) => this.onCommentAction(action, id)}
actions={['reject', 'approve']}
loading={comments.loading} />
@@ -104,6 +105,7 @@ class ModerationQueue extends React.Component {
.get('status') === 'rejected')
}
comments={comments.get('byId')}
+ users={users.get('byId')}
onClickAction={(action, id) => this.onCommentAction(action, id)}
actions={['approve']}
loading={comments.loading} />
@@ -117,6 +119,7 @@ class ModerationQueue extends React.Component {
return !data.get('status') && data.get('flagged') === true;
})}
comments={comments.get('byId')}
+ users={users.get('byId')}
onClickAction={(action, id) => this.onCommentAction(action, id)}
actions={['reject', 'approve']}
loading={comments.loading} />
@@ -129,6 +132,6 @@ class ModerationQueue extends React.Component {
}
}
-export default connect(({comments}) => ({comments}))(ModerationQueue);
+export default connect(({comments, users}) => ({comments, users}))(ModerationQueue);
const lang = new I18n(translations);
diff --git a/client/coral-admin/src/helpers/response.js b/client/coral-admin/src/helpers/response.js
deleted file mode 100644
index bccfc5a04..000000000
--- a/client/coral-admin/src/helpers/response.js
+++ /dev/null
@@ -1,30 +0,0 @@
-export const base = '/api/v1';
-
-export const getInit = (method, body) => {
- let init = {
- method,
- headers: new Headers({
- 'Content-Type': 'application/json',
- 'Accept': 'application/json'
- }),
- credentials: 'same-origin'
- };
-
- if (method.toLowerCase() !== 'get') {
- init.body = JSON.stringify(body);
- }
-
- return init;
-};
-
-export const handleResp = res => {
- if (res.status === 401) {
- throw new Error('Not Authorized to make this request');
- } else if (res.status > 399) {
- throw new Error('Error! Status ', res.status);
- } else if (res.status === 204) {
- return res.text();
- } else {
- return res.json();
- }
-};
diff --git a/client/coral-admin/src/reducers/index.js b/client/coral-admin/src/reducers/index.js
index 61029539a..1f1b444fc 100644
--- a/client/coral-admin/src/reducers/index.js
+++ b/client/coral-admin/src/reducers/index.js
@@ -2,6 +2,7 @@ import {combineReducers} from 'redux';
import comments from 'reducers/comments';
import settings from 'reducers/settings';
import community from 'reducers/community';
+import users from 'reducers/users';
import auth from 'reducers/auth';
// Combine all reducers into a main one
@@ -9,6 +10,6 @@ export default combineReducers({
settings,
comments,
community,
- auth
+ auth,
+ users
});
-
diff --git a/client/coral-admin/src/reducers/users.js b/client/coral-admin/src/reducers/users.js
new file mode 100644
index 000000000..872ae904a
--- /dev/null
+++ b/client/coral-admin/src/reducers/users.js
@@ -0,0 +1,20 @@
+import {Map, List, fromJS} from 'immutable';
+
+const initialState = Map({
+ byId: Map(),
+ ids: List()
+});
+
+export default (state = initialState, action) => {
+ switch (action.type) {
+ case 'USERS_MODERATION_QUEUE_FETCH_SUCCESS': return replaceUsers(action, state);
+ default: return state;
+ }
+};
+
+// Replace the comment list with a new one
+const replaceUsers = (action, state) => {
+ const users = fromJS(action.users.reduce((prev, curr) => { prev[curr.id] = curr; return prev; }, {}));
+ return state.set('byId', users)
+ .set('ids', List(users.keys()));
+};
diff --git a/client/coral-admin/src/services/talk-adapter.js b/client/coral-admin/src/services/talk-adapter.js
index 6b872d12d..5502df7ed 100644
--- a/client/coral-admin/src/services/talk-adapter.js
+++ b/client/coral-admin/src/services/talk-adapter.js
@@ -1,4 +1,4 @@
-import {base, handleResp, getInit} from '../../../coral-framework/helpers/response';
+import coralApi from '../../../coral-framework/helpers/response';
/**
* The adapter is a redux middleware that interecepts the actions that need
@@ -15,9 +15,6 @@ export default store => next => action => {
case 'COMMENTS_MODERATION_QUEUE_FETCH':
fetchModerationQueueComments(store);
break;
- // case 'COMMENT_STREAM_FETCH':
- // fetchCommentStream(store);
- // break;
case 'COMMENT_UPDATE':
updateComment(store, action.comment);
break;
@@ -33,24 +30,41 @@ export default store => next => action => {
const fetchModerationQueueComments = store =>
Promise.all([
- fetch(`${base}/queue/comments/pending`, getInit('GET')),
- fetch(`${base}/comments?status=rejected`, getInit('GET')),
- fetch(`${base}/comments?action_type=flag`, getInit('GET'))
+ coralApi('/queue/comments/pending'),
+ coralApi('/comments?status=rejected'),
+ coralApi('/comments?action_type=flag')
])
-.then(res => Promise.all(res.map(handleResp)))
-.then(res => {
- res[2] = res[2].map(comment => { comment.flagged = true; return comment; });
- return res.reduce((prev, curr) => prev.concat(curr), []);
+.then(([pending, rejected, flagged]) => {
+ /* Combine seperate calls into a single object */
+ let all = {};
+ all.comments = pending.comments
+ .concat(rejected.comments)
+ .concat(flagged.comments.map(comment => {
+ comment.flagged = true;
+ return comment;
+ }));
+ all.users = pending.users
+ .concat(rejected.users)
+ .concat(flagged.users);
+ all.actions = pending.actions
+ .concat(rejected.actions)
+ .concat(flagged.actions);
+ return all;
})
-.then(res => store.dispatch({type: 'COMMENTS_MODERATION_QUEUE_FETCH_SUCCESS',
- comments: res}))
-.catch(error => store.dispatch({type: 'COMMENTS_MODERATION_QUEUE_FETCH_FAILED', error}));
+.then(all => {
+ /* Post comments and users to redux store. Actions will be posted when they are needed. */
+ store.dispatch({type: 'USERS_MODERATION_QUEUE_FETCH_SUCCESS',
+ users: all.users});
+ store.dispatch({type: 'COMMENTS_MODERATION_QUEUE_FETCH_SUCCESS',
+ comments: all.comments});
+
+});
+// .catch(error => store.dispatch({type: 'COMMENTS_MODERATION_QUEUE_FETCH_FAILED', error}));
// Update a comment. Now to update a comment we need to send back the whole object
const updateComment = (store, comment) => {
- fetch(`${base}/comments/${comment.get('id')}/status`, getInit('PUT', {status: comment.get('status')}))
- .then(handleResp)
+ coralApi(`/comments/${comment.get('id')}/status`, {method: 'PUT', body: {status: comment.get('status')}})
.then(res => store.dispatch({type: 'COMMENT_UPDATE_SUCCESS', res}))
.catch(error => store.dispatch({type: 'COMMENT_UPDATE_FAILED', error}));
};
@@ -63,8 +77,7 @@ const createComment = (store, name, comment) => {
name: name,
createdAt: Date.now()
};
- return fetch(`${base}/comments`, getInit('POST', body))
- .then(handleResp)
+ return coralApi('/comments', {method: 'POST', body})
.then(res => store.dispatch({type: 'COMMENT_CREATE_SUCCESS', comment: res}))
.catch(error => store.dispatch({type: 'COMMENT_CREATE_FAILED', error}));
};
diff --git a/client/coral-embed-stream/public/samplearticle.html b/client/coral-embed-stream/public/samplearticle.html
index 64c3fd0f8..454cb249c 100644
--- a/client/coral-embed-stream/public/samplearticle.html
+++ b/client/coral-embed-stream/public/samplearticle.html
@@ -7,7 +7,7 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut lobortis sollicitudin eros a ornare. Curabitur dignissim vestibulum massa non rhoncus. Cras laoreet ante vel nunc hendrerit, ac imperdiet neque egestas. Suspendisse aliquet iaculis fermentum. Pellentesque interdum nec elit sed tincidunt. Donec volutpat, tellus posuere laoreet consequat, mi lacus laoreet massa, sed vehicula mauris velit non lectus. Integer non enim nec neque congue faucibus porttitor sit amet dui.
Nunc pharetra orci id diam feugiat, vitae rutrum magna efficitur. Morbi porttitor blandit lorem, et facilisis tellus luctus at. Morbi tincidunt eget nisl id placerat. Nullam consectetur quam vel mauris lacinia, non consectetur est faucibus. Duis cursus auctor nulla nec sagittis. Aenean sem erat, ultrices a hendrerit consectetur, accumsan non lorem. Integer ac neque sed magna sodales vulputate at quis neque. Praesent eget ornare lacus. Donec ultricies, dolor eget commodo faucibus, arcu velit ullamcorper tellus, in cursus tellus elit sed urna. Suspendisse in consequat magna. Duis vel ullamcorper tortor, vel cursus libero. Proin et nisi luctus ligula faucibus luctus. Morbi pulvinar, justo ac feugiat elementum, libero tellus congue justo, pharetra ultrices felis felis id leo. Integer mattis quam tempus libero porta, ac pretium ligula elementum.
-
+
diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js
index dba27cbe8..218081d7f 100644
--- a/client/coral-embed-stream/src/CommentStream.js
+++ b/client/coral-embed-stream/src/CommentStream.js
@@ -77,13 +77,32 @@ class CommentStream extends Component {
componentDidMount () {
// Set up messaging between embedded Iframe an parent component
- const pym = new Pym.Child({polling: 100});
+ this.pym = new Pym.Child({polling: 100});
- if (/https?\:\/\/([^?]+)/.test(pym.parentUrl)) {
- this.props.getStream(pym.parentUrl);
- } else {
- this.props.getStream(window.location);
- }
+ const path = this.pym.parentUrl.split('#')[0];
+
+ this.props.getStream(path || window.location);
+ this.path = path;
+
+ this.pym.sendMessage('childReady');
+
+ this.pym.onMessage('DOMContentLoaded', hash => {
+ // the comment ids can start with numbers, which is invalid for DOM id attributes
+ const commentId = hash.replace('#', 'c_');
+ let count = 0;
+ const interval = setInterval(() => {
+ if (document.getElementById(commentId)) {
+ window.clearInterval(interval);
+ this.pym.scrollParentToChildEl(commentId);
+ }
+
+ if (++count > 100) { // ~10 seconds
+ // give up waiting for the comments to load.
+ // it would be weird for the page to jump after that long.
+ window.clearInterval(interval);
+ }
+ }, 100);
+ });
}
render () {
@@ -92,11 +111,11 @@ class CommentStream extends Component {
const {actions, users, comments} = this.props.items;
const {loggedIn, user, showSignInDialog} = this.props.auth;
const {activeTab} = this.state;
+
return