From d9dc198d463a5bb97558e44b5ce6312769a853b8 Mon Sep 17 00:00:00 2001 From: David Erwin Date: Thu, 10 Nov 2016 14:52:05 -0500 Subject: [PATCH 01/13] Moved chained funcitons to multiple lines --- .eslintrc.json | 3 +- bin/cli-settings | 6 +- bin/cli-users | 9 +- .../src/containers/ModerationQueue.js | 17 ++- client/coral-framework/store/actions/items.js | 3 +- client/coral-plugin-commentbox/CommentBox.js | 3 +- models/user.js | 3 +- routes/api/comments/index.js | 137 +++++++++++------- routes/api/settings/index.js | 10 +- routes/api/stream/index.js | 3 +- tests/routes/api/settings/index.js | 6 +- 11 files changed, 131 insertions(+), 69 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 23bdea410..6ac5a08e6 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -59,6 +59,7 @@ "no-multiple-empty-lines": [ "error", {"max": 1} - ] + ], + "newline-per-chained-call": ["error", { "ignoreChainWithDepth": 2 }] } } diff --git a/bin/cli-settings b/bin/cli-settings index 0920473da..cff6c04ed 100755 --- a/bin/cli-settings +++ b/bin/cli-settings @@ -24,11 +24,13 @@ program const Setting = require('../models/setting'); const defaults = {id: '1', moderation: 'pre'}; - Setting.update({id: '1'}, {$setOnInsert: defaults}, {upsert: true}) + Setting + .update({id: '1'}, {$setOnInsert: defaults}, {upsert: true}) .then(() => { console.log('Created settings object.'); mongoose.disconnect(); - }).catch((err) => { + }) + .catch((err) => { console.error(`failed to create the settings object ${JSON.stringify(err)}`); throw new Error(err); // just to be safe }); diff --git a/bin/cli-users b/bin/cli-users index 74aa902eb..b27c41e14 100755 --- a/bin/cli-users +++ b/bin/cli-users @@ -71,10 +71,12 @@ function createUser(options) { }) .then((result) => { return User.createLocalUser(result.email.trim(), result.password.trim(), result.displayName.trim()); - }).then((user) => { + }) + .then((user) => { console.log(`Created user ${user.id}.`); mongoose.disconnect(); - }).catch((err) => { + }) + .catch((err) => { console.error(err); mongoose.disconnect(); }); @@ -249,7 +251,8 @@ function mergeUsers(dstUserID, srcUserID) { .then(() => { console.log(`User ${srcUserID} was merged into user ${dstUserID}.`); mongoose.disconnect(); - }).catch((err) => { + }) + .catch((err) => { console.error(err); mongoose.disconnect(); }); diff --git a/client/coral-admin/src/containers/ModerationQueue.js b/client/coral-admin/src/containers/ModerationQueue.js index 6cd9f46fc..9178bda57 100644 --- a/client/coral-admin/src/containers/ModerationQueue.js +++ b/client/coral-admin/src/containers/ModerationQueue.js @@ -73,7 +73,12 @@ class ModerationQueue extends React.Component { !comments.get('byId').get(id).get('status'))} + commentIds={ + comments.get('ids') + .filter(id => !comments.get('byId') + .get(id) + .get('status')) + } comments={comments.get('byId')} onClickAction={(action, id) => this.onCommentAction(action, id)} actions={['reject', 'approve']} @@ -83,7 +88,15 @@ class ModerationQueue extends React.Component { comments.get('byId').get(id).get('status') === 'rejected')} + commentIds={ + comments + .get('ids') + .filter(id => + comments + .get('byId') + .get(id) + .get('status') === 'rejected') + } comments={comments.get('byId')} onClickAction={(action, id) => this.onCommentAction(action, id)} actions={['approve']} diff --git a/client/coral-framework/store/actions/items.js b/client/coral-framework/store/actions/items.js index b690c6f0a..173413d66 100644 --- a/client/coral-framework/store/actions/items.js +++ b/client/coral-framework/store/actions/items.js @@ -241,7 +241,8 @@ export function postAction (item_id, action_type, user_id, item_type) { return response.ok ? response.json() : Promise.reject(`${response.status} ${response.statusText}`); } - ).then((json)=>{ + ) + .then((json)=>{ return json; }); }; diff --git a/client/coral-plugin-commentbox/CommentBox.js b/client/coral-plugin-commentbox/CommentBox.js index a4e32d73b..dbcd9dd97 100644 --- a/client/coral-plugin-commentbox/CommentBox.js +++ b/client/coral-plugin-commentbox/CommentBox.js @@ -40,7 +40,8 @@ class CommentBox extends Component { .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)); + }) + .catch((err) => console.error(err)); this.setState({body: ''}); } diff --git a/models/user.js b/models/user.js index 6800b59ef..0370a7e33 100644 --- a/models/user.js +++ b/models/user.js @@ -112,7 +112,8 @@ UserSchema.statics.mergeUsers = function(dstUserID, srcUserID) { }); return srcUser.remove(); - }).then(() => dstUser.save()); + }) + .then(() => dstUser.save()); }; /** diff --git a/routes/api/comments/index.js b/routes/api/comments/index.js index a2e77b417..3a0129ff4 100644 --- a/routes/api/comments/index.js +++ b/routes/api/comments/index.js @@ -12,17 +12,21 @@ const router = express.Router(); router.get('/', (req, res, next) => { Comment.find({}).then((comments) => { res.status(200).json(comments); - }).catch(error => { + }) + .catch(error => { next(error); }); }); 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(error => { + next(error); + }); }); //============================================================================== @@ -31,20 +35,26 @@ 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(error => { + next(error); + }); }); // 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(error => { + next(error); + }); }); // Returns back all the comments that are in the moderation queue. The moderation queue is pre or post moderated, @@ -52,17 +62,23 @@ 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); + + 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); }); - }).catch(error => { - next(error); - }); }); //============================================================================== @@ -70,27 +86,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 +128,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 +143,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/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/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; }); }); From 89398120d5ca770d08654d90346a6d31f1da3314 Mon Sep 17 00:00:00 2001 From: David Erwin Date: Thu, 10 Nov 2016 14:57:57 -0500 Subject: [PATCH 02/13] Remove function keyword --- routes/api/comments/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/api/comments/index.js b/routes/api/comments/index.js index 3a0129ff4..e8a995089 100644 --- a/routes/api/comments/index.js +++ b/routes/api/comments/index.js @@ -65,7 +65,7 @@ router.get('/status/pending', (req, res, next) => { Setting .getModerationSetting() - .then(function({moderation}){ + .then(({moderation}) => { let moderationValue = req.query.moderation; if (typeof moderationValue === 'undefined' || moderationValue === undefined) { moderationValue = moderation; From f7249c4016e7b5c802771ffbabde7f98aebd0558 Mon Sep 17 00:00:00 2001 From: David Erwin Date: Thu, 10 Nov 2016 15:12:56 -0500 Subject: [PATCH 03/13] More linting and commenting --- models/comment.js | 25 +++++++++--- models/setting.js | 9 +++-- models/user.js | 73 +++++++++++++++++++----------------- routes/api/comments/index.js | 20 +++------- 4 files changed, 67 insertions(+), 60 deletions(-) diff --git a/models/comment.js b/models/comment.js index 3f99bcb6a..a80e353f0 100644 --- a/models/comment.js +++ b/models/comment.js @@ -86,9 +86,13 @@ CommentSchema.statics.findAcceptedAndNewByAssetId = function(asset_id) { * @param {String} action_type the type of action that was performed on the comment */ CommentSchema.statics.findByActionType = function(action_type) { - return Action.findCommentsIdByActionType(action_type, 'comment').then((actions) => { - 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,18 @@ 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 15c457307..7d1f4b367 100644 --- a/models/setting.js +++ b/models/setting.js @@ -12,7 +12,7 @@ const SettingSchema = new Schema({ }); /** - * 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 () { @@ -20,7 +20,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 () { @@ -28,12 +28,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 0370a7e33..ac642c910 100644 --- a/models/user.js +++ b/models/user.js @@ -100,20 +100,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()); }; /** @@ -123,33 +125,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 e8a995089..5126bf93c 100644 --- a/routes/api/comments/index.js +++ b/routes/api/comments/index.js @@ -13,9 +13,7 @@ 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) => { @@ -24,9 +22,7 @@ router.get('/:comment_id', (req, res, next) => { .then(comment => { res.status(200).json(comment); }) - .catch(error => { - next(error); - }); + .catch(next); }); //============================================================================== @@ -40,9 +36,7 @@ router.get('/action/:action_type', (req, res, next) => { .then((comments) => { res.status(200).json(comments); }) - .catch(error => { - next(error); - }); + .catch(next); }); // Get all the comments that were rejected. @@ -52,9 +46,7 @@ router.get('/status/rejected', (req, res, next) => { .then(comments => { res.status(200).json(comments); }) - .catch(error => { - next(error); - }); + .catch(next); }); // Returns back all the comments that are in the moderation queue. The moderation queue is pre or post moderated, @@ -76,9 +68,7 @@ router.get('/status/pending', (req, res, next) => { res.status(200).json(comments); }); }) - .catch(error => { - next(error); - }); + .catch(next); }); //============================================================================== From 95f3b86f3b02fdcfad56f0aa66fbba9f6ae8a90f Mon Sep 17 00:00:00 2001 From: David Erwin Date: Thu, 10 Nov 2016 15:24:34 -0500 Subject: [PATCH 04/13] cleaning up nested objects --- models/comment.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/models/comment.js b/models/comment.js index a80e353f0..8eab6aff4 100644 --- a/models/comment.js +++ b/models/comment.js @@ -107,9 +107,11 @@ CommentSchema.statics.findByStatusByActionType = function(status, action_type) { return Comment.find({ 'status': status, - 'id': {'$in': actions.map(a => { - return a.item_id;} - )} + 'id': { + '$in': actions.map(a => { + return a.item_id; + }) + } }); }); From 0ce892fe7a2c47f4b47203d0678bcdf4b0659d50 Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 10 Nov 2016 17:04:04 -0500 Subject: [PATCH 05/13] Loading settings and modifying commentbox to reflect pre and post-mod behavior. --- .../coral-embed-stream/src/CommentStream.js | 4 ++- .../coral-framework/store/actions/config.js | 34 +++++++++++-------- client/coral-framework/store/actions/items.js | 2 +- client/coral-plugin-author-name/AuthorName.js | 2 +- client/coral-plugin-commentbox/CommentBox.js | 10 ++++-- client/coral-plugin-replies/ReplyBox.js | 7 +--- 6 files changed, 33 insertions(+), 26 deletions(-) diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index 28b70841f..d6edfddda 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -108,6 +108,7 @@ class CommentStream extends Component { appendItemArray={this.props.appendItemArray} updateItem={this.props.updateItem} id={rootItemId} + premod={this.props.config.moderation} reply={false}/> { @@ -138,6 +139,7 @@ class CommentStream extends Component { updateItem={this.props.updateItem} id={rootItemId} parent_id={commentId} + premod={this.props.config.moderation} showReply={comment.showReply}/> { comment.children && @@ -168,7 +170,7 @@ class CommentStream extends Component { }) } diff --git a/client/coral-framework/store/actions/config.js b/client/coral-framework/store/actions/config.js index 7eb82d428..800017102 100644 --- a/client/coral-framework/store/actions/config.js +++ b/client/coral-framework/store/actions/config.js @@ -14,17 +14,23 @@ export const FETCH_CONFIG_SUCCESS = 'FETCH_CONFIG_SUCCESS'; * Action creators */ -export const fetchConfig = () => async (dispatch) => { - dispatch({type: FETCH_CONFIG_REQUEST}); - - try { - //TODO: Replace with fetching config from backend - // const response = await fetch(`./talk.config.json`) - // const json = await response.json() - dispatch({type: FETCH_CONFIG_SUCCESS, config: fromJS({ - notifLength: 4500 - })}); - } catch (error) { - dispatch({type: FETCH_CONFIG_FAILED}); - } -}; +export function fetchConfig () { + return (dispatch) => { + dispatch({type: FETCH_CONFIG_REQUEST}); + console.log('Fetching settings'); + return fetch('/api/v1/settings') + .then( + response => { + return response.ok ? response.json() + : Promise.reject(`${response.status} ${response.statusText}`); + } + ) + .then((json) => { + console.log(json); + return dispatch({type: FETCH_CONFIG_SUCCESS, config: fromJS(json)}); + }).catch((error) => { + console.log(error); + dispatch({type: FETCH_CONFIG_FAILED, error}); + }); + }; +} diff --git a/client/coral-framework/store/actions/items.js b/client/coral-framework/store/actions/items.js index b690c6f0a..5b44de359 100644 --- a/client/coral-framework/store/actions/items.js +++ b/client/coral-framework/store/actions/items.js @@ -148,7 +148,7 @@ export function getStream (assetId) { export function getItemsArray (ids) { return (dispatch) => { - return fetch(`/v1/item/${ ids}`) + return fetch(`/v1/item/${ids}`) .then( response => { return response.ok ? response.json() diff --git a/client/coral-plugin-author-name/AuthorName.js b/client/coral-plugin-author-name/AuthorName.js index ddfd40ccf..585c1c07d 100644 --- a/client/coral-plugin-author-name/AuthorName.js +++ b/client/coral-plugin-author-name/AuthorName.js @@ -2,7 +2,7 @@ import React from 'react'; const packagename = 'coral-plugin-author-name'; const AuthorName = ({name}) => -
+
{name}
; diff --git a/client/coral-plugin-commentbox/CommentBox.js b/client/coral-plugin-commentbox/CommentBox.js index a4e32d73b..3811e0cd9 100644 --- a/client/coral-plugin-commentbox/CommentBox.js +++ b/client/coral-plugin-commentbox/CommentBox.js @@ -19,7 +19,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,8 +38,12 @@ 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.'); + if (premod === 'pre') { + addNotification('success', 'Your comment has been posted and is being reviewed by our moderation team.'); + } 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: ''}); } diff --git a/client/coral-plugin-replies/ReplyBox.js b/client/coral-plugin-replies/ReplyBox.js index cd226181b..d9fddf1ad 100644 --- a/client/coral-plugin-replies/ReplyBox.js +++ b/client/coral-plugin-replies/ReplyBox.js @@ -8,12 +8,7 @@ const ReplyBox = (props) =>
{ props.showReply && } From ff4e778dde8501dec407a2d2666976df634f69f7 Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 10 Nov 2016 17:34:26 -0500 Subject: [PATCH 06/13] Adding seperate translation files for packages. --- .../coral-admin/public/translations/en.json | 24 ------------------- .../coral-admin/public/translations/es.json | 13 ---------- .../CommentCount.js | 9 ++++--- .../translations.json | 10 ++++++++ client/coral-plugin-commentbox/CommentBox.js | 14 ++--------- .../coral-plugin-commentbox/translations.json | 12 ++++++++++ client/coral-plugin-flags/FlagButton.js | 8 +++++-- client/coral-plugin-flags/translations.json | 10 ++++++++ client/coral-plugin-replies/ReplyBox.js | 2 +- client/coral-plugin-replies/ReplyButton.js | 10 ++------ client/coral-plugin-replies/translations.json | 8 +++++++ 11 files changed, 57 insertions(+), 63 deletions(-) delete mode 100644 client/coral-admin/public/translations/en.json delete mode 100644 client/coral-admin/public/translations/es.json create mode 100644 client/coral-plugin-comment-count/translations.json create mode 100644 client/coral-plugin-commentbox/translations.json create mode 100644 client/coral-plugin-flags/translations.json create mode 100644 client/coral-plugin-replies/translations.json diff --git a/client/coral-admin/public/translations/en.json b/client/coral-admin/public/translations/en.json deleted file mode 100644 index 591de1754..000000000 --- a/client/coral-admin/public/translations/en.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "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" - } -} diff --git a/client/coral-admin/public/translations/es.json b/client/coral-admin/public/translations/es.json deleted file mode 100644 index d151cf13c..000000000 --- a/client/coral-admin/public/translations/es.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "modqueue": { - "pending": "pendiente", - "rejected": "rechazado", - "flagged": "marcado", - "shortcuts": "Atajos de teclado", - "close": "Cerrar" - }, - "comment": { - "flagged": "marcado", - "anon": "Anónimo" - } -} 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..bf2522a47 --- /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..349a589a6 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'; @@ -88,15 +89,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..86e9ade54 --- /dev/null +++ b/client/coral-plugin-commentbox/translations.json @@ -0,0 +1,12 @@ +{ + "en": { + "post": "Post", + "reply": "Reply", + "comment": "Comment", + }, + "es": { + "post": "Publicar", + "reply": "Respuesta", + "comment": "Comentario" + } +} diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index eeeb5e3f5..a920edc33 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'; @@ -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..f5fb9ba9a --- /dev/null +++ b/client/coral-plugin-flags/translations.json @@ -0,0 +1,10 @@ +{ + "en": { + "flag": "Flag", + "flagged": "Flagged" + }, + "es": { + "flag": "¡traduceme!", + "flagged": "¡traduceme!" + } +} diff --git a/client/coral-plugin-replies/ReplyBox.js b/client/coral-plugin-replies/ReplyBox.js index cd226181b..6d7c1fb34 100644 --- a/client/coral-plugin-replies/ReplyBox.js +++ b/client/coral-plugin-replies/ReplyBox.js @@ -4,7 +4,7 @@ import CommentBox from '../coral-plugin-commentbox/CommentBox'; const name = 'coral-plugin-replies'; const ReplyBox = (props) =>
{ props.showReply &&
; From 5b74beabd6955d562a840538ab603acc595e4ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Curcio?= Date: Fri, 11 Nov 2016 13:14:26 -0300 Subject: [PATCH 08/13] Community Section - Search Commenters (#60) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Table * úsers api * Ádding envs and version * Community Table Added * Ádding redux * Adding loading data state * Community Actions * Adding Inmutable * Fetching commenters * Search commenters * Linting and translations * Ádding Sort * sortBuilder * pagr * request per page, pager and mor * package.json * new Page actiokn * éslint * Changes and cleaner comps * removed console.log --- .eslintignore | 2 +- client/coral-admin/src/AppRouter.js | 2 +- client/coral-admin/src/actions/community.js | 42 ++++++++++ client/coral-admin/src/components/Page.js | 12 --- .../coral-admin/src/components/ui/Header.js | 3 + .../coral-admin/src/components/ui/Layout.css | 4 + .../coral-admin/src/components/ui/Layout.js | 5 +- client/coral-admin/src/constants/community.js | 5 ++ .../src/containers/Community/Community.css | 22 +++++ .../src/containers/Community/Community.js | 68 ++++++++++++++++ .../Community/CommunityContainer.js | 80 +++++++++++++++++++ .../src/containers/Community/Loading.js | 7 ++ .../src/containers/Community/NoResults.js | 9 +++ .../src/containers/Community/Pager.css | 10 +++ .../src/containers/Community/Pager.js | 45 +++++++++++ .../src/containers/Community/Table.js | 34 ++++++++ .../src/containers/CommunityContainer.js | 11 --- .../src/containers/LayoutContainer.js | 7 +- client/coral-admin/src/helpers/response.js | 27 +++++++ client/coral-admin/src/index.js | 1 - client/coral-admin/src/reducers/community.js | 47 +++++++++++ client/coral-admin/src/reducers/index.js | 6 +- client/coral-admin/src/translations.js | 8 ++ models/user.js | 21 +++++ routes/api/index.js | 1 + routes/api/user/index.js | 63 +++++++++++++++ webpack.config.dev.js | 6 ++ webpack.config.js | 2 +- 28 files changed, 517 insertions(+), 33 deletions(-) create mode 100644 client/coral-admin/src/actions/community.js delete mode 100644 client/coral-admin/src/components/Page.js create mode 100644 client/coral-admin/src/components/ui/Layout.css create mode 100644 client/coral-admin/src/constants/community.js create mode 100644 client/coral-admin/src/containers/Community/Community.css create mode 100644 client/coral-admin/src/containers/Community/Community.js create mode 100644 client/coral-admin/src/containers/Community/CommunityContainer.js create mode 100644 client/coral-admin/src/containers/Community/Loading.js create mode 100644 client/coral-admin/src/containers/Community/NoResults.js create mode 100644 client/coral-admin/src/containers/Community/Pager.css create mode 100644 client/coral-admin/src/containers/Community/Pager.js create mode 100644 client/coral-admin/src/containers/Community/Table.js delete mode 100644 client/coral-admin/src/containers/CommunityContainer.js create mode 100644 client/coral-admin/src/helpers/response.js create mode 100644 client/coral-admin/src/reducers/community.js create mode 100644 routes/api/user/index.js diff --git a/.eslintignore b/.eslintignore index 1521c8b76..53c37a166 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1 @@ -dist +dist \ No newline at end of file diff --git a/client/coral-admin/src/AppRouter.js b/client/coral-admin/src/AppRouter.js index d1b25d0f1..5d21fc819 100644 --- a/client/coral-admin/src/AppRouter.js +++ b/client/coral-admin/src/AppRouter.js @@ -4,7 +4,7 @@ import {Router, Route, IndexRoute, browserHistory} from 'react-router'; import ModerationQueue from 'containers/ModerationQueue'; import CommentStream from 'containers/CommentStream'; import Configure from 'containers/Configure'; -import CommunityContainer from 'containers/CommunityContainer'; +import CommunityContainer from 'containers/Community/CommunityContainer'; import LayoutContainer from 'containers/LayoutContainer'; const routes = ( diff --git a/client/coral-admin/src/actions/community.js b/client/coral-admin/src/actions/community.js new file mode 100644 index 000000000..06c8ab0f6 --- /dev/null +++ b/client/coral-admin/src/actions/community.js @@ -0,0 +1,42 @@ +import qs from 'qs'; + +import { + FETCH_COMMENTERS_REQUEST, + FETCH_COMMENTERS_SUCCESS, + FETCH_COMMENTERS_FAILURE, + SORT_UPDATE, + COMMENTERS_NEW_PAGE +} from '../constants/community'; + +import {base, getInit, handleResp} from '../helpers/response'; + +export const fetchCommenters = (query = {}) => dispatch => { + dispatch(requestFetchCommenters()); + fetch(`${base}/user?${qs.stringify(query)}`, getInit('GET')) + .then(handleResp) + .then(({result, page, count, limit, totalPages}) => + dispatch({ + type: FETCH_COMMENTERS_SUCCESS, + commenters: result, + page, + count, + limit, + totalPages + }) + ) + .catch(error => dispatch({type: FETCH_COMMENTERS_FAILURE, error})); +}; + +const requestFetchCommenters = () => ({ + type: FETCH_COMMENTERS_REQUEST +}); + +export const updateSorting = sort => ({ + type: SORT_UPDATE, + sort +}); + +export const newPage = () => ({ + type: COMMENTERS_NEW_PAGE +}); + diff --git a/client/coral-admin/src/components/Page.js b/client/coral-admin/src/components/Page.js deleted file mode 100644 index 845c10cb8..000000000 --- a/client/coral-admin/src/components/Page.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import {Layout} from 'react-mdl'; -import 'material-design-lite'; -import Header from 'components/Header'; - -export default (props) => ( - -
- {props.children} -
-
-); diff --git a/client/coral-admin/src/components/ui/Header.js b/client/coral-admin/src/components/ui/Header.js index b7c654bd4..86e622672 100644 --- a/client/coral-admin/src/components/ui/Header.js +++ b/client/coral-admin/src/components/ui/Header.js @@ -9,6 +9,9 @@ export default () => ( Moderate Community Configure + + {`v${process.env.VERSION}`} + ); diff --git a/client/coral-admin/src/components/ui/Layout.css b/client/coral-admin/src/components/ui/Layout.css new file mode 100644 index 000000000..779dec8b9 --- /dev/null +++ b/client/coral-admin/src/components/ui/Layout.css @@ -0,0 +1,4 @@ +.layout { + max-width: 1170px; + margin: 0 auto; +} \ No newline at end of file diff --git a/client/coral-admin/src/components/ui/Layout.js b/client/coral-admin/src/components/ui/Layout.js index e80d55c30..3e1b9cf2d 100644 --- a/client/coral-admin/src/components/ui/Layout.js +++ b/client/coral-admin/src/components/ui/Layout.js @@ -2,11 +2,14 @@ import React from 'react'; import {Layout as LayoutMDL} from 'react-mdl'; import Header from './Header'; import Drawer from './Drawer'; +import styles from './Layout.css'; export const Layout = ({children}) => (
- {children} +
+ {children} +
); diff --git a/client/coral-admin/src/constants/community.js b/client/coral-admin/src/constants/community.js new file mode 100644 index 000000000..e628a14d6 --- /dev/null +++ b/client/coral-admin/src/constants/community.js @@ -0,0 +1,5 @@ +export const FETCH_COMMENTERS_REQUEST = 'FETCH_COMMENTERS_REQUEST'; +export const FETCH_COMMENTERS_SUCCESS = 'FETCH_COMMENTERS_SUCCESS'; +export const FETCH_COMMENTERS_FAILURE = 'FETCH_COMMENTERS_FAILURE'; +export const SORT_UPDATE = 'SORT_UPDATE'; +export const COMMENTERS_NEW_PAGE = 'COMMENTERS_NEW_PAGE'; diff --git a/client/coral-admin/src/containers/Community/Community.css b/client/coral-admin/src/containers/Community/Community.css new file mode 100644 index 000000000..63148da7e --- /dev/null +++ b/client/coral-admin/src/containers/Community/Community.css @@ -0,0 +1,22 @@ +.dataTable { + width: 100%; +} + +.roleButton { + display: block; +} + +.searchInput { + display: block; + padding-left: 40px; + /*border: none;*/ +} + +.searchBox { + /*border: 1px solid rgba(0,0,0,.12);*/ + background: white; +} + +.email { + display: block; +} \ No newline at end of file diff --git a/client/coral-admin/src/containers/Community/Community.js b/client/coral-admin/src/containers/Community/Community.js new file mode 100644 index 000000000..8e0b955a4 --- /dev/null +++ b/client/coral-admin/src/containers/Community/Community.js @@ -0,0 +1,68 @@ +import React from 'react'; +import I18n from 'coral-framework/i18n/i18n'; +import translations from '../../translations'; +import {Grid, Cell} from 'react-mdl'; + +import styles from './Community.css'; +import Table from './Table'; +import Loading from './Loading'; +import NoResults from './NoResults'; +import Pager from './Pager'; + +const lang = new I18n(translations); + +const tableHeaders = [ + { + title: lang.t('community.username_and_email'), + field: 'displayName' + }, + { + title: lang.t('community.account_creation_date'), + field: 'created_at' + } +]; + +const Community = ({isFetching, commenters, ...props}) => { + const hasResults = !isFetching && !!commenters.length; + return ( + + +
+
+ +
+ +
+
+
+
+ + { isFetching && } + { !hasResults && } + { hasResults && + + } + + + + ); +}; + +export default Community; diff --git a/client/coral-admin/src/containers/Community/CommunityContainer.js b/client/coral-admin/src/containers/Community/CommunityContainer.js new file mode 100644 index 000000000..cf67dba4d --- /dev/null +++ b/client/coral-admin/src/containers/Community/CommunityContainer.js @@ -0,0 +1,80 @@ +import React, {Component} from 'react'; +import {connect} from 'react-redux'; +import { + fetchCommenters, + updateSorting, + newPage, +} from '../../actions/community'; + +import Community from './Community'; + +class CommunityContainer extends Component { + constructor(props) { + super(props); + + this.state = { + searchValue: '' + }; + + this.onKeyDownHandler = this.onKeyDownHandler.bind(this); + this.onChangeHandler = this.onChangeHandler.bind(this); + this.onHeaderClickHandler = this.onHeaderClickHandler.bind(this); + this.onNewPageHandler = this.onNewPageHandler.bind(this); + } + + onKeyDownHandler(e) { + if (e.key === 'Enter') { + e.preventDefault(); + this.search(); + } + } + + onChangeHandler(e) { + this.setState({ + searchValue: e.target.value + }); + } + + search(query = {}) { + const {community} = this.props; + + this.props.dispatch(fetchCommenters({ + value: this.state.searchValue, + field: community.get('field'), + asc: community.get('asc'), + ...query + })); + } + + componentDidMount() { + this.search(); + } + + onHeaderClickHandler(sort) { + this.props.dispatch(updateSorting(sort)); + this.search(); + } + + onNewPageHandler(page) { + this.props.dispatch(newPage(page)); + this.search({page}); + } + + render() { + const {searchValue} = this.state; + const {community} = this.props; + return ( + + ); + } +} + +export default connect(({community}) => ({community}))(CommunityContainer); diff --git a/client/coral-admin/src/containers/Community/Loading.js b/client/coral-admin/src/containers/Community/Loading.js new file mode 100644 index 000000000..beda271eb --- /dev/null +++ b/client/coral-admin/src/containers/Community/Loading.js @@ -0,0 +1,7 @@ +import React from 'react'; + +const Loading = () => ( +

Loading results

+); + +export default Loading; diff --git a/client/coral-admin/src/containers/Community/NoResults.js b/client/coral-admin/src/containers/Community/NoResults.js new file mode 100644 index 000000000..9e0663960 --- /dev/null +++ b/client/coral-admin/src/containers/Community/NoResults.js @@ -0,0 +1,9 @@ +import React from 'react'; + +const NoResults = () => ( +
+ No users found with that user name or email address +
+); + +export default NoResults; diff --git a/client/coral-admin/src/containers/Community/Pager.css b/client/coral-admin/src/containers/Community/Pager.css new file mode 100644 index 000000000..82e96f727 --- /dev/null +++ b/client/coral-admin/src/containers/Community/Pager.css @@ -0,0 +1,10 @@ +.li { + display: inline-block; + margin-right: 5px; + padding: 0; + min-width: 30px; +} + +.current { + background: #e3edf3; +} \ No newline at end of file diff --git a/client/coral-admin/src/containers/Community/Pager.js b/client/coral-admin/src/containers/Community/Pager.js new file mode 100644 index 000000000..3184cfca0 --- /dev/null +++ b/client/coral-admin/src/containers/Community/Pager.js @@ -0,0 +1,45 @@ +import React, {PropTypes} from 'react'; +import styles from './Pager.css'; + +const Rows = (curr, total, onClickHandler) => Array.from(Array(total)).map((e, i) => +
  • onClickHandler(i + 1)}> + {i + 1} +
  • +); + +const Pager = ({totalPages, page, onNewPageHandler}) => ( +
    +
      + { + (totalPages > page) ? +
    • onNewPageHandler(page - 1)}> + Prev +
    • + : + null + } + {Rows(page, totalPages, onNewPageHandler)} + { + (page < totalPages) ? +
    • onNewPageHandler(page + 1)}> + Next +
    • + : + null + } +
    +
    +); + +Pager.propTypes = { + totalPages: PropTypes.number.isRequired, + page: PropTypes.number.isRequired, +}; + +export default Pager; + diff --git a/client/coral-admin/src/containers/Community/Table.js b/client/coral-admin/src/containers/Community/Table.js new file mode 100644 index 000000000..a15a88723 --- /dev/null +++ b/client/coral-admin/src/containers/Community/Table.js @@ -0,0 +1,34 @@ +import React from 'react'; +import styles from './Community.css'; + +const Table = ({headers, data, onHeaderClickHandler}) => ( +
    + + + {headers.map((header, i) =>( + + ))} + + + + {data.map((row, i)=> ( + + + + + ))} + +
    onHeaderClickHandler({field: header.field})}> + {header.title} +
    + {row.displayName} + {row.profiles.map(({id}) => id)} + + {row.created_at} +
    +); + +export default Table; diff --git a/client/coral-admin/src/containers/CommunityContainer.js b/client/coral-admin/src/containers/CommunityContainer.js deleted file mode 100644 index b936edcec..000000000 --- a/client/coral-admin/src/containers/CommunityContainer.js +++ /dev/null @@ -1,11 +0,0 @@ -import React, {Component} from 'react'; - -export default class CommunityContainer extends Component { - render() { - return ( -
    -

    Community

    -
    - ); - } -} diff --git a/client/coral-admin/src/containers/LayoutContainer.js b/client/coral-admin/src/containers/LayoutContainer.js index 50f54a631..921af251d 100644 --- a/client/coral-admin/src/containers/LayoutContainer.js +++ b/client/coral-admin/src/containers/LayoutContainer.js @@ -1,18 +1,19 @@ -import React, {Component}from 'react'; +import React, {Component} from 'react'; import {connect} from 'react-redux'; import {Layout} from '../components/ui/Layout'; class LayoutContainer extends Component { render () { - return ; + return ; } } LayoutContainer.propTypes = {}; -const mapStateToProps = () => ({data: {}}); +const mapStateToProps = () => ({}); const mapDispatchToProps = (dispatch) => ({dispatch}); export default connect(mapStateToProps, mapDispatchToProps)(LayoutContainer); + diff --git a/client/coral-admin/src/helpers/response.js b/client/coral-admin/src/helpers/response.js new file mode 100644 index 000000000..439ba5a8a --- /dev/null +++ b/client/coral-admin/src/helpers/response.js @@ -0,0 +1,27 @@ +export const base = '/api/v1'; + +export const getInit = (method, body) => { + const headers = new Headers({ + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }); + + const init = {method, headers}; + 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/index.js b/client/coral-admin/src/index.js index aed9d5748..84d1b84ad 100644 --- a/client/coral-admin/src/index.js +++ b/client/coral-admin/src/index.js @@ -1,4 +1,3 @@ - import React from 'react'; import ReactDOM from 'react-dom'; import App from './components/App'; diff --git a/client/coral-admin/src/reducers/community.js b/client/coral-admin/src/reducers/community.js new file mode 100644 index 000000000..8d5dfd2c3 --- /dev/null +++ b/client/coral-admin/src/reducers/community.js @@ -0,0 +1,47 @@ +import {Map} from 'immutable'; + +import { + FETCH_COMMENTERS_REQUEST, + FETCH_COMMENTERS_FAILURE, + FETCH_COMMENTERS_SUCCESS, + SORT_UPDATE +} from '../constants/community'; + +const initialState = Map({ + community: Map(), + isFetching: false, + error: '', + commenters: [], + field: 'created_at', + asc: false, + totalPages: 0, + page: 0 +}); + +export default function community (state = initialState, action) { + switch (action.type) { + case FETCH_COMMENTERS_REQUEST : + return state + .set('isFetching', true); + case FETCH_COMMENTERS_FAILURE : + return state + .set('isFetching', false) + .set('error', action.error); + case FETCH_COMMENTERS_SUCCESS : { + const {commenters, type, ...rest} = action; // eslint-disable-line + return state + .merge({ + isFetching: false, + error: '', + ...rest + }) + .set('commenters', commenters); // Sets to normal array + } + case SORT_UPDATE : + return state + .set('field', action.sort.field) + .set('asc', !state.get('asc')); + default : + return state; + } +} diff --git a/client/coral-admin/src/reducers/index.js b/client/coral-admin/src/reducers/index.js index 63176ca3b..1b29ced69 100644 --- a/client/coral-admin/src/reducers/index.js +++ b/client/coral-admin/src/reducers/index.js @@ -1,10 +1,12 @@ - import {combineReducers} from 'redux'; import comments from 'reducers/comments'; import settings from 'reducers/settings'; +import community from 'reducers/community'; // Combine all reducers into a main one export default combineReducers({ settings, - comments + comments, + community }); + diff --git a/client/coral-admin/src/translations.js b/client/coral-admin/src/translations.js index 5302c1221..67a8142fd 100644 --- a/client/coral-admin/src/translations.js +++ b/client/coral-admin/src/translations.js @@ -1,5 +1,9 @@ export default { en: { + 'community': { + username_and_email: 'Username and Email', + account_creation_date: 'Account Creation Date' + }, 'modqueue': { 'pending': 'pending', 'rejected': 'rejected', @@ -24,6 +28,10 @@ export default { } }, es: { + 'community': { + username_and_email: 'Usuario y E-mail', + account_creation_date: 'Fecha de creación de la cuenta' + }, 'modqueue': { 'pending': 'pendiente', 'rejected': 'rechazado', diff --git a/models/user.js b/models/user.js index ac642c910..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. diff --git a/routes/api/index.js b/routes/api/index.js index d161cf622..2fb489b88 100644 --- a/routes/api/index.js +++ b/routes/api/index.js @@ -6,5 +6,6 @@ router.use('/asset', require('./asset')); 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/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/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({ From 0c998e11969907061ea9baa2d359dadbee3ac58e Mon Sep 17 00:00:00 2001 From: David Erwin Date: Fri, 11 Nov 2016 11:15:11 -0500 Subject: [PATCH 09/13] Lint --- client/coral-framework/store/actions/config.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/coral-framework/store/actions/config.js b/client/coral-framework/store/actions/config.js index 800017102..f131b8c82 100644 --- a/client/coral-framework/store/actions/config.js +++ b/client/coral-framework/store/actions/config.js @@ -16,8 +16,9 @@ export const FETCH_CONFIG_SUCCESS = 'FETCH_CONFIG_SUCCESS'; export function fetchConfig () { return (dispatch) => { + dispatch({type: FETCH_CONFIG_REQUEST}); - console.log('Fetching settings'); + return fetch('/api/v1/settings') .then( response => { @@ -26,11 +27,11 @@ export function fetchConfig () { } ) .then((json) => { - console.log(json); return dispatch({type: FETCH_CONFIG_SUCCESS, config: fromJS(json)}); - }).catch((error) => { - console.log(error); + }) + .catch((error) => { dispatch({type: FETCH_CONFIG_FAILED, error}); }); + }; } From f6c295ca78a22009607271324c1a8eb2401b4477 Mon Sep 17 00:00:00 2001 From: David Erwin Date: Fri, 11 Nov 2016 11:16:19 -0500 Subject: [PATCH 10/13] Lint --- client/coral-plugin-commentbox/CommentBox.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/coral-plugin-commentbox/CommentBox.js b/client/coral-plugin-commentbox/CommentBox.js index 3811e0cd9..2fb097610 100644 --- a/client/coral-plugin-commentbox/CommentBox.js +++ b/client/coral-plugin-commentbox/CommentBox.js @@ -44,7 +44,8 @@ class CommentBox extends Component { appendItemArray(parent_id || id, related, comment_id, !parent_id, parent_type); addNotification('success', 'Your comment has been posted.'); } - }).catch((err) => console.error(err)); + }) + .catch((err) => console.error(err)); this.setState({body: ''}); } From 309f53b359e3cf6db5aeb112a91674f243857c79 Mon Sep 17 00:00:00 2001 From: David Jay Date: Fri, 11 Nov 2016 11:44:50 -0500 Subject: [PATCH 11/13] Adding notifcation translations. --- client/coral-plugin-commentbox/translations.json | 6 ++++-- client/coral-plugin-flags/translations.json | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/client/coral-plugin-commentbox/translations.json b/client/coral-plugin-commentbox/translations.json index eee577b2a..7e68b44b5 100644 --- a/client/coral-plugin-commentbox/translations.json +++ b/client/coral-plugin-commentbox/translations.json @@ -2,11 +2,13 @@ "en": { "post": "Post", "reply": "Reply", - "comment": "Comment" + "comment": "Comment", + "comment-post-notif": "Your comment has been posted." }, "es": { "post": "Publicar", "reply": "Respuesta", - "comment": "Comentario" + "comment": "Comentario", + "comment-post-notif": "¡traduceme!" } } diff --git a/client/coral-plugin-flags/translations.json b/client/coral-plugin-flags/translations.json index f5fb9ba9a..0721d3e00 100644 --- a/client/coral-plugin-flags/translations.json +++ b/client/coral-plugin-flags/translations.json @@ -1,10 +1,12 @@ { "en": { "flag": "Flag", - "flagged": "Flagged" + "flagged": "Flagged", + "flag-notif": "Thank you for reporting this comment. Our moderation team has been notified and will review it shortly." }, "es": { "flag": "¡traduceme!", - "flagged": "¡traduceme!" + "flagged": "¡traduceme!", + "flag-notif": "¡traduceme!" } } From aeefa89e0a38900e05b277ee6f2531b4753e58f1 Mon Sep 17 00:00:00 2001 From: gaba Date: Fri, 11 Nov 2016 09:22:05 -0800 Subject: [PATCH 12/13] Fix spanish translations. --- client/coral-plugin-commentbox/translations.json | 4 ++-- client/coral-plugin-flags/translations.json | 6 +++--- client/coral-plugin-replies/translations.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/coral-plugin-commentbox/translations.json b/client/coral-plugin-commentbox/translations.json index 7e68b44b5..cf407bdae 100644 --- a/client/coral-plugin-commentbox/translations.json +++ b/client/coral-plugin-commentbox/translations.json @@ -7,8 +7,8 @@ }, "es": { "post": "Publicar", - "reply": "Respuesta", + "reply": "Responder", "comment": "Comentario", - "comment-post-notif": "¡traduceme!" + "comment-post-notif": "Tu comentario fue publicado." } } diff --git a/client/coral-plugin-flags/translations.json b/client/coral-plugin-flags/translations.json index 0721d3e00..28eb9f8cb 100644 --- a/client/coral-plugin-flags/translations.json +++ b/client/coral-plugin-flags/translations.json @@ -5,8 +5,8 @@ "flag-notif": "Thank you for reporting this comment. Our moderation team has been notified and will review it shortly." }, "es": { - "flag": "¡traduceme!", - "flagged": "¡traduceme!", - "flag-notif": "¡traduceme!" + "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/translations.json b/client/coral-plugin-replies/translations.json index b54e2b398..b4d820c44 100644 --- a/client/coral-plugin-replies/translations.json +++ b/client/coral-plugin-replies/translations.json @@ -3,6 +3,6 @@ "reply": "Reply" }, "es": { - "reply": "Respuesta" + "reply": "Responder" } } From ba43e9d6ddea953d2b11405c0646091f6193324d Mon Sep 17 00:00:00 2001 From: David Jay Date: Fri, 11 Nov 2016 13:46:35 -0500 Subject: [PATCH 13/13] Adding translations for comment post notifications. --- client/coral-plugin-commentbox/CommentBox.js | 6 +++--- client/coral-plugin-commentbox/translations.json | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/client/coral-plugin-commentbox/CommentBox.js b/client/coral-plugin-commentbox/CommentBox.js index 0018c6866..9032ad328 100644 --- a/client/coral-plugin-commentbox/CommentBox.js +++ b/client/coral-plugin-commentbox/CommentBox.js @@ -40,7 +40,7 @@ class CommentBox extends Component { postItem(comment, 'comments') .then((comment_id) => { if (premod === 'pre') { - addNotification('success', 'Your comment has been posted and is being reviewed by our moderation team.'); + 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.'); @@ -60,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}/> diff --git a/client/coral-plugin-commentbox/translations.json b/client/coral-plugin-commentbox/translations.json index 7e68b44b5..e8eb8ad52 100644 --- a/client/coral-plugin-commentbox/translations.json +++ b/client/coral-plugin-commentbox/translations.json @@ -3,12 +3,16 @@ "post": "Post", "reply": "Reply", "comment": "Comment", - "comment-post-notif": "Your comment has been posted." + "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", - "comment-post-notif": "¡traduceme!" + "name": "Nombre", + "comment-post-notif": "¡traduceme!", + "comment-post-notif-premod": "¡traduceme!" } }