From a9bc90619dc080113058f07c78f6cc4288b06aa8 Mon Sep 17 00:00:00 2001 From: David Jay Date: Mon, 5 Dec 2016 15:59:16 -0500 Subject: [PATCH 01/29] Adding popup on report button click. --- client/coral-plugin-flags/FlagButton.js | 84 ++++++++++++--------- client/coral-plugin-flags/translations.json | 8 +- client/coral-ui/components/PopupMenu.css | 32 ++++++++ client/coral-ui/components/PopupMenu.js | 6 ++ client/coral-ui/index.js | 1 + 5 files changed, 92 insertions(+), 39 deletions(-) create mode 100644 client/coral-ui/components/PopupMenu.css create mode 100644 client/coral-ui/components/PopupMenu.js diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index cbb0fef63..ed59fc774 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -1,47 +1,61 @@ -import React from 'react'; +import React, {Component} from 'react'; import {I18n} from '../coral-framework'; import translations from './translations.json'; +import {PopupMenu} from 'coral-ui'; const name = 'coral-plugin-flags'; -const FlagButton = ({flag, id, postAction, deleteAction, addItem, updateItem, addNotification, currentUser}) => { - const flagged = flag && flag.current_user; - const onFlagClick = () => { - if (!currentUser) { +export default class FlagButton extends Component { + + state = { + showMenu: false, + } + + onFlagClick = () => { + if (!this.props.currentUser) { return; } - if (!flagged) { - postAction(id, 'flag', currentUser.id, 'comments') - .then((action) => { - let id = `${action.action_type}_${action.item_id}`; - addItem({id, current_user: action, count: flag ? flag.count + 1 : 1}, 'actions'); - updateItem(action.item_id, action.action_type, id, 'comments'); - }); - addNotification('success', lang.t('flag-notif')); - } else { - deleteAction(flagged.id) - .then(() => { - updateItem(id, 'flag', '', 'comments'); - }); - addNotification('success', lang.t('flag-notif-remove')); - } - }; + this.setState({showMenu: !this.state.showMenu}); + } - return
- -
; -}; + render () { + const {flag} = this.props; + // const {flag, id, postAction, deleteAction, addItem, updateItem, addNotification, currentUser} = this.props; + const flagged = flag && flag.current_user; + // const onFlagClick = () => { -export default FlagButton; + // if (!flagged) { + // postAction(id, 'flag', currentUser.id, 'comments') + // .then((action) => { + // let id = `${action.action_type}_${action.item_id}`; + // addItem({id, current_user: action, count: flag ? flag.count + 1 : 1}, 'actions'); + // updateItem(action.item_id, action.action_type, id, 'comments'); + // }); + // addNotification('success', lang.t('flag-notif')); + // } else { + // deleteAction(flagged.id) + // .then(() => { + // updateItem(id, 'flag', '', 'comments'); + // }); + // addNotification('success', lang.t('flag-notif-remove')); + // } + // }; + + return
+ { this.state.showMenu && test } + +
; + } +} const styles = { flaggedIcon: { diff --git a/client/coral-plugin-flags/translations.json b/client/coral-plugin-flags/translations.json index fb2daa883..d87445fb8 100644 --- a/client/coral-plugin-flags/translations.json +++ b/client/coral-plugin-flags/translations.json @@ -1,13 +1,13 @@ { "en": { - "flag": "Flag", - "flagged": "Flagged", + "flag": "Report", + "flagged": "Reported", "flag-notif": "Thank you for reporting this comment. Our moderation team has been notified and will review it shortly.", "flag-notif-remove": "Your flag has been removed." }, "es": { - "flag": "Marcar", - "flagged": "Marcado", + "flag": "Informe", + "flagged": "Informado", "flag-notif": "Gracias por marcar este comentario. Nuestro equipo de moderación ha sido notificado y muy pronto lo va a revisar.", "flag-notif-remove": "¡traduceme!" } diff --git a/client/coral-ui/components/PopupMenu.css b/client/coral-ui/components/PopupMenu.css new file mode 100644 index 000000000..93d4535cb --- /dev/null +++ b/client/coral-ui/components/PopupMenu.css @@ -0,0 +1,32 @@ +.popupMenu { + display: inline-block; + position: absolute; + width: inherit; + border: solid 1px #2376D8; + bottom: 36px; + box-sizing: border-box; + background: white; + border-radius: 3px; + padding: 20px 10px; + z-index: 3; +} + +.popupMenu:before{ + content: ''; + border: 10px solid transparent; + border-top-color: white; + position: absolute; + left: 1em; + top: 56px; + z-index: 2; +} + +.popupMenu:after{ + content: ''; + border: 10px solid transparent; + border-top-color: #2376D8; + position: absolute; + left: 1em; + top: 57px; + z-index: 1; +} diff --git a/client/coral-ui/components/PopupMenu.js b/client/coral-ui/components/PopupMenu.js new file mode 100644 index 000000000..dfc81c3a1 --- /dev/null +++ b/client/coral-ui/components/PopupMenu.js @@ -0,0 +1,6 @@ +import React from 'react'; +import styles from './PopupMenu.css'; + +export default ({children}) => ( + {children} +); diff --git a/client/coral-ui/index.js b/client/coral-ui/index.js index ffdb3bbd2..b40765052 100644 --- a/client/coral-ui/index.js +++ b/client/coral-ui/index.js @@ -7,3 +7,4 @@ export {default as TabContent} from './components/TabContent'; export {default as Button} from './components/Button'; export {default as Spinner} from './components/Spinner'; export {default as Tooltip} from './components/Tooltip'; +export {default as PopupMenu} from './components/PopupMenu'; From ab43d1f0ac4c7c1b287be9a1a2ee5de1a10e4013 Mon Sep 17 00:00:00 2001 From: David Jay Date: Mon, 5 Dec 2016 17:38:13 -0500 Subject: [PATCH 02/29] Showing first set of options in menu. --- client/coral-embed-stream/style/default.css | 7 ++++++ client/coral-plugin-flags/FlagButton.js | 26 +++++++++++++++++---- client/coral-plugin-flags/translations.json | 18 +++++++------- client/coral-ui/components/PopupMenu.css | 4 ++-- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/client/coral-embed-stream/style/default.css b/client/coral-embed-stream/style/default.css index b6fe672cc..bf55bde7d 100644 --- a/client/coral-embed-stream/style/default.css +++ b/client/coral-embed-stream/style/default.css @@ -195,3 +195,10 @@ hr { float: right; margin: 8px; } + +/* Flag Styles */ + +.coral-plugin-flags-popup-header { + font-weight: bolder; + font-size: 14px; +} diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index ed59fc774..1eafc1d09 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -1,7 +1,7 @@ import React, {Component} from 'react'; import {I18n} from '../coral-framework'; import translations from './translations.json'; -import {PopupMenu} from 'coral-ui'; +import {PopupMenu, Button} from 'coral-ui'; const name = 'coral-plugin-flags'; @@ -9,6 +9,8 @@ export default class FlagButton extends Component { state = { showMenu: false, + itemType: '', + reason: '' } onFlagClick = () => { @@ -42,12 +44,28 @@ export default class FlagButton extends Component { // }; return
- { this.state.showMenu && test } + { + this.state.showMenu && + + {lang.t('report-header')} +
+ Flag username
+ Flag comment
+
+ +
+ } From 9da19e87eab9b31d02fffad5cce58dd146e93092 Mon Sep 17 00:00:00 2001 From: David Jay Date: Tue, 6 Dec 2016 17:48:08 -0500 Subject: [PATCH 04/29] Adding options to popup menu. --- client/coral-plugin-flags/FlagButton.js | 114 ++++++++++++++++++----- client/coral-ui/components/PopupMenu.css | 1 + 2 files changed, 93 insertions(+), 22 deletions(-) diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index da508bf3d..69d94509d 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -10,21 +10,70 @@ export default class FlagButton extends Component { state = { showMenu: false, itemType: '', - reason: '' + reason: '', + step: 1 } - onFlagClick = () => { + onReportClick = () => { if (!this.props.currentUser) { return; } this.setState({showMenu: !this.state.showMenu}); } + onPopupContinue = () => { + this.setState({step: this.state.step + 1}); + } + + getPopupMenu = (step) => { + switch(step) { + case 1: + return { + header: 'Report an issue', + options: [ + { val: 'username', text: 'Flag username'}, + { val: 'comment', text: 'Flag comment'}, + ], + button: 'Continue', + sets: 'itemType' + } + case 2: + const options = this.state.itemType === 'comments' ? + [ + { val: 'I don\'t agree with this comment', text: 'I don\'t agree with this comment'}, + { val: 'This comment is offensive', text: 'This comment is offensive'}, + { val: 'This comment reveals personally identifiable inforation without consent', text: 'This comment reveals personally identifiable inforation without consent'}, + { val: 'Other', text: 'Other'}, + ] + :[ + { val: 'This username is offensive', text: 'This username is offensive'}, + { val: 'I don\'t like this username', text: 'I don\'t like this username'}, + { val: 'This looks like an ad/marketing', text: 'This looks like an ad/marketing'}, + { val: 'Other', text: 'Other'}, + ] + return { + header: 'Help us understand', + options, + button: 'Continue', + sets: 'reason' + } + case 3: + return { + header: 'Thank you for your input', + text: 'We value your safety and feedback. A moderator will review your flag.' + } + } + } + + onPopupOptionClick = (sets) => (e) => { + this.setState({[sets]: e.target.value}); + } + render () { const {flag} = this.props; // const {flag, id, postAction, deleteAction, addItem, updateItem, addNotification, currentUser} = this.props; const flagged = flag && flag.current_user; - // const onFlagClick = () => { + // const onReportClick = () => { // if (!flagged) { // postAction(id, 'flag', currentUser.id, 'comments') @@ -42,27 +91,10 @@ export default class FlagButton extends Component { // addNotification('success', lang.t('flag-notif-remove')); // } // }; + const popupMenu = this.getPopupMenu(this.state.step); return
- { - this.state.showMenu && - -
{lang.t('report-header')}
-
- -
- -
-
-
- 1 of 3 -
- -
- } -
+ { + this.state.showMenu && + +
{popupMenu.header}
+ { + popupMenu.text && +
{popupMenu.text}
+ } + { + popupMenu.options &&
+ { + popupMenu.options.map((option) => +
+ +
+
+ ) + } +
+ } +
+ {this.state.step} of 3 +
+ { + popupMenu.button && + } +
+ }
; } } diff --git a/client/coral-ui/components/PopupMenu.css b/client/coral-ui/components/PopupMenu.css index 8f08e8cc8..a0864a306 100644 --- a/client/coral-ui/components/PopupMenu.css +++ b/client/coral-ui/components/PopupMenu.css @@ -4,6 +4,7 @@ width: inherit; border: solid 1px #2376D8; bottom: 36px; + right: 25px; box-sizing: border-box; background: white; border-radius: 3px; From 343802462487dc3baac24734504f3ef67e70fbed Mon Sep 17 00:00:00 2001 From: David Jay Date: Tue, 6 Dec 2016 18:01:11 -0500 Subject: [PATCH 05/29] Posting flag action. --- client/coral-plugin-flags/FlagButton.js | 93 ++++++++++++------------- 1 file changed, 44 insertions(+), 49 deletions(-) diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index 69d94509d..82ac6694e 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -22,47 +22,61 @@ export default class FlagButton extends Component { } onPopupContinue = () => { - this.setState({step: this.state.step + 1}); + const {postAction, addItem, updateItem, currentUser, flag, id} = this.props; + const {itemType, reason, step} = this.state; + + this.setState({step: step + 1}); + + if (itemType && reason) { + postAction(id, 'flag', currentUser.id, itemType, reason) + .then((action) => { + let id = `${action.action_type}_${action.item_id}`; + addItem({id, current_user: action, count: flag ? flag.count + 1 : 1}, 'actions'); + updateItem(action.item_id, action.action_type, id, 'comments'); + }); + } } getPopupMenu = (step) => { switch(step) { - case 1: + case 1: { return { header: 'Report an issue', options: [ - { val: 'username', text: 'Flag username'}, - { val: 'comment', text: 'Flag comment'}, + {val: 'users', text: 'Flag username'}, + {val: 'comments', text: 'Flag comment'}, ], button: 'Continue', sets: 'itemType' - } - case 2: - const options = this.state.itemType === 'comments' ? - [ - { val: 'I don\'t agree with this comment', text: 'I don\'t agree with this comment'}, - { val: 'This comment is offensive', text: 'This comment is offensive'}, - { val: 'This comment reveals personally identifiable inforation without consent', text: 'This comment reveals personally identifiable inforation without consent'}, - { val: 'Other', text: 'Other'}, - ] - :[ - { val: 'This username is offensive', text: 'This username is offensive'}, - { val: 'I don\'t like this username', text: 'I don\'t like this username'}, - { val: 'This looks like an ad/marketing', text: 'This looks like an ad/marketing'}, - { val: 'Other', text: 'Other'}, - ] - return { - header: 'Help us understand', - options, - button: 'Continue', - sets: 'reason' - } - case 3: - return { - header: 'Thank you for your input', - text: 'We value your safety and feedback. A moderator will review your flag.' - } + }; } + case 2: { + const options = this.state.itemType === 'comments' ? + [ + {val: 'I don\'t agree with this comment', text: 'I don\'t agree with this comment'}, + {val: 'This comment is offensive', text: 'This comment is offensive'}, + {val: 'This comment reveals personally identifiable inforation without consent', text: 'This comment reveals personally identifiable inforation without consent'}, + {val: 'Other', text: 'Other'}, + ] + : [ + {val: 'This username is offensive', text: 'This username is offensive'}, + {val: 'I don\'t like this username', text: 'I don\'t like this username'}, + {val: 'This looks like an ad/marketing', text: 'This looks like an ad/marketing'}, + {val: 'Other', text: 'Other'}, + ]; + return { + header: 'Help us understand', + options, + button: 'Continue', + sets: 'reason' + }; + } + case 3: { + return { + header: 'Thank you for your input', + text: 'We value your safety and feedback. A moderator will review your flag.' + }; + }} } onPopupOptionClick = (sets) => (e) => { @@ -71,26 +85,7 @@ export default class FlagButton extends Component { render () { const {flag} = this.props; - // const {flag, id, postAction, deleteAction, addItem, updateItem, addNotification, currentUser} = this.props; const flagged = flag && flag.current_user; - // const onReportClick = () => { - - // if (!flagged) { - // postAction(id, 'flag', currentUser.id, 'comments') - // .then((action) => { - // let id = `${action.action_type}_${action.item_id}`; - // addItem({id, current_user: action, count: flag ? flag.count + 1 : 1}, 'actions'); - // updateItem(action.item_id, action.action_type, id, 'comments'); - // }); - // addNotification('success', lang.t('flag-notif')); - // } else { - // deleteAction(flagged.id) - // .then(() => { - // updateItem(id, 'flag', '', 'comments'); - // }); - // addNotification('success', lang.t('flag-notif-remove')); - // } - // }; const popupMenu = this.getPopupMenu(this.state.step); return
From 13d0dec84a3300181a2e9cb9cb9a06954c9b3228 Mon Sep 17 00:00:00 2001 From: David Jay Date: Tue, 6 Dec 2016 18:11:44 -0500 Subject: [PATCH 06/29] Updating postAction to send reasons to backend. --- client/coral-framework/actions/items.js | 5 +++-- models/action.js | 8 +++++--- routes/api/comments/index.js | 5 +++-- tests/client/coral-framework/store/itemActions.spec.js | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/client/coral-framework/actions/items.js b/client/coral-framework/actions/items.js index 2029714c7..5ad709111 100644 --- a/client/coral-framework/actions/items.js +++ b/client/coral-framework/actions/items.js @@ -217,11 +217,12 @@ export function postItem (item, type, id) { * */ -export function postAction (item_id, action_type, user_id, item_type) { +export function postAction (item_id, action_type, user_id, item_type, text) { return () => { const action = { action_type, - user_id + user_id, + text }; return coralApi(`/${item_type}/${item_id}/actions`, {method: 'POST', body: action}); diff --git a/models/action.js b/models/action.js index 891dbd4f5..591a7d4c0 100644 --- a/models/action.js +++ b/models/action.js @@ -11,7 +11,8 @@ const ActionSchema = new Schema({ action_type: String, item_type: String, item_id: String, - user_id: String + user_id: String, + text: String, }, { timestamps: { createdAt: 'created_at', @@ -34,12 +35,13 @@ ActionSchema.statics.findById = function(id) { * @param {String} action the new action to the comment * @return {Promise} */ -ActionSchema.statics.insertUserAction = ({item_id, item_type, user_id, action_type}) => { +ActionSchema.statics.insertUserAction = ({item_id, item_type, user_id, action_type, text}) => { const action = { item_id, item_type, user_id, - action_type + action_type, + text }; // Create/Update the action. diff --git a/routes/api/comments/index.js b/routes/api/comments/index.js index 3bdf4afc6..daf3ae121 100644 --- a/routes/api/comments/index.js +++ b/routes/api/comments/index.js @@ -111,11 +111,12 @@ router.put('/:comment_id/status', authorization.needed('admin'), (req, res, next router.post('/:comment_id/actions', (req, res, next) => { const { - action_type + action_type, + text } = req.body; Comment - .addAction(req.params.comment_id, req.user.id, action_type) + .addAction(req.params.comment_id, req.user.id, action_type, text) .then((action) => { res.status(201).json(action); }) diff --git a/tests/client/coral-framework/store/itemActions.spec.js b/tests/client/coral-framework/store/itemActions.spec.js index 45c41025f..ee5951dd6 100644 --- a/tests/client/coral-framework/store/itemActions.spec.js +++ b/tests/client/coral-framework/store/itemActions.spec.js @@ -155,7 +155,7 @@ describe('itemActions', () => { describe('postAction', () => { it ('should post an action', () => { fetchMock.post('*', {id: '456'}); - return actions.postAction('abc', 'flag', '123', 'comments')(store.dispatch) + return actions.postAction('abc', 'flag', '123', 'comments', 'Comment smells funny')(store.dispatch) .then(response => { expect(fetchMock.calls().matched[0][0]).to.equal('/api/v1/comments/abc/actions'); expect(response).to.deep.equal({id:'456'}); From 9e69a453d9c0f2ef123704e019195429b0994aab Mon Sep 17 00:00:00 2001 From: David Jay Date: Tue, 6 Dec 2016 18:14:53 -0500 Subject: [PATCH 07/29] Adding text to postAction in commentStream. --- client/coral-embed-stream/src/CommentStream.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index 26142a311..eafbbe900 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -253,7 +253,7 @@ const mapDispatchToProps = (dispatch) => ({ getStream: (rootId) => dispatch(getStream(rootId)), addNotification: (type, text) => dispatch(addNotification(type, text)), clearNotification: () => dispatch(clearNotification()), - postAction: (item, action, user, itemType) => dispatch(postAction(item, action, user, itemType)), + postAction: (item, action, user, itemType, text) => dispatch(postAction(item, action, user, itemType, text)), deleteAction: (item, action, user, itemType) => dispatch(deleteAction(item, action, user, itemType)), appendItemArray: (item, property, value, addToFront, itemType) => dispatch(appendItemArray(item, property, value, addToFront, itemType)), handleSignInDialog: () => dispatch(authActions.showSignInDialog()), From 74eb09a80759ab54b2cdf4b7e0144066f6a57e37 Mon Sep 17 00:00:00 2001 From: David Jay Date: Tue, 6 Dec 2016 18:20:19 -0500 Subject: [PATCH 08/29] Cleaning up after merge. --- client/coral-plugin-flags/FlagButton.js | 1 - 1 file changed, 1 deletion(-) diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index 41e9cccf3..baee12295 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -5,7 +5,6 @@ import {PopupMenu, Button} from 'coral-ui'; const name = 'coral-plugin-flags'; -<<<<<<< HEAD export default class FlagButton extends Component { state = { From 713cc0cda18fc37265ce458e96b55cefef2ba04a Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 7 Dec 2016 19:01:02 -0500 Subject: [PATCH 09/29] Posting actions to comment and user endpoints. --- .../coral-embed-stream/src/CommentStream.js | 4 +++- client/coral-framework/actions/items.js | 4 ++-- client/coral-plugin-flags/FlagButton.js | 20 ++++++++++++------- models/action.js | 8 +++++--- models/comment.js | 6 ++++-- models/user.js | 17 ++++++++++++++++ routes/api/comments/index.js | 5 +++-- routes/api/user/index.js | 18 +++++++++++++++++ 8 files changed, 65 insertions(+), 17 deletions(-) diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index 7d1e20a09..93a2c186e 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -145,6 +145,7 @@ class CommentStream extends Component { ({ getStream: (rootId) => dispatch(getStream(rootId)), addNotification: (type, text) => dispatch(addNotification(type, text)), clearNotification: () => dispatch(clearNotification()), - postAction: (item, action, user, itemType, text) => dispatch(postAction(item, action, user, itemType, text)), + postAction: (item, action, user, itemType, field, detail) => dispatch(postAction(item, action, user, itemType, field, detail)), showSignInDialog: () => dispatch(showSignInDialog()), deleteAction: (item, action, user, itemType) => dispatch(deleteAction(item, action, user, itemType)), appendItemArray: (item, property, value, addToFront, itemType) => dispatch(appendItemArray(item, property, value, addToFront, itemType)), diff --git a/client/coral-framework/actions/items.js b/client/coral-framework/actions/items.js index 5ad709111..2a0c118a2 100644 --- a/client/coral-framework/actions/items.js +++ b/client/coral-framework/actions/items.js @@ -217,12 +217,12 @@ export function postItem (item, type, id) { * */ -export function postAction (item_id, action_type, user_id, item_type, text) { +export function postAction (item_id, action_type, user_id, item_type, field, detail) { return () => { const action = { action_type, user_id, - text + field, detail }; return coralApi(`/${item_type}/${item_id}/actions`, {method: 'POST', body: action}); diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index baee12295..fcaa30b99 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -23,17 +23,18 @@ export default class FlagButton extends Component { } onPopupContinue = () => { - const {postAction, addItem, updateItem, currentUser, flag, id} = this.props; - const {itemType, reason, step} = this.state; + const {postAction, addItem, updateItem, currentUser, flag, id, author_id} = this.props; + const {itemType, field, detail, step} = this.state; this.setState({step: step + 1}); - if (itemType && reason) { - postAction(id, 'flag', currentUser.id, itemType, reason) + if (itemType && detail) { + const item_id = itemType === 'comments' ? id : author_id; + postAction(item_id, 'flag', currentUser.id, itemType, field, detail) .then((action) => { let id = `${action.action_type}_${action.item_id}`; addItem({id, current_user: action, count: flag ? flag.count + 1 : 1}, 'actions'); - updateItem(action.item_id, action.action_type, id, 'comments'); + updateItem(action.item_id, action.action_type, id, action.item_type); }); } } @@ -44,7 +45,7 @@ export default class FlagButton extends Component { return { header: 'Report an issue', options: [ - {val: 'users', text: 'Flag username'}, + {val: 'user', text: 'Flag username'}, {val: 'comments', text: 'Flag comment'}, ], button: 'Continue', @@ -69,7 +70,7 @@ export default class FlagButton extends Component { header: 'Help us understand', options, button: 'Continue', - sets: 'reason' + sets: 'detail' }; } case 3: { @@ -82,6 +83,11 @@ export default class FlagButton extends Component { onPopupOptionClick = (sets) => (e) => { this.setState({[sets]: e.target.value}); + + // If flagging a user, indicate that this is referencing the username rather than the bio + if(sets === 'itemType' && e.target.value === 'user') { + this.setState({field: 'username'}); + } } render () { diff --git a/models/action.js b/models/action.js index fa0892ffb..13b1c5494 100644 --- a/models/action.js +++ b/models/action.js @@ -13,7 +13,8 @@ const ActionSchema = new Schema({ item_type: String, item_id: String, user_id: String, - text: String, + field: String, // Used when an action references a particular field of an object. (e.g. a flag on a username or bio) + detail: String, // Describes the reason for an action (e.g. 'Username is offensive') }, { timestamps: { createdAt: 'created_at', @@ -36,13 +37,14 @@ ActionSchema.statics.findById = function(id) { * @param {String} action the new action to the comment * @return {Promise} */ -ActionSchema.statics.insertUserAction = ({item_id, item_type, user_id, action_type, text}) => { +ActionSchema.statics.insertUserAction = ({item_id, item_type, user_id, action_type, field, detail}) => { const action = { item_id, item_type, user_id, action_type, - text + field, + detail }; // Create/Update the action. diff --git a/models/comment.js b/models/comment.js index af9aa4cb1..80bfd67ea 100644 --- a/models/comment.js +++ b/models/comment.js @@ -284,11 +284,13 @@ CommentSchema.statics.pushStatus = (id, status, assigned_by = null) => Comment.u * @param {String} action the new action to the comment * @return {Promise} */ -CommentSchema.statics.addAction = (item_id, user_id, action_type) => Action.insertUserAction({ +CommentSchema.statics.addAction = (item_id, user_id, action_type, field, detail) => Action.insertUserAction({ item_id, item_type: 'comment', user_id, - action_type + action_type, + field, + detail }); /** diff --git a/models/user.js b/models/user.js index 336486a54..626b10e06 100644 --- a/models/user.js +++ b/models/user.js @@ -2,6 +2,7 @@ const mongoose = require('../mongoose'); const uuid = require('uuid'); const bcrypt = require('bcrypt'); const jwt = require('jsonwebtoken'); +const Action = require('./action'); // SALT_ROUNDS is the number of rounds that the bcrypt algorithm will run // through during the salting process. @@ -546,3 +547,19 @@ UserService.addBio = (id, bio) => ( new: true }) ); + +/** + * Add an action to the user. + * @param {String} item_id identifier of the user (uuid) + * @param {String} user_id user id of the action (uuid) + * @param {String} action the new action to the user + * @return {Promise} + */ +UserService.addAction = (item_id, user_id, action_type, field, detail) => Action.insertUserAction({ + item_id, + item_type: 'comment', + user_id, + action_type, + field, + detail +}); diff --git a/routes/api/comments/index.js b/routes/api/comments/index.js index b0b981fb3..25984405e 100644 --- a/routes/api/comments/index.js +++ b/routes/api/comments/index.js @@ -151,11 +151,12 @@ router.post('/:comment_id/actions', (req, res, next) => { const { action_type, - text + field, + detail } = req.body; Comment - .addAction(req.params.comment_id, req.user.id, action_type, text) + .addAction(req.params.comment_id, req.user.id, action_type, field, detail) .then((action) => { res.status(201).json(action); }) diff --git a/routes/api/user/index.js b/routes/api/user/index.js index 1765809ad..c5cf3d336 100644 --- a/routes/api/user/index.js +++ b/routes/api/user/index.js @@ -157,4 +157,22 @@ router.put('/:user_id/bio', (req, res, next) => { }); }); +router.post('/:user_id/actions', authorization.needed(), (req, res, next) => { + console.log('Hit action endpoint'); + const { + action_type, + field, + detail + } = req.body; + + User + .addAction(req.params.comment_id, req.user.id, action_type, field, detail) + .then((action) => { + res.status(201).json(action); + }) + .catch((err) => { + next(err); + }); +}); + module.exports = router; From a8805b464beced0117c2926671cd16c5817ec118 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 7 Dec 2016 20:19:07 -0500 Subject: [PATCH 10/29] Updating style. --- client/coral-embed-stream/style/default.css | 5 +- client/coral-plugin-flags/FlagButton.js | 72 +++++++++++---------- client/coral-ui/components/PopupMenu.css | 12 ++-- 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/client/coral-embed-stream/style/default.css b/client/coral-embed-stream/style/default.css index 0e1cdb3bb..273e4e0b2 100644 --- a/client/coral-embed-stream/style/default.css +++ b/client/coral-embed-stream/style/default.css @@ -200,8 +200,11 @@ hr { /* Flag Styles */ -.coral-plugin-flags-popup { +.coral-plugin-flags-popup span { min-width: 100px; + bottom: 36px; + right: 75px; + position: absolute; } .coral-plugin-flags-popup-form { diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index fcaa30b99..b223fad41 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -108,41 +108,43 @@ export default class FlagButton extends Component { { this.state.showMenu && - -
{popupMenu.header}
- { - popupMenu.text && -
{popupMenu.text}
- } - { - popupMenu.options &&
- { - popupMenu.options.map((option) => -
- -
-
- ) - } -
- } -
- {this.state.step} of 3 -
- { - popupMenu.button && - } -
+
+ +
{popupMenu.header}
+ { + popupMenu.text && +
{popupMenu.text}
+ } + { + popupMenu.options &&
+ { + popupMenu.options.map((option) => +
+ +
+
+ ) + } +
+ } +
+ {this.state.step} of 3 +
+ { + popupMenu.button && + } +
+
}
; } diff --git a/client/coral-ui/components/PopupMenu.css b/client/coral-ui/components/PopupMenu.css index a0864a306..fe57ba8b2 100644 --- a/client/coral-ui/components/PopupMenu.css +++ b/client/coral-ui/components/PopupMenu.css @@ -1,10 +1,8 @@ .popupMenu { display: inline-block; - position: absolute; width: inherit; - border: solid 1px #2376D8; - bottom: 36px; - right: 25px; + border: solid 1px #999; + box-shadow: 3px 3px 5px 0 rgba(0, 0, 0, 0.3); box-sizing: border-box; background: white; border-radius: 3px; @@ -17,7 +15,7 @@ border: 10px solid transparent; border-top-color: white; position: absolute; - left: 1em; + right: 3em; bottom: -20px; z-index: 2; } @@ -25,9 +23,9 @@ .popupMenu:after{ content: ''; border: 10px solid transparent; - border-top-color: #2376D8; + border-top-color: #999; position: absolute; - left: 1em; + right: 3em; bottom: -21px; z-index: 1; } From 3be1556803b10fea9b789a048278e262ae06332e Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 7 Dec 2016 20:30:30 -0500 Subject: [PATCH 11/29] Enabling i18n --- client/coral-plugin-flags/FlagButton.js | 28 ++++++++++----------- client/coral-plugin-flags/translations.json | 14 ++++++++++- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index b223fad41..115d1a577 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -43,40 +43,40 @@ export default class FlagButton extends Component { switch(step) { case 1: { return { - header: 'Report an issue', + header: lang.t('step-1-username'), options: [ - {val: 'user', text: 'Flag username'}, - {val: 'comments', text: 'Flag comment'}, + {val: 'user', text: lang.t('flag-username')}, + {val: 'comments', text: lang.t('flag-comment')}, ], - button: 'Continue', + button: lang.t('continue'), sets: 'itemType' }; } case 2: { const options = this.state.itemType === 'comments' ? [ - {val: 'I don\'t agree with this comment', text: 'I don\'t agree with this comment'}, - {val: 'This comment is offensive', text: 'This comment is offensive'}, - {val: 'This comment reveals personally identifiable inforation without consent', text: 'This comment reveals personally identifiable inforation without consent'}, + {val: 'I don\'t agree with this comment', text: lang.t('no-agree-comment')}, + {val: 'This comment is offensive', text: lang.t('comment-offensive')}, + {val: 'This comment reveals personally identifiable inforation without consent', text: lang.t('personal-info')}, {val: 'Other', text: 'Other'}, ] : [ - {val: 'This username is offensive', text: 'This username is offensive'}, - {val: 'I don\'t like this username', text: 'I don\'t like this username'}, - {val: 'This looks like an ad/marketing', text: 'This looks like an ad/marketing'}, + {val: 'This username is offensive', text: lang.t('username-offensive')}, + {val: 'I don\'t like this username', text: lang.t('no-like-username')}, + {val: 'This looks like an ad/marketing', text: lang.t('marketing')}, {val: 'Other', text: 'Other'}, ]; return { - header: 'Help us understand', + header: lang.t('step-2-header'), options, - button: 'Continue', + button: lang.t('continue'), sets: 'detail' }; } case 3: { return { - header: 'Thank you for your input', - text: 'We value your safety and feedback. A moderator will review your flag.' + header: lang.t('step-3-input'), + text: lang.t('thank-you') }; }} } diff --git a/client/coral-plugin-flags/translations.json b/client/coral-plugin-flags/translations.json index 2ccc2ea90..4cba5b40d 100644 --- a/client/coral-plugin-flags/translations.json +++ b/client/coral-plugin-flags/translations.json @@ -4,7 +4,19 @@ "reported": "Reported", "report-notif": "Thank you for reporting this comment. Our moderation team has been notified and will review it shortly.", "report-notif-remove": "Your report has been removed.", - "report-header": "Report an issue" + "step-1-header": "Report an issue", + "step-2-header": "Help us understand", + "step-3-header": "Thank you for your input", + "flag-username": "Flag username", + "flag-comment": "Flag comment", + "continue": "Continue", + "no-agree-comment": "I don't agree with this comment", + "comment-offensive": "This comment is offensive", + "personal-info": "This comment reveals personally identifiable inforation without consent", + "username-offensive": "This username is offensive", + "no-like-username": "I don't like this username", + "marketing": "This looks like an ad/marketing", + "thank-you": "We value your safety and feedback. A moderator will review your flag." }, "es": { "report": "Informe", From 18f7b07198353e21eb7b1d920ac9826d1945daaa Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 7 Dec 2016 21:12:31 -0500 Subject: [PATCH 12/29] Addressing setting bug caused by open thread feature. --- .../coral-embed-stream/src/CommentStream.js | 8 ++++---- client/coral-framework/actions/config.js | 2 +- client/coral-framework/reducers/config.js | 2 +- client/coral-framework/reducers/items.js | 3 +-- client/coral-plugin-flags/FlagButton.js | 6 +++--- client/coral-plugin-flags/translations.json | 20 ++++++++++++++++--- client/coral-ui/components/Button.css | 2 +- 7 files changed, 28 insertions(+), 15 deletions(-) diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index 93a2c186e..76a73171a 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -80,7 +80,7 @@ class CommentStream extends Component { const rootItem = this.props.items.assets && this.props.items.assets[rootItemId]; const {actions, users, comments} = this.props.items; const {loggedIn, user, showSignInDialog} = this.props.auth; - const {status} = this.props.config; + const {status, moderation} = this.props.config; const {activeTab} = this.state; return
@@ -109,7 +109,7 @@ class CommentStream extends Component { appendItemArray={this.props.appendItemArray} updateItem={this.props.updateItem} id={rootItemId} - premod={this.props.config.moderation} + premod={moderation} reply={false} author={user} /> @@ -165,7 +165,7 @@ class CommentStream extends Component { id={rootItemId} author={user} parent_id={commentId} - premod={this.props.config.moderation} + premod={moderation} showReply={comment.showReply}/> { comment.children && @@ -218,7 +218,7 @@ class CommentStream extends Component { author={user} parent_id={commentId} child_id={replyId} - premod={this.props.config.moderation} + premod={moderation} showReply={reply.showReply}/>
; }) diff --git a/client/coral-framework/actions/config.js b/client/coral-framework/actions/config.js index 6dc880434..b516ba7cd 100644 --- a/client/coral-framework/actions/config.js +++ b/client/coral-framework/actions/config.js @@ -4,7 +4,7 @@ import coralApi from '../helpers/response'; /** * Action name constants */ - +export const UPDATE_SETTINGS = 'UPDATE_SETTINGS'; export const OPEN_COMMENTS = 'OPEN_COMMENTS'; export const CLOSE_COMMENTS = 'CLOSE_COMMENTS'; export const ADD_ITEM = 'ADD_ITEM'; diff --git a/client/coral-framework/reducers/config.js b/client/coral-framework/reducers/config.js index 9620f5b97..0b7773d1c 100644 --- a/client/coral-framework/reducers/config.js +++ b/client/coral-framework/reducers/config.js @@ -12,7 +12,7 @@ export default (state = initialState, action) => { switch(action.type) { // Override config if worked case actions.UPDATE_SETTINGS: - return action.config; + return state.merge(action.config); case actions.OPEN_COMMENTS: return state.set('status', 'open'); diff --git a/client/coral-framework/reducers/items.js b/client/coral-framework/reducers/items.js index 17569c545..93388c1ab 100644 --- a/client/coral-framework/reducers/items.js +++ b/client/coral-framework/reducers/items.js @@ -6,7 +6,7 @@ import * as actions from '../actions/items'; const initialState = fromJS({ comments: {}, users: {}, - actions: {} + actions: {} }); export default (state = initialState, action) => { @@ -17,7 +17,6 @@ export default (state = initialState, action) => { return state.setIn([action.item_type, action.id, action.property], fromJS(action.value)); case actions.APPEND_ITEM_ARRAY: return state.updateIn([action.item_type, action.id, action.property], (prop) => { - console.log(prop); if (action.add_to_front) { return prop ? prop.unshift(fromJS(action.value)) : fromJS([action.value]); } else { diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index 115d1a577..8dd484604 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -58,13 +58,13 @@ export default class FlagButton extends Component { {val: 'I don\'t agree with this comment', text: lang.t('no-agree-comment')}, {val: 'This comment is offensive', text: lang.t('comment-offensive')}, {val: 'This comment reveals personally identifiable inforation without consent', text: lang.t('personal-info')}, - {val: 'Other', text: 'Other'}, + {val: 'Other', text: lang.t('other')}, ] : [ {val: 'This username is offensive', text: lang.t('username-offensive')}, {val: 'I don\'t like this username', text: lang.t('no-like-username')}, - {val: 'This looks like an ad/marketing', text: lang.t('marketing')}, - {val: 'Other', text: 'Other'}, + {val: 'This looks like an ad/marketing', text: lang.t('marketing ')}, + {val: 'Other', text: lang.t('other')}, ]; return { header: lang.t('step-2-header'), diff --git a/client/coral-plugin-flags/translations.json b/client/coral-plugin-flags/translations.json index 4cba5b40d..ac6c95523 100644 --- a/client/coral-plugin-flags/translations.json +++ b/client/coral-plugin-flags/translations.json @@ -12,17 +12,31 @@ "continue": "Continue", "no-agree-comment": "I don't agree with this comment", "comment-offensive": "This comment is offensive", - "personal-info": "This comment reveals personally identifiable inforation without consent", + "personal-info": "This comment reveals personally identifiable information", "username-offensive": "This username is offensive", "no-like-username": "I don't like this username", "marketing": "This looks like an ad/marketing", - "thank-you": "We value your safety and feedback. A moderator will review your flag." + "thank-you": "We value your safety and feedback. A moderator will review your flag.", + "other": "Other" }, "es": { "report": "Informe", "reported": "Informado", "report-notif": "Gracias por marcar este comentario. Nuestro equipo de moderación ha sido notificado y muy pronto lo va a revisar.", "report-notif-remove": "¡traduceme!", - "report-header": "¡traduceme!" + "step-1-header": "¡traduceme!", + "step-2-header": "¡traduceme!", + "step-3-header": "¡traduceme!", + "flag-username": "¡traduceme!", + "flag-comment": "¡traduceme!", + "continue": "¡traduceme!", + "no-agree-comment": "¡traduceme!", + "comment-offensive": "¡traduceme!", + "personal-info": "¡traduceme!", + "username-offensive": "¡traduceme!", + "no-like-username": "¡traduceme!", + "marketing": "¡traduceme!", + "thank-you": "¡traduceme!", + "other": "¡traduceme!" } } diff --git a/client/coral-ui/components/Button.css b/client/coral-ui/components/Button.css index 3a3a4221e..e8e41e3ab 100644 --- a/client/coral-ui/components/Button.css +++ b/client/coral-ui/components/Button.css @@ -21,7 +21,7 @@ cursor: pointer; text-decoration: none; text-align: center; - line-height: 36px; + line-height: 28px; vertical-align: middle; margin: 2px; } From dd85fbb3e09254f047c89a6ad21c74f2bae6c0b9 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 7 Dec 2016 22:16:41 -0500 Subject: [PATCH 13/29] Adding other field. --- .../coral-embed-stream/src/CommentStream.js | 2 +- client/coral-embed-stream/style/default.css | 5 ++ client/coral-framework/actions/items.js | 6 +-- client/coral-plugin-flags/FlagButton.js | 47 ++++++++++++++----- client/coral-plugin-flags/translations.json | 2 + 5 files changed, 47 insertions(+), 15 deletions(-) diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index 76a73171a..3262d32b6 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -274,7 +274,7 @@ const mapDispatchToProps = (dispatch) => ({ getStream: (rootId) => dispatch(getStream(rootId)), addNotification: (type, text) => dispatch(addNotification(type, text)), clearNotification: () => dispatch(clearNotification()), - postAction: (item, action, user, itemType, field, detail) => dispatch(postAction(item, action, user, itemType, field, detail)), + postAction: (item, action, itemType, field, detail) => dispatch(postAction(item, action, itemType, field, detail)), showSignInDialog: () => dispatch(showSignInDialog()), deleteAction: (item, action, user, itemType) => dispatch(deleteAction(item, action, user, itemType)), appendItemArray: (item, property, value, addToFront, itemType) => dispatch(appendItemArray(item, property, value, addToFront, itemType)), diff --git a/client/coral-embed-stream/style/default.css b/client/coral-embed-stream/style/default.css index 273e4e0b2..04c09aa16 100644 --- a/client/coral-embed-stream/style/default.css +++ b/client/coral-embed-stream/style/default.css @@ -237,6 +237,11 @@ hr { margin-top: 10px; } +.coral-plugin-flags-other-text { + margin-left: 20px; + width: 75%; +} + /* Close comments */ .close-comments-intro-wrapper { diff --git a/client/coral-framework/actions/items.js b/client/coral-framework/actions/items.js index 2a0c118a2..0ef3db8eb 100644 --- a/client/coral-framework/actions/items.js +++ b/client/coral-framework/actions/items.js @@ -217,12 +217,12 @@ export function postItem (item, type, id) { * */ -export function postAction (item_id, action_type, user_id, item_type, field, detail) { +export function postAction (item_id, action_type, item_type, field, detail) { return () => { const action = { action_type, - user_id, - field, detail + field, + detail }; return coralApi(`/${item_type}/${item_id}/actions`, {method: 'POST', body: action}); diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index 8dd484604..a392776cb 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -9,8 +9,10 @@ export default class FlagButton extends Component { state = { showMenu: false, + showOther: false, itemType: '', - reason: '', + detail: '', + otherText: '', step: 1 } @@ -23,14 +25,16 @@ export default class FlagButton extends Component { } onPopupContinue = () => { - const {postAction, addItem, updateItem, currentUser, flag, id, author_id} = this.props; - const {itemType, field, detail, step} = this.state; + const {postAction, addItem, updateItem, flag, id, author_id} = this.props; + const {itemType, field, detail, step, otherText} = this.state; this.setState({step: step + 1}); if (itemType && detail) { + console.log('OtherText', otherText); + const updatedDetail = otherText || detail; const item_id = itemType === 'comments' ? id : author_id; - postAction(item_id, 'flag', currentUser.id, itemType, field, detail) + postAction(item_id, 'flag', itemType, field, updatedDetail) .then((action) => { let id = `${action.action_type}_${action.item_id}`; addItem({id, current_user: action, count: flag ? flag.count + 1 : 1}, 'actions'); @@ -43,7 +47,7 @@ export default class FlagButton extends Component { switch(step) { case 1: { return { - header: lang.t('step-1-username'), + header: lang.t('step-1-header'), options: [ {val: 'user', text: lang.t('flag-username')}, {val: 'comments', text: lang.t('flag-comment')}, @@ -57,14 +61,14 @@ export default class FlagButton extends Component { [ {val: 'I don\'t agree with this comment', text: lang.t('no-agree-comment')}, {val: 'This comment is offensive', text: lang.t('comment-offensive')}, - {val: 'This comment reveals personally identifiable inforation without consent', text: lang.t('personal-info')}, - {val: 'Other', text: lang.t('other')}, + {val: 'This comment reveals personally identifiable infomration', text: lang.t('personal-info')}, + {val: 'other', text: lang.t('other')}, ] : [ {val: 'This username is offensive', text: lang.t('username-offensive')}, {val: 'I don\'t like this username', text: lang.t('no-like-username')}, - {val: 'This looks like an ad/marketing', text: lang.t('marketing ')}, - {val: 'Other', text: lang.t('other')}, + {val: 'This looks like an ad/marketing', text: lang.t('marketing')}, + {val: 'other', text: lang.t('other')}, ]; return { header: lang.t('step-2-header'), @@ -75,19 +79,27 @@ export default class FlagButton extends Component { } case 3: { return { - header: lang.t('step-3-input'), + header: lang.t('step-3-header'), text: lang.t('thank-you') }; }} } onPopupOptionClick = (sets) => (e) => { - this.setState({[sets]: e.target.value}); + if(sets === 'detail' && e.target.value === 'other') { + this.setState({showOther: true}); + } // If flagging a user, indicate that this is referencing the username rather than the bio if(sets === 'itemType' && e.target.value === 'user') { this.setState({field: 'username'}); } + + this.setState({[sets]: e.target.value}); + } + + onOtherTextChange = (e) => { + this.setState({otherText: e.target.value}); } render () { @@ -131,6 +143,19 @@ export default class FlagButton extends Component {
) } + { + this.state.showOther &&
+ +
+
+ } }
diff --git a/client/coral-plugin-flags/translations.json b/client/coral-plugin-flags/translations.json index ac6c95523..1b5bee21b 100644 --- a/client/coral-plugin-flags/translations.json +++ b/client/coral-plugin-flags/translations.json @@ -17,6 +17,7 @@ "no-like-username": "I don't like this username", "marketing": "This looks like an ad/marketing", "thank-you": "We value your safety and feedback. A moderator will review your flag.", + "flag-reason": "Reason for flag", "other": "Other" }, "es": { @@ -37,6 +38,7 @@ "no-like-username": "¡traduceme!", "marketing": "¡traduceme!", "thank-you": "¡traduceme!", + "flag-reason": "Reason for flag", "other": "¡traduceme!" } } From f8923aa283f530a41e0a6126508ba5f66a7c9ff8 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 7 Dec 2016 22:22:23 -0500 Subject: [PATCH 14/29] Updating tests. --- tests/client/coral-framework/store/itemActions.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client/coral-framework/store/itemActions.spec.js b/tests/client/coral-framework/store/itemActions.spec.js index ee5951dd6..8bf65fa33 100644 --- a/tests/client/coral-framework/store/itemActions.spec.js +++ b/tests/client/coral-framework/store/itemActions.spec.js @@ -155,7 +155,7 @@ describe('itemActions', () => { describe('postAction', () => { it ('should post an action', () => { fetchMock.post('*', {id: '456'}); - return actions.postAction('abc', 'flag', '123', 'comments', 'Comment smells funny')(store.dispatch) + return actions.postAction('abc', 'flag', 'comments', 'Comment smells funny')(store.dispatch) .then(response => { expect(fetchMock.calls().matched[0][0]).to.equal('/api/v1/comments/abc/actions'); expect(response).to.deep.equal({id:'456'}); From fc96c1ee91e5619ab402bc592fd6b35c7d3abe1f Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 8 Dec 2016 14:27:31 -0500 Subject: [PATCH 15/29] Compressing variables from postAction into single object. --- client/coral-embed-stream/src/CommentStream.js | 4 ++-- client/coral-framework/actions/items.js | 8 +------- client/coral-plugin-flags/FlagButton.js | 7 ++++++- client/coral-plugin-likes/LikeButton.js | 5 ++++- tests/client/coral-framework/store/itemActions.spec.js | 6 +++++- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index 3262d32b6..49bff199a 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -268,13 +268,13 @@ const mapStateToProps = state => ({ }); const mapDispatchToProps = (dispatch) => ({ - addItem: (item, itemType) => dispatch(addItem(item, itemType)), + addItem: (args) => dispatch(addItem.apply(args)), updateItem: (id, property, value, itemType) => dispatch(updateItem(id, property, value, itemType)), postItem: (data, type, id) => dispatch(postItem(data, type, id)), getStream: (rootId) => dispatch(getStream(rootId)), addNotification: (type, text) => dispatch(addNotification(type, text)), clearNotification: () => dispatch(clearNotification()), - postAction: (item, action, itemType, field, detail) => dispatch(postAction(item, action, itemType, field, detail)), + postAction: (item, itemType, action) => dispatch(postAction(item, itemType, action)), showSignInDialog: () => dispatch(showSignInDialog()), deleteAction: (item, action, user, itemType) => dispatch(deleteAction(item, action, user, itemType)), appendItemArray: (item, property, value, addToFront, itemType) => dispatch(appendItemArray(item, property, value, addToFront, itemType)), diff --git a/client/coral-framework/actions/items.js b/client/coral-framework/actions/items.js index 0ef3db8eb..e6fa55efa 100644 --- a/client/coral-framework/actions/items.js +++ b/client/coral-framework/actions/items.js @@ -217,14 +217,8 @@ export function postItem (item, type, id) { * */ -export function postAction (item_id, action_type, item_type, field, detail) { +export function postAction (item_id, item_type, action) { return () => { - const action = { - action_type, - field, - detail - }; - return coralApi(`/${item_type}/${item_id}/actions`, {method: 'POST', body: action}); }; } diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index a392776cb..36665e71e 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -34,7 +34,12 @@ export default class FlagButton extends Component { console.log('OtherText', otherText); const updatedDetail = otherText || detail; const item_id = itemType === 'comments' ? id : author_id; - postAction(item_id, 'flag', itemType, field, updatedDetail) + const action = { + action_type: 'flag', + field, + detail: updatedDetail + }; + postAction(item_id, itemType, action) .then((action) => { let id = `${action.action_type}_${action.item_id}`; addItem({id, current_user: action, count: flag ? flag.count + 1 : 1}, 'actions'); diff --git a/client/coral-plugin-likes/LikeButton.js b/client/coral-plugin-likes/LikeButton.js index b3d31fbf4..cfe302768 100644 --- a/client/coral-plugin-likes/LikeButton.js +++ b/client/coral-plugin-likes/LikeButton.js @@ -12,7 +12,10 @@ const LikeButton = ({like, id, postAction, deleteAction, addItem, showSignInDial return; } if (!liked) { - postAction(id, 'like', currentUser.id, 'comments') + const action = { + action_type: 'like' + }; + postAction(id, 'comments', action) .then((action) => { let id = `${action.action_type}_${action.item_id}`; addItem({id, current_user: action, count: like ? like.count + 1 : 1}, 'actions'); diff --git a/tests/client/coral-framework/store/itemActions.spec.js b/tests/client/coral-framework/store/itemActions.spec.js index 8bf65fa33..24b9c78d5 100644 --- a/tests/client/coral-framework/store/itemActions.spec.js +++ b/tests/client/coral-framework/store/itemActions.spec.js @@ -155,7 +155,11 @@ describe('itemActions', () => { describe('postAction', () => { it ('should post an action', () => { fetchMock.post('*', {id: '456'}); - return actions.postAction('abc', 'flag', 'comments', 'Comment smells funny')(store.dispatch) + const action = { + action_type: 'flag', + detail: 'Comment smells funny' + }; + return actions.postAction('abc', 'comments', action)(store.dispatch) .then(response => { expect(fetchMock.calls().matched[0][0]).to.equal('/api/v1/comments/abc/actions'); expect(response).to.deep.equal({id:'456'}); From 191681d7568f52919963fa66bff8b02db30d9059 Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 8 Dec 2016 14:31:09 -0500 Subject: [PATCH 16/29] Closing Report menu when a user clicks outside of it. --- client/coral-plugin-flags/FlagButton.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index 36665e71e..186594bee 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -2,10 +2,11 @@ import React, {Component} from 'react'; import {I18n} from '../coral-framework'; import translations from './translations.json'; import {PopupMenu, Button} from 'coral-ui'; +import onClickOutside from 'react-onclickoutside'; const name = 'coral-plugin-flags'; -export default class FlagButton extends Component { +class FlagButton extends Component { state = { showMenu: false, @@ -107,6 +108,10 @@ export default class FlagButton extends Component { this.setState({otherText: e.target.value}); } + handleClickOutside () { + this.setState({showMenu: false}); + } + render () { const {flag} = this.props; const flagged = flag && flag.current_user; @@ -180,6 +185,8 @@ export default class FlagButton extends Component { } } +export default onClickOutside(FlagButton); + const styles = { flaggedIcon: { color: '#F00' From 9d28577e9b3a0dd36076fbe35fe8f2b1e7b50b59 Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 8 Dec 2016 15:27:49 -0500 Subject: [PATCH 17/29] Removing extra commas and collapsing actions into an object in the backend. --- client/coral-plugin-flags/FlagButton.js | 2 +- models/action.js | 17 +++++------------ models/comment.js | 6 ++---- models/user.js | 6 ++---- routes/api/comments/index.js | 9 +-------- routes/api/user/index.js | 8 +------- tests/routes/api/comments/index.js | 2 +- 7 files changed, 13 insertions(+), 37 deletions(-) diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index 920b6b71e..9a19e6113 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -57,7 +57,7 @@ class FlagButton extends Component { header: lang.t('step-1-header'), options: [ {val: 'user', text: lang.t('flag-username')}, - {val: 'comments', text: lang.t('flag-comment')}, + {val: 'comments', text: lang.t('flag-comment')} ], button: lang.t('continue'), sets: 'itemType' diff --git a/models/action.js b/models/action.js index 13b1c5494..820d8e9ca 100644 --- a/models/action.js +++ b/models/action.js @@ -32,23 +32,16 @@ ActionSchema.statics.findById = function(id) { /** * Add an action. - * @param {String} item_id identifier of the comment (uuid) + * @param {String} item_id identifier of the item (uuid) * @param {String} user_id user id of the action (uuid) - * @param {String} action the new action to the comment + * @param {String} action the new action to the item * @return {Promise} */ -ActionSchema.statics.insertUserAction = ({item_id, item_type, user_id, action_type, field, detail}) => { - const action = { - item_id, - item_type, - user_id, - action_type, - field, - detail - }; +ActionSchema.statics.insertUserAction = ({item_id, item_type, user_id, action}) => { + let action_obj = Object.assign({}, action, {item_id, item_type, user_id}); // Create/Update the action. - return Action.findOneAndUpdate(action, action, { + return Action.findOneAndUpdate(action_obj, action_obj, { // Ensure that if it's new, we return the new object created. new: true, diff --git a/models/comment.js b/models/comment.js index 80bfd67ea..25616c65b 100644 --- a/models/comment.js +++ b/models/comment.js @@ -284,13 +284,11 @@ CommentSchema.statics.pushStatus = (id, status, assigned_by = null) => Comment.u * @param {String} action the new action to the comment * @return {Promise} */ -CommentSchema.statics.addAction = (item_id, user_id, action_type, field, detail) => Action.insertUserAction({ +CommentSchema.statics.addAction = (item_id, user_id, action) => Action.insertUserAction({ item_id, item_type: 'comment', user_id, - action_type, - field, - detail + action }); /** diff --git a/models/user.js b/models/user.js index 626b10e06..c34c87cff 100644 --- a/models/user.js +++ b/models/user.js @@ -555,11 +555,9 @@ UserService.addBio = (id, bio) => ( * @param {String} action the new action to the user * @return {Promise} */ -UserService.addAction = (item_id, user_id, action_type, field, detail) => Action.insertUserAction({ +UserService.addAction = (item_id, user_id, action) => Action.insertUserAction({ item_id, item_type: 'comment', user_id, - action_type, - field, - detail + action }); diff --git a/routes/api/comments/index.js b/routes/api/comments/index.js index 25984405e..c3aa3efc8 100644 --- a/routes/api/comments/index.js +++ b/routes/api/comments/index.js @@ -148,15 +148,8 @@ router.put('/:comment_id/status', authorization.needed('admin'), (req, res, next }); router.post('/:comment_id/actions', (req, res, next) => { - - const { - action_type, - field, - detail - } = req.body; - Comment - .addAction(req.params.comment_id, req.user.id, action_type, field, detail) + .addAction(req.params.comment_id, req.user.id, req.body) .then((action) => { res.status(201).json(action); }) diff --git a/routes/api/user/index.js b/routes/api/user/index.js index c5cf3d336..3c52be5ca 100644 --- a/routes/api/user/index.js +++ b/routes/api/user/index.js @@ -158,15 +158,9 @@ router.put('/:user_id/bio', (req, res, next) => { }); router.post('/:user_id/actions', authorization.needed(), (req, res, next) => { - console.log('Hit action endpoint'); - const { - action_type, - field, - detail - } = req.body; User - .addAction(req.params.comment_id, req.user.id, action_type, field, detail) + .addAction(req.params.comment_id, req.user.id, req.body) .then((action) => { res.status(201).json(action); }) diff --git a/tests/routes/api/comments/index.js b/tests/routes/api/comments/index.js index bf7a06ff6..06a5bc789 100644 --- a/tests/routes/api/comments/index.js +++ b/tests/routes/api/comments/index.js @@ -350,7 +350,7 @@ describe('/api/v1/comments/:comment_id/actions', () => { return chai.request(app) .post('/api/v1/comments/abc/actions') .set(passport.inject({id: '456', roles: ['admin']})) - .send({'user_id': '456', 'action_type': 'flag'}) + .send({'action_type': 'flag'}) .then((res) => { expect(res).to.have.status(201); expect(res).to.have.body; From 7f24153b4ecd1b12a8d5d1175250e8132caccd81 Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 8 Dec 2016 15:47:47 -0500 Subject: [PATCH 18/29] Revert "Removing extra commas and collapsing actions into an object in the backend." This reverts commit 9d28577e9b3a0dd36076fbe35fe8f2b1e7b50b59. --- client/coral-plugin-flags/FlagButton.js | 2 +- models/action.js | 17 ++++++++++++----- models/comment.js | 6 ++++-- models/user.js | 6 ++++-- routes/api/comments/index.js | 9 ++++++++- routes/api/user/index.js | 8 +++++++- tests/routes/api/comments/index.js | 2 +- 7 files changed, 37 insertions(+), 13 deletions(-) diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index 9a19e6113..920b6b71e 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -57,7 +57,7 @@ class FlagButton extends Component { header: lang.t('step-1-header'), options: [ {val: 'user', text: lang.t('flag-username')}, - {val: 'comments', text: lang.t('flag-comment')} + {val: 'comments', text: lang.t('flag-comment')}, ], button: lang.t('continue'), sets: 'itemType' diff --git a/models/action.js b/models/action.js index 820d8e9ca..13b1c5494 100644 --- a/models/action.js +++ b/models/action.js @@ -32,16 +32,23 @@ ActionSchema.statics.findById = function(id) { /** * Add an action. - * @param {String} item_id identifier of the item (uuid) + * @param {String} item_id identifier of the comment (uuid) * @param {String} user_id user id of the action (uuid) - * @param {String} action the new action to the item + * @param {String} action the new action to the comment * @return {Promise} */ -ActionSchema.statics.insertUserAction = ({item_id, item_type, user_id, action}) => { - let action_obj = Object.assign({}, action, {item_id, item_type, user_id}); +ActionSchema.statics.insertUserAction = ({item_id, item_type, user_id, action_type, field, detail}) => { + const action = { + item_id, + item_type, + user_id, + action_type, + field, + detail + }; // Create/Update the action. - return Action.findOneAndUpdate(action_obj, action_obj, { + return Action.findOneAndUpdate(action, action, { // Ensure that if it's new, we return the new object created. new: true, diff --git a/models/comment.js b/models/comment.js index 25616c65b..80bfd67ea 100644 --- a/models/comment.js +++ b/models/comment.js @@ -284,11 +284,13 @@ CommentSchema.statics.pushStatus = (id, status, assigned_by = null) => Comment.u * @param {String} action the new action to the comment * @return {Promise} */ -CommentSchema.statics.addAction = (item_id, user_id, action) => Action.insertUserAction({ +CommentSchema.statics.addAction = (item_id, user_id, action_type, field, detail) => Action.insertUserAction({ item_id, item_type: 'comment', user_id, - action + action_type, + field, + detail }); /** diff --git a/models/user.js b/models/user.js index c34c87cff..626b10e06 100644 --- a/models/user.js +++ b/models/user.js @@ -555,9 +555,11 @@ UserService.addBio = (id, bio) => ( * @param {String} action the new action to the user * @return {Promise} */ -UserService.addAction = (item_id, user_id, action) => Action.insertUserAction({ +UserService.addAction = (item_id, user_id, action_type, field, detail) => Action.insertUserAction({ item_id, item_type: 'comment', user_id, - action + action_type, + field, + detail }); diff --git a/routes/api/comments/index.js b/routes/api/comments/index.js index c3aa3efc8..25984405e 100644 --- a/routes/api/comments/index.js +++ b/routes/api/comments/index.js @@ -148,8 +148,15 @@ router.put('/:comment_id/status', authorization.needed('admin'), (req, res, next }); router.post('/:comment_id/actions', (req, res, next) => { + + const { + action_type, + field, + detail + } = req.body; + Comment - .addAction(req.params.comment_id, req.user.id, req.body) + .addAction(req.params.comment_id, req.user.id, action_type, field, detail) .then((action) => { res.status(201).json(action); }) diff --git a/routes/api/user/index.js b/routes/api/user/index.js index 3c52be5ca..c5cf3d336 100644 --- a/routes/api/user/index.js +++ b/routes/api/user/index.js @@ -158,9 +158,15 @@ router.put('/:user_id/bio', (req, res, next) => { }); router.post('/:user_id/actions', authorization.needed(), (req, res, next) => { + console.log('Hit action endpoint'); + const { + action_type, + field, + detail + } = req.body; User - .addAction(req.params.comment_id, req.user.id, req.body) + .addAction(req.params.comment_id, req.user.id, action_type, field, detail) .then((action) => { res.status(201).json(action); }) diff --git a/tests/routes/api/comments/index.js b/tests/routes/api/comments/index.js index 06a5bc789..bf7a06ff6 100644 --- a/tests/routes/api/comments/index.js +++ b/tests/routes/api/comments/index.js @@ -350,7 +350,7 @@ describe('/api/v1/comments/:comment_id/actions', () => { return chai.request(app) .post('/api/v1/comments/abc/actions') .set(passport.inject({id: '456', roles: ['admin']})) - .send({'action_type': 'flag'}) + .send({'user_id': '456', 'action_type': 'flag'}) .then((res) => { expect(res).to.have.status(201); expect(res).to.have.body; From e4a13d433f2dde37a90e001107a1476334d8a296 Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 8 Dec 2016 15:48:43 -0500 Subject: [PATCH 19/29] Removing commas. --- client/coral-plugin-flags/FlagButton.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index 920b6b71e..70e167e2b 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -57,7 +57,7 @@ class FlagButton extends Component { header: lang.t('step-1-header'), options: [ {val: 'user', text: lang.t('flag-username')}, - {val: 'comments', text: lang.t('flag-comment')}, + {val: 'comments', text: lang.t('flag-comment')} ], button: lang.t('continue'), sets: 'itemType' @@ -69,13 +69,13 @@ class FlagButton extends Component { {val: 'I don\'t agree with this comment', text: lang.t('no-agree-comment')}, {val: 'This comment is offensive', text: lang.t('comment-offensive')}, {val: 'This comment reveals personally identifiable infomration', text: lang.t('personal-info')}, - {val: 'other', text: lang.t('other')}, + {val: 'other', text: lang.t('other')} ] : [ {val: 'This username is offensive', text: lang.t('username-offensive')}, {val: 'I don\'t like this username', text: lang.t('no-like-username')}, {val: 'This looks like an ad/marketing', text: lang.t('marketing')}, - {val: 'other', text: lang.t('other')}, + {val: 'other', text: lang.t('other')} ]; return { header: lang.t('step-2-header'), From f0108e14348d0642e4487d4aa466e665605e515d Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 8 Dec 2016 16:55:42 -0500 Subject: [PATCH 20/29] Fixing bug in addItem in commentStream. --- client/coral-embed-stream/src/CommentStream.js | 2 +- client/coral-plugin-flags/FlagButton.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index 0b0a6eb3c..ff04c7b32 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -287,7 +287,7 @@ const mapStateToProps = state => ({ }); const mapDispatchToProps = (dispatch) => ({ - addItem: (args) => dispatch(addItem.apply(args)), + addItem: (item, item_id) => dispatch(addItem(item, item_id)), updateItem: (id, property, value, itemType) => dispatch(updateItem(id, property, value, itemType)), postItem: (data, type, id) => dispatch(postItem(data, type, id)), getStream: (rootId) => dispatch(getStream(rootId)), diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index 70e167e2b..e749ffa34 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -33,7 +33,6 @@ class FlagButton extends Component { this.setState({step: step + 1}); if (itemType && detail) { - console.log('OtherText', otherText); const updatedDetail = otherText || detail; const item_id = itemType === 'comments' ? id : author_id; const action = { From ee187469e02d28898e4fa74774b39a080ffdf708 Mon Sep 17 00:00:00 2001 From: David Jay Date: Fri, 9 Dec 2016 12:54:15 -0500 Subject: [PATCH 21/29] Moving FlagComment to seperate file. --- .../coral-embed-stream/src/CommentStream.js | 6 +- client/coral-plugin-flags/FlagBio.js | 0 client/coral-plugin-flags/FlagButton.js | 64 ++++++------------- client/coral-plugin-flags/FlagComment.js | 52 +++++++++++++++ 4 files changed, 74 insertions(+), 48 deletions(-) create mode 100644 client/coral-plugin-flags/FlagBio.js create mode 100644 client/coral-plugin-flags/FlagComment.js diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index ff04c7b32..a3d51c65e 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -17,7 +17,7 @@ import PubDate from '../../coral-plugin-pubdate/PubDate'; import Count from '../../coral-plugin-comment-count/CommentCount'; import AuthorName from '../../coral-plugin-author-name/AuthorName'; import {ReplyBox, ReplyButton} from '../../coral-plugin-replies'; -import FlagButton from '../../coral-plugin-flags/FlagButton'; +import FlagComment from '../../coral-plugin-flags/FlagComment'; import LikeButton from '../../coral-plugin-likes/LikeButton'; import PermalinkButton from '../../coral-plugin-permalinks/PermalinkButton'; import SignInContainer from '../../coral-sign-in/containers/SignInContainer'; @@ -161,7 +161,7 @@ class CommentStream extends Component { currentUser={this.props.auth.user}/>
-
- { if (!this.props.currentUser) { const offset = document.getElementById(`c_${this.props.id}`).getBoundingClientRect().top - 75; @@ -30,11 +31,23 @@ class FlagButton extends Component { const {postAction, addItem, updateItem, flag, id, author_id} = this.props; const {itemType, field, detail, step, otherText} = this.state; + //Proceed to the next step this.setState({step: step + 1}); + // If itemType and detail are both set, post the action if (itemType && detail) { + + // Set the text from the "other" field if it exists. const updatedDetail = otherText || detail; - const item_id = itemType === 'comments' ? id : author_id; + let item_id; + switch(itemType) { + case 'comments': + item_id = id; + break; + case 'user': + item_id = author_id; + break; + } const action = { action_type: 'flag', field, @@ -49,49 +62,10 @@ class FlagButton extends Component { } } - getPopupMenu = (step) => { - switch(step) { - case 1: { - return { - header: lang.t('step-1-header'), - options: [ - {val: 'user', text: lang.t('flag-username')}, - {val: 'comments', text: lang.t('flag-comment')} - ], - button: lang.t('continue'), - sets: 'itemType' - }; - } - case 2: { - const options = this.state.itemType === 'comments' ? - [ - {val: 'I don\'t agree with this comment', text: lang.t('no-agree-comment')}, - {val: 'This comment is offensive', text: lang.t('comment-offensive')}, - {val: 'This comment reveals personally identifiable infomration', text: lang.t('personal-info')}, - {val: 'other', text: lang.t('other')} - ] - : [ - {val: 'This username is offensive', text: lang.t('username-offensive')}, - {val: 'I don\'t like this username', text: lang.t('no-like-username')}, - {val: 'This looks like an ad/marketing', text: lang.t('marketing')}, - {val: 'other', text: lang.t('other')} - ]; - return { - header: lang.t('step-2-header'), - options, - button: lang.t('continue'), - sets: 'detail' - }; - } - case 3: { - return { - header: lang.t('step-3-header'), - text: lang.t('thank-you') - }; - }} - } - + // When a popup option is clicked, update the state onPopupOptionClick = (sets) => (e) => { + + // If the "other" option is clicked, show the other textbox if(sets === 'detail' && e.target.value === 'other') { this.setState({showOther: true}); } @@ -113,9 +87,9 @@ class FlagButton extends Component { } render () { - const {flag} = this.props; + const {flag, getPopupMenu} = this.props; const flagged = flag && flag.current_user; - const popupMenu = this.getPopupMenu(this.state.step); + const popupMenu = getPopupMenu(this.state.step, this.state.itemType); return