;
diff --git a/client/coral-plugin-comment-count/CommentCount.js b/client/coral-plugin-comment-count/CommentCount.js
index b0d7312e2..47f00ffb5 100644
--- a/client/coral-plugin-comment-count/CommentCount.js
+++ b/client/coral-plugin-comment-count/CommentCount.js
@@ -1,5 +1,6 @@
import React from 'react';
-
+import {I18n} from '../coral-framework';
+import translations from './translations.json';
const name = 'coral-plugin-comment-count';
const CommentCount = ({items, id}) => {
@@ -15,9 +16,11 @@ const CommentCount = ({items, id}) => {
}
}
- return
- {`${count } ${ count === 1 ? 'Comment' : 'Comments'}`}
+ return
+ {`${count} ${count === 1 ? lang.t('comment') : lang.t('comment-plural')}`}
;
};
export default CommentCount;
+
+const lang = new I18n(translations);
diff --git a/client/coral-plugin-comment-count/translations.json b/client/coral-plugin-comment-count/translations.json
new file mode 100644
index 000000000..f212810e9
--- /dev/null
+++ b/client/coral-plugin-comment-count/translations.json
@@ -0,0 +1,10 @@
+{
+ "en": {
+ "comment": "Comment",
+ "comment-plural": "Comments"
+ },
+ "es": {
+ "comment": "Comentario",
+ "comment-plural": "Comentarios"
+ }
+}
diff --git a/client/coral-plugin-commentbox/CommentBox.js b/client/coral-plugin-commentbox/CommentBox.js
index a4e32d73b..9032ad328 100644
--- a/client/coral-plugin-commentbox/CommentBox.js
+++ b/client/coral-plugin-commentbox/CommentBox.js
@@ -1,5 +1,6 @@
import React, {Component, PropTypes} from 'react';
import {I18n} from '../coral-framework';
+import translations from './translations.json';
const name = 'coral-plugin-commentbox';
@@ -19,7 +20,7 @@ class CommentBox extends Component {
}
postComment = () => {
- const {postItem, updateItem, id, parent_id, addNotification, appendItemArray} = this.props;
+ const {postItem, updateItem, id, parent_id, addNotification, appendItemArray, premod} = this.props;
let comment = {
body: this.state.body,
asset_id: id,
@@ -38,9 +39,14 @@ class CommentBox extends Component {
updateItem(parent_id, 'showReply', false, 'comments');
postItem(comment, 'comments')
.then((comment_id) => {
- appendItemArray(parent_id || id, related, comment_id, !parent_id, parent_type);
- addNotification('success', 'Your comment has been posted.');
- }).catch((err) => console.error(err));
+ if (premod === 'pre') {
+ addNotification('success', lang.t('comment-post-notif-premod'));
+ } else {
+ appendItemArray(parent_id || id, related, comment_id, !parent_id, parent_type);
+ addNotification('success', 'Your comment has been posted.');
+ }
+ })
+ .catch((err) => console.error(err));
this.setState({body: ''});
}
@@ -54,7 +60,7 @@ class CommentBox extends Component {
style={styles && styles.textarea}
value={this.state.username}
id={reply ? 'replyUser' : 'commentUser'}
- placeholder='Name'
+ placeholder={lang.t('name')}
onChange={(e) => this.setState({username: e.target.value})}/>
this.setState({body: e.target.value})}
rows={3}/>
@@ -88,15 +94,4 @@ class CommentBox extends Component {
export default CommentBox;
-const lang = new I18n({
- en: {
- post: 'Post',
- reply: 'Reply',
- comment: 'Comment',
- },
- es: {
- post: 'Publicar',
- reply: 'Respuesta',
- comment: 'Comentario'
- }
-});
+const lang = new I18n(translations);
diff --git a/client/coral-plugin-commentbox/translations.json b/client/coral-plugin-commentbox/translations.json
new file mode 100644
index 000000000..e8eb8ad52
--- /dev/null
+++ b/client/coral-plugin-commentbox/translations.json
@@ -0,0 +1,18 @@
+{
+ "en": {
+ "post": "Post",
+ "reply": "Reply",
+ "comment": "Comment",
+ "name": "Name",
+ "comment-post-notif": "Your comment has been posted.",
+ "comment-post-notif-premod": "Thank you for reporting this comment. Our moderation team has been notified and will review it shortly."
+ },
+ "es": {
+ "post": "Publicar",
+ "reply": "Respuesta",
+ "comment": "Comentario",
+ "name": "Nombre",
+ "comment-post-notif": "¡traduceme!",
+ "comment-post-notif-premod": "¡traduceme!"
+ }
+}
diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js
index eeeb5e3f5..4f90dfb7c 100644
--- a/client/coral-plugin-flags/FlagButton.js
+++ b/client/coral-plugin-flags/FlagButton.js
@@ -1,4 +1,6 @@
import React from 'react';
+import {I18n} from '../coral-framework';
+import translations from './translations.json';
const name = 'coral-plugin-flags';
@@ -10,7 +12,7 @@ const FlagButton = ({flag, id, postAction, addItem, updateItem, addNotification}
addItem({...action, current_user:true}, 'actions');
updateItem(action.item_id, action.action_type, action.id, 'comments');
});
- addNotification('success', 'Thank you for reporting this comment. Our moderation team has been notified and will review it shortly.');
+ addNotification('success', lang.t('flag-notif'));
};
return
@@ -20,8 +22,8 @@ const FlagButton = ({flag, id, postAction, addItem, updateItem, addNotification}
aria-hidden={true}>flag
{
flagged
- ? Flagged
- : Flag
+ ? {lang.t('flag')}
+ : {lang.t('flagged')}
}
;
@@ -37,3 +39,5 @@ const styles = {
color: 'inherit'
}
};
+
+const lang = new I18n(translations);
diff --git a/client/coral-plugin-flags/translations.json b/client/coral-plugin-flags/translations.json
new file mode 100644
index 000000000..28eb9f8cb
--- /dev/null
+++ b/client/coral-plugin-flags/translations.json
@@ -0,0 +1,12 @@
+{
+ "en": {
+ "flag": "Flag",
+ "flagged": "Flagged",
+ "flag-notif": "Thank you for reporting this comment. Our moderation team has been notified and will review it shortly."
+ },
+ "es": {
+ "flag": "Marcar",
+ "flagged": "Marcado",
+ "flag-notif": "Gracias por marcar este comentario. Nuestro equipo de moderación ha sido notificado y muy pronto lo va a revisar."
+ }
+}
diff --git a/client/coral-plugin-replies/ReplyBox.js b/client/coral-plugin-replies/ReplyBox.js
index cd226181b..6614aed72 100644
--- a/client/coral-plugin-replies/ReplyBox.js
+++ b/client/coral-plugin-replies/ReplyBox.js
@@ -4,16 +4,11 @@ import CommentBox from '../coral-plugin-commentbox/CommentBox';
const name = 'coral-plugin-replies';
const ReplyBox = (props) =>
{
props.showReply &&
}
diff --git a/client/coral-plugin-replies/ReplyButton.js b/client/coral-plugin-replies/ReplyButton.js
index 82c379e86..44213c2f7 100644
--- a/client/coral-plugin-replies/ReplyButton.js
+++ b/client/coral-plugin-replies/ReplyButton.js
@@ -1,5 +1,6 @@
import React from 'react';
import {I18n} from '../coral-framework';
+import translations from './translations.json';
const name = 'coral-plugin-replies';
@@ -13,11 +14,4 @@ const ReplyButton = (props) => {
- return Comment.find({'id': {'$in': actions.map(function(a){return a.item_id;})}});
- });
+ return Action
+ .findCommentsIdByActionType(action_type, 'comment')
+ .then((actions) => {
+ return Comment.find({'id': {'$in': actions.map(function(a){
+ return a.item_id;})}
+ });
+ });
};
/**
@@ -97,9 +101,20 @@ CommentSchema.statics.findByActionType = function(action_type) {
* @param {String} status the status of the comment to search for
*/
CommentSchema.statics.findByStatusByActionType = function(status, action_type) {
- return Action.findCommentsIdByActionType(action_type, 'comment').then((actions) => {
- return Comment.find({'status': status, 'id': {'$in': actions.map(function(a){return a.item_id;})}});
- });
+ return Action
+ .findCommentsIdByActionType(action_type, 'comment')
+ .then((actions) => {
+
+ return Comment.find({
+ 'status': status,
+ 'id': {
+ '$in': actions.map(a => {
+ return a.item_id;
+ })
+ }
+ });
+
+ });
};
/**
diff --git a/models/setting.js b/models/setting.js
index a9b60abb8..09b13e099 100644
--- a/models/setting.js
+++ b/models/setting.js
@@ -20,7 +20,7 @@ SettingSchema.statics.init = function (defaults) {
};
/**
- * gets the entire settings record and sends it back
+ * Gets the entire settings record and sends it back
* @return {Promise} settings the whole settings record
*/
SettingSchema.statics.getSettings = function () {
@@ -28,7 +28,7 @@ SettingSchema.statics.getSettings = function () {
};
/**
- * gets the moderation settings and sends it back
+ * Gets the moderation settings and sends it back
* @return {Promise} moderation the settings for how to moderate comments
*/
SettingSchema.statics.getModerationSetting = function () {
@@ -36,12 +36,13 @@ SettingSchema.statics.getModerationSetting = function () {
};
/**
- * this will update the settings object with whatever you pass in
+ * This will update the settings object with whatever you pass in
* @param {object} setting a hash of whatever settings you want to update
* @return {Promise} settings Promise that resolves to the entire (updated) settings object.
*/
SettingSchema.statics.updateSettings = function (setting) {
- // there should only ever be one record unless something has gone wrong.
+ // There should only ever be one record unless something has gone wrong.
+ // In the future we may have multiple records for custom settings for objects/users.
return this.findOneAndUpdate({id: '1'}, {$set: setting}, {new: true});
};
diff --git a/models/user.js b/models/user.js
index 6800b59ef..c0a846f1a 100644
--- a/models/user.js
+++ b/models/user.js
@@ -25,6 +25,11 @@ const UserSchema = new mongoose.Schema({
}
}],
roles: [String]
+}, {
+ timestamps: {
+ createdAt: 'created_at',
+ updatedAt: 'updated_at'
+ }
});
// Add the indixies on the user profile data.
@@ -52,6 +57,22 @@ UserSchema.options.toJSON.transform = (doc, ret, options) => {
return ret;
};
+/**
+ * toObject overrides to remove the password field from the toObject
+ * output.
+ */
+UserSchema.options.toObject = {};
+UserSchema.options.toObject.hide = 'password';
+UserSchema.options.toObject.transform = (doc, ret, options) => {
+ if (options.hide) {
+ options.hide.split(' ').forEach((prop) => {
+ delete ret[prop];
+ });
+ }
+
+ return ret;
+};
+
/**
* Finds a user given their email address that we have for them in the system
* and ensures that the retuned user matches the password passed in as well.
@@ -100,19 +121,22 @@ UserSchema.statics.findLocalUser = function(email, password) {
UserSchema.statics.mergeUsers = function(dstUserID, srcUserID) {
let srcUser, dstUser;
- return Promise.all([
- User.findOne({id: dstUserID}).exec(),
- User.findOne({id: srcUserID}).exec()
- ]).then((users) => {
- dstUser = users[0];
- srcUser = users[1];
+ return Promise
+ .all([
+ User.findOne({id: dstUserID}).exec(),
+ User.findOne({id: srcUserID}).exec()
+ ])
+ .then((users) => {
+ dstUser = users[0];
+ srcUser = users[1];
- srcUser.profiles.forEach((profile) => {
- dstUser.profiles.push(profile);
- });
+ srcUser.profiles.forEach((profile) => {
+ dstUser.profiles.push(profile);
+ });
- return srcUser.remove();
- }).then(() => dstUser.save());
+ return srcUser.remove();
+ })
+ .then(() => dstUser.save());
};
/**
@@ -122,33 +146,34 @@ UserSchema.statics.mergeUsers = function(dstUserID, srcUserID) {
* @param {Function} done [description]
*/
UserSchema.statics.findOrCreateExternalUser = function(profile) {
- return User.findOne({
- profiles: {
- $elemMatch: {
- id: profile.id,
- provider: profile.provider
- }
- }
- })
- .then((user) => {
- if (user) {
- return user;
- }
-
- // The user was not found, lets create them!
- user = new User({
- displayName: profile.displayName,
- roles: [],
- profiles: [
- {
+ return User
+ .findOne({
+ profiles: {
+ $elemMatch: {
id: profile.id,
provider: profile.provider
}
- ]
- });
+ }
+ })
+ .then((user) => {
+ if (user) {
+ return user;
+ }
- return user.save();
- });
+ // The user was not found, lets create them!
+ user = new User({
+ displayName: profile.displayName,
+ roles: [],
+ profiles: [
+ {
+ id: profile.id,
+ provider: profile.provider
+ }
+ ]
+ });
+
+ return user.save();
+ });
};
UserSchema.statics.changePassword = function(id, password) {
diff --git a/routes/api/comments/index.js b/routes/api/comments/index.js
index a2e77b417..5126bf93c 100644
--- a/routes/api/comments/index.js
+++ b/routes/api/comments/index.js
@@ -12,17 +12,17 @@ const router = express.Router();
router.get('/', (req, res, next) => {
Comment.find({}).then((comments) => {
res.status(200).json(comments);
- }).catch(error => {
- next(error);
- });
+ })
+ .catch(next);
});
router.get('/:comment_id', (req, res, next) => {
- Comment.findById(req.params.comment_id).then((comment) => {
- res.status(200).json(comment);
- }).catch(error => {
- next(error);
- });
+ Comment
+ .findById(req.params.comment_id)
+ .then(comment => {
+ res.status(200).json(comment);
+ })
+ .catch(next);
});
//==============================================================================
@@ -31,20 +31,22 @@ router.get('/:comment_id', (req, res, next) => {
// Get all the comments that have that action_type over them.
router.get('/action/:action_type', (req, res, next) => {
- Comment.findByActionType(req.params.action_type).then((comments) => {
- res.status(200).json(comments);
- }).catch(error => {
- next(error);
- });
+ Comment
+ .findByActionType(req.params.action_type)
+ .then((comments) => {
+ res.status(200).json(comments);
+ })
+ .catch(next);
});
// Get all the comments that were rejected.
router.get('/status/rejected', (req, res, next) => {
- Comment.findByStatus('rejected').then((comments) => {
- res.status(200).json(comments);
- }).catch(error => {
- next(error);
- });
+ Comment
+ .findByStatus('rejected')
+ .then(comments => {
+ res.status(200).json(comments);
+ })
+ .catch(next);
});
// Returns back all the comments that are in the moderation queue. The moderation queue is pre or post moderated,
@@ -52,17 +54,21 @@ router.get('/status/rejected', (req, res, next) => {
// Pre-moderation: New comments are shown in the moderator queues immediately.
// Post-moderation: New comments do not appear in moderation queues unless they are flagged by other users.
router.get('/status/pending', (req, res, next) => {
- Setting.getModerationSetting().then(function({moderation}){
- let moderationValue = req.query.moderation;
- if (typeof moderationValue === 'undefined' || moderationValue === undefined) {
- moderationValue = moderation;
- }
- Comment.moderationQueue(moderationValue).then((comments) => {
- res.status(200).json(comments);
- });
- }).catch(error => {
- next(error);
- });
+
+ Setting
+ .getModerationSetting()
+ .then(({moderation}) => {
+ let moderationValue = req.query.moderation;
+ if (typeof moderationValue === 'undefined' || moderationValue === undefined) {
+ moderationValue = moderation;
+ }
+ Comment
+ .moderationQueue(moderationValue)
+ .then((comments) => {
+ res.status(200).json(comments);
+ });
+ })
+ .catch(next);
});
//==============================================================================
@@ -70,27 +76,36 @@ router.get('/status/pending', (req, res, next) => {
//==============================================================================
router.post('/', (req, res, next) => {
+
const {body, author_id, asset_id, parent_id, status, username} = req.body;
- Comment.new(body, author_id, asset_id, parent_id, status, username).then((comment) => {
- res.status(200).send({'id': comment.id});
- }).catch(error => {
- next(error);
- });
+
+ Comment
+ .new(body, author_id, asset_id, parent_id, status, username)
+ .then((comment) => {
+ res.status(200).send({'id': comment.id});
+ })
+ .catch(error => {
+ next(error);
+ });
});
router.post('/:comment_id', (req, res, next) => {
- Comment.findById(req.params.comment_id).then((comment) => {
- comment.body = req.body.body;
- comment.author_id = req.body.author_id;
- comment.asset_id = req.body.asset_id;
- comment.parent_id = req.body.parent_id;
- comment.status = req.body.status;
- return comment.save();
- }).then((comment) => {
- res.status(200).send(comment);
- }).catch(error => {
- next(error);
- });
+ Comment
+ .findById(req.params.comment_id)
+ .then((comment) => {
+ comment.body = req.body.body;
+ comment.author_id = req.body.author_id;
+ comment.asset_id = req.body.asset_id;
+ comment.parent_id = req.body.parent_id;
+ comment.status = req.body.status;
+ return comment.save();
+ })
+ .then((comment) => {
+ res.status(200).send(comment);
+ })
+ .catch(error => {
+ next(error);
+ });
});
router.post('/:comment_id/status', (req, res, next) => {
@@ -103,11 +118,14 @@ router.post('/:comment_id/status', (req, res, next) => {
});
router.post('/:comment_id/actions', (req, res, next) => {
- Comment.addAction(req.params.comment_id, req.body.user_id, req.body.action_type).then((action) => {
- res.status(200).send(action);
- }).catch(error => {
- next(error);
- });
+ Comment
+ .addAction(req.params.comment_id, req.body.user_id, req.body.action_type)
+ .then((action) => {
+ res.status(200).send(action);
+ })
+ .catch(error => {
+ next(error);
+ });
});
//==============================================================================
@@ -115,11 +133,14 @@ router.post('/:comment_id/actions', (req, res, next) => {
//==============================================================================
router.delete('/:comment_id', (req, res, next) => {
- Comment.removeById(req.params.comment_id).then(() => {
- res.status(201).send('OK. Removed');
- }).catch(error => {
- next(error);
- });
+ Comment
+ .removeById(req.params.comment_id)
+ .then(() => {
+ res.status(201).send('OK. Removed');
+ })
+ .catch(error => {
+ next(error);
+ });
});
module.exports = router;
diff --git a/routes/api/index.js b/routes/api/index.js
index 46570f588..3e149f9e8 100644
--- a/routes/api/index.js
+++ b/routes/api/index.js
@@ -7,5 +7,6 @@ router.use('/auth', require('./auth'));
router.use('/comments', require('./comments'));
router.use('/settings', require('./settings'));
router.use('/stream', require('./stream'));
+router.use('/user', require('./user'));
module.exports = router;
diff --git a/routes/api/settings/index.js b/routes/api/settings/index.js
index 53bf53f3c..585bf083a 100644
--- a/routes/api/settings/index.js
+++ b/routes/api/settings/index.js
@@ -3,11 +3,17 @@ const router = express.Router();
const Setting = require('../../../models/setting');
router.get('/', (req, res, next) => {
- Setting.getSettings().then(settings => res.json(settings)).catch(next);
+ Setting
+ .getSettings()
+ .then(settings => res.json(settings))
+ .catch(next);
});
router.put('/', (req, res, next) => {
- Setting.updateSettings(req.body).then(() => res.status(204).end()).catch(next);
+ Setting
+ .updateSettings(req.body)
+ .then(() => res.status(204).end())
+ .catch(next);
});
module.exports = router;
diff --git a/routes/api/stream/index.js b/routes/api/stream/index.js
index 1e3e39d81..3f49d48fc 100644
--- a/routes/api/stream/index.js
+++ b/routes/api/stream/index.js
@@ -36,7 +36,8 @@ router.get('/', (req, res, next) => {
users,
actions
});
- }).catch(error => {
+ })
+ .catch(error => {
next(error);
});
});
diff --git a/routes/api/user/index.js b/routes/api/user/index.js
new file mode 100644
index 000000000..18872eab7
--- /dev/null
+++ b/routes/api/user/index.js
@@ -0,0 +1,63 @@
+const express = require('express');
+const router = express.Router();
+const User = require('../../../models/user');
+
+router.get('/', (req, res, next) => {
+ const {
+ value = '',
+ field = 'created_at',
+ page = 1,
+ asc = 'false',
+ limit = 50 // Total Per Page
+ } = req.query;
+
+ let q = {
+ $or: [
+ {
+ 'displayName': {
+ $regex: new RegExp(`^${value}`),
+ $options: 'i'
+ },
+ 'profiles': {
+ $elemMatch: {
+ id: {
+ $regex: new RegExp(`^${value}`),
+ $options: 'i'
+ },
+ provider: 'local'
+ }
+ }
+ }
+ ]
+ };
+
+ Promise.all([
+ User.find(q)
+ .sort({[field]: (asc === 'true') ? 1 : -1})
+ .skip((page - 1) * limit)
+ .limit(limit),
+ User.count()
+ ])
+ .then(([data, count]) => {
+ const users = data.map((user) => {
+ const {displayName, created_at} = user;
+ return {
+ displayName,
+ created_at,
+ profiles: user.toObject().profiles
+ };
+ });
+
+ res.json({
+ result: users,
+ limit: Number(limit),
+ count,
+ page: Number(page),
+ totalPages: Math.ceil(count / limit)
+ });
+
+ })
+ .catch(next);
+});
+
+module.exports = router;
diff --git a/tests/routes/api/settings/index.js b/tests/routes/api/settings/index.js
index 5bcf9de28..41c37828e 100644
--- a/tests/routes/api/settings/index.js
+++ b/tests/routes/api/settings/index.js
@@ -43,11 +43,13 @@ describe('update settings', () => {
return Setting.getSettings();
- }).then(settings => {
+ })
+ .then(settings => {
// confirm updated settings in db
expect(settings).to.have.property('moderation');
expect(settings.moderation).to.equal('post');
- }).catch(err => {
+ })
+ .catch(err => {
throw err;
});
});
diff --git a/webpack.config.dev.js b/webpack.config.dev.js
index e2c92b396..8e2f253e5 100644
--- a/webpack.config.dev.js
+++ b/webpack.config.dev.js
@@ -82,6 +82,12 @@ module.exports = {
precss,
new webpack.ProvidePlugin({
'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
+ }),
+ new webpack.DefinePlugin({
+ 'process.env': {
+ 'NODE_ENV': `"${'development'}"`,
+ 'VERSION': `"${require('./package.json').version}"`
+ }
})
],
resolve: {
diff --git a/webpack.config.js b/webpack.config.js
index 434da160d..bf602733f 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -8,7 +8,7 @@ devConfig.plugins = devConfig.plugins.concat([
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': `"${'production'}"`,
- 'VERSION': `"${require('./package.json')}"`
+ 'VERSION': `"${require('./package.json').version}"`
}
}),
new webpack.optimize.UglifyJsPlugin({