diff --git a/client/coral-admin/src/containers/ModerationQueue.js b/client/coral-admin/src/containers/ModerationQueue.js
index 9178bda57..cfc48ae6b 100644
--- a/client/coral-admin/src/containers/ModerationQueue.js
+++ b/client/coral-admin/src/containers/ModerationQueue.js
@@ -6,7 +6,7 @@ import {updateStatus} from 'actions/comments';
import styles from './ModerationQueue.css';
import key from 'keymaster';
import I18n from 'coral-framework/i18n/i18n';
-import translations from '../translations';
+import translations from '../translations.json';
/*
* Renders the moderation queue as a tabbed layout with 3 moderation
@@ -91,7 +91,7 @@ class ModerationQueue extends React.Component {
commentIds={
comments
.get('ids')
- .filter(id =>
+ .filter(id =>
comments
.get('byId')
.get(id)
diff --git a/client/coral-admin/src/translations.js b/client/coral-admin/src/translations.js
deleted file mode 100644
index fa655294a..000000000
--- a/client/coral-admin/src/translations.js
+++ /dev/null
@@ -1,55 +0,0 @@
-export default {
- en: {
- 'community': {
- username_and_email: 'Username and Email',
- account_creation_date: 'Account Creation Date',
- newsroom_role: 'Newsroom Role',
- admin: 'Administrator',
- moderator: 'Moderator',
- role: 'Select role...'
- },
- 'modqueue': {
- 'pending': 'pending',
- 'rejected': 'rejected',
- 'flagged': 'flagged',
- 'shortcuts': 'Shortcuts',
- 'close': 'Close',
- 'actions': 'Actions',
- 'navigation': 'Navigation',
- 'approve': 'Approve comment',
- 'reject': 'Reject comment',
- 'nextcomment': 'Go to the next comment',
- 'prevcomment': 'Go to the previous comment',
- 'singleview': 'Toggle single comment edit view',
- 'thismenu': 'Open this menu'
- },
- 'comment': {
- 'flagged': 'flagged',
- 'anon': 'Anonymous'
- },
- 'embedlink': {
- 'copy': 'Copy to Clipboard'
- }
- },
- es: {
- 'community': {
- username_and_email: 'Usuario y E-mail',
- account_creation_date: 'Fecha de creación de la cuenta',
- newsroom_role: 'Rol en la redacción',
- admin: 'Administrador',
- moderator: 'Moderador',
- role: 'Select role...'
- },
- 'modqueue': {
- 'pending': 'pendiente',
- 'rejected': 'rechazado',
- 'flagged': 'marcado',
- 'shortcuts': 'Atajos de teclado',
- 'close': 'Cerrar'
- },
- 'comment': {
- 'flagged': 'marcado',
- 'anon': 'Anónimo'
- }
- }
-};
diff --git a/client/coral-admin/src/translations.json b/client/coral-admin/src/translations.json
new file mode 100644
index 000000000..dd959172b
--- /dev/null
+++ b/client/coral-admin/src/translations.json
@@ -0,0 +1,81 @@
+{
+ "en": {
+ "community": {
+ "username_and_email": "Username and Email",
+ "account_creation_date": "Account Creation Date",
+ "newsroom_role": "Newsroom Role",
+ "admin": "Administrator",
+ "moderator": "Moderator",
+ "role": "Select role..."
+ },
+ "modqueue": {
+ "pending": "pending",
+ "rejected": "rejected",
+ "flagged": "flagged",
+ "shortcuts": "Shortcuts",
+ "close": "Close",
+ "actions": "Actions",
+ "navigation": "Navigation",
+ "approve": "Approve comment",
+ "reject": "Reject comment",
+ "nextcomment": "Go to the next comment",
+ "prevcomment": "Go to the previous comment",
+ "singleview": "Toggle single comment edit view",
+ "thismenu": "Open this menu"
+ },
+ "comment": {
+ "flagged": "flagged",
+ "anon": "Anonymous"
+ },
+ "embedlink": {
+ "copy": "Copy to Clipboard"
+ },
+ "configure": {
+ "enable-pre-moderation": "Enable pre-moderation",
+ "include-comment-stream": "Include Comment Stream Description for Readers.",
+ "include-comment-stream-desc": "Write a message to be added to the top of your comment stream. Pose a topic, include community guidelines, etc.",
+ "include-text": "Include your text here.",
+ "comment-settings": "Comment Settings",
+ "embed-comment-stream": "Embed Comment Stream",
+ "save-changes": "Save Changes",
+ "copy-and-paste": "Copy and paste code below into your CMS to embed your comment box in your articles",
+ "moderate": "Moderate",
+ "configure": "Configure",
+ "community": "Community"
+ }
+ },
+ "es": {
+ "community": {
+ "username_and_email": "Usuario y E-mail",
+ "account_creation_date": "Fecha de creación de la cuenta",
+ "newsroom_role": "Rol en la redacción",
+ "admin": "Administrador",
+ "moderator": "Moderador",
+ "role": "Select role..."
+ },
+ "modqueue": {
+ "pending": "pendiente",
+ "rejected": "rechazado",
+ "flagged": "marcado",
+ "shortcuts": "Atajos de teclado",
+ "close": "Cerrar"
+ },
+ "comment": {
+ "flagged": "marcado",
+ "anon": "Anónimo"
+ },
+ "configure": {
+ "enable-pre-moderation": "Habilitar pre-moderación",
+ "include-comment-stream": "Incluir la Descripción a un Hilo de Comentario para los y las Lectoras.",
+ "include-comment-stream-desc": "Escribir un mensaje que será agregado a la parte de arriba del tu hilo de comentarios. Por ejemplo, un tema, guias de comunidad, etc.",
+ "include-text": "Incluir tu texto aqui.",
+ "comment-settings": "Configuración de Comentarios",
+ "embed-comment-stream": "Colocar Hilo de Comentarios",
+ "save-changes": "Guardar Cambios",
+ "copy-and-paste": "Copiar y pegar el código de más abajo en tu CMS para colocar la caja de comentarios en tus articulos",
+ "moderate": "Moderar",
+ "configure": "Configurar",
+ "community": "Comunidad"
+ }
+ }
+}
diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js
index 9a1910105..ecfc6d7d2 100644
--- a/client/coral-embed-stream/src/CommentStream.js
+++ b/client/coral-embed-stream/src/CommentStream.js
@@ -7,6 +7,7 @@ import {
} from '../../coral-framework';
import {connect} from 'react-redux';
import CommentBox from '../../coral-plugin-commentbox/CommentBox';
+import InfoBox from '../../coral-plugin-infobox/InfoBox';
import Content from '../../coral-plugin-commentcontent/CommentContent';
import PubDate from '../../coral-plugin-pubdate/PubDate';
import Count from '../../coral-plugin-comment-count/CommentCount';
@@ -76,34 +77,25 @@ 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});
+ const path = /https?\:\/\/([^?]+)/.exec(pym.parentUrl)[1];
+ this.props.getStream(path);
}
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
{
rootItem
?
{
- rootItem.comments.map((commentId) => {
+ rootItem.comments && rootItem.comments.map((commentId) => {
const comment = this.props.items.comments[commentId];
return
diff --git a/client/coral-embed-stream/style/default.css b/client/coral-embed-stream/style/default.css
index f68e2a0e3..2f7394d4d 100644
--- a/client/coral-embed-stream/style/default.css
+++ b/client/coral-embed-stream/style/default.css
@@ -49,6 +49,23 @@ hr {
font-weight: bold;
}
+/* Info Box Styles */
+.coral-plugin-infobox-info {
+ position: fixed;
+ top: 0;
+ border: 0;
+ background: rgb(105,105,105);
+ color: white;
+ border-radius: 2px;
+ font-weight: bold;
+ display: block;
+}
+
+.hidden {
+ visibility: hidden;
+ display: none;
+}
+
/* Comment Box Styles */
.coral-plugin-commentbox-container {
display: flex;
diff --git a/client/coral-framework/store/actions/items.js b/client/coral-framework/store/actions/items.js
index 2e7dca70f..2dad64639 100644
--- a/client/coral-framework/store/actions/items.js
+++ b/client/coral-framework/store/actions/items.js
@@ -94,9 +94,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}`, getInit('GET'))
+ return fetch(`/api/v1/stream?asset_url=${encodeURIComponent(assetUrl)}`)
.then(responseHandler)
.then((json) => {
@@ -108,6 +108,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) => {
@@ -125,10 +127,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/client/coral-plugin-infobox/InfoBox.js b/client/coral-plugin-infobox/InfoBox.js
new file mode 100644
index 000000000..db2ea22c4
--- /dev/null
+++ b/client/coral-plugin-infobox/InfoBox.js
@@ -0,0 +1,10 @@
+import React from 'react';
+const packagename = 'coral-plugin-infobox';
+
+const InfoBox = ({enable, content}) =>
+
+ {content}
+
;
+
+export default InfoBox;
diff --git a/client/coral-plugin-infobox/__tests__/infoBox.spec.js b/client/coral-plugin-infobox/__tests__/infoBox.spec.js
new file mode 100644
index 000000000..b8b761489
--- /dev/null
+++ b/client/coral-plugin-infobox/__tests__/infoBox.spec.js
@@ -0,0 +1,26 @@
+import React from 'react';
+import {shallow} from 'enzyme';
+import {expect} from 'chai';
+import InfoBox from '../InfoBox';
+
+describe('InfoBox', () => {
+ let comment;
+ let render;
+ beforeEach(() => {
+ comment = {};
+ const postItem = (item) => {
+ comment.posted = item;
+ return Promise.resolve(4);
+ };
+ render = shallow(
comment.text = e.target.value}
+ item_id={'1'}
+ comments={['1', '2', '3']}/>);
+ });
+
+ it('should render the InfoBox appropriately', () => {
+ expect(render.contains(' {
- 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(decodeURIComponent(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/client/coral-framework/store/itemActions.spec.js b/tests/client/coral-framework/store/itemActions.spec.js
index 4dbba5e82..14da38b41 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;
});
diff --git a/tests/models/setting.js b/tests/models/setting.js
index f50110635..3f4dc27fa 100644
--- a/tests/models/setting.js
+++ b/tests/models/setting.js
@@ -8,7 +8,7 @@ const expect = require('chai').expect;
describe('Setting: model', () => {
beforeEach(() => {
- const defaults = {id: 1, moderation: 'pre'};
+ const defaults = {id: 1};
return Setting.update({id: '1'}, {$setOnInsert: defaults}, {upsert: true});
});
@@ -18,13 +18,21 @@ describe('Setting: model', () => {
expect(settings).to.have.property('moderation').and.to.equal('pre');
});
});
+ it('should have two infoBox fields defined', () => {
+ return Setting.getSettings().then(settings => {
+ expect(settings).to.have.property('infoBoxEnable').and.to.equal(false);
+ expect(settings).to.have.property('infoBoxContent').and.to.equal('');
+ });
+ });
});
describe('#updateSettings()', () => {
it('should update the settings with a passed object', () => {
- const mockSettings = {moderation: 'post'};
+ const mockSettings = {moderation: 'post', infoBoxEnable: true, infoBoxContent: 'yeah'};
return Setting.updateSettings(mockSettings).then(updatedSettings => {
expect(updatedSettings).to.have.property('moderation').and.to.equal('post');
+ expect(updatedSettings).to.have.property('infoBoxEnable', true);
+ expect(updatedSettings).to.have.property('infoBoxContent', 'yeah');
});
});
});
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);
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 @@
-
-
+
+
+
+
+