diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index e3832a0dc..9270b7a01 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -16,7 +16,7 @@ import Pym from 'pym.js'; import FlagButton from '../../coral-plugin-flags/FlagButton'; import LikeButton from '../../coral-plugin-likes/LikeButton'; -const {addItem, updateItem, postItem, getStream, postAction, appendItemArray} = itemActions; +const {addItem, updateItem, postItem, getStream, postAction, deleteAction, appendItemArray} = itemActions; const {addNotification, clearNotification} = notificationActions; const {setLoggedInUser} = authActions; @@ -55,6 +55,9 @@ const mapDispatchToProps = (dispatch) => { postAction: (item, action, user, itemType) => { return dispatch(postAction(item, action, user, itemType)); }, + deleteAction: (item, action, user, itemType) => { + return dispatch(deleteAction(item, action, user, itemType)); + }, appendItemArray: (item, property, value, addToFront, itemType) => { return dispatch(appendItemArray(item, property, value, addToFront, itemType)); } @@ -129,6 +132,7 @@ class CommentStream extends Component { id={commentId} like={this.props.items.actions[comment.like]} postAction={this.props.postAction} + deleteAction={this.props.deleteAction} addItem={this.props.addItem} updateItem={this.props.updateItem} currentUser={this.props.auth.user}/> @@ -139,6 +143,7 @@ class CommentStream extends Component { id={commentId} flag={this.props.items.actions[comment.flag]} postAction={this.props.postAction} + deleteAction={this.props.deleteAction} addItem={this.props.addItem} updateItem={this.props.updateItem} currentUser={this.props.auth.user}/> @@ -170,6 +175,7 @@ class CommentStream extends Component { id={replyId} like={this.props.items.actions[reply.like]} postAction={this.props.postAction} + deleteAction={this.props.deleteAction} addItem={this.props.addItem} updateItem={this.props.updateItem} currentUser={this.props.auth.user}/> @@ -180,6 +186,7 @@ class CommentStream extends Component { id={replyId} flag={this.props.items.actions[reply.flag]} postAction={this.props.postAction} + deleteAction={this.props.deleteAction} addItem={this.props.addItem} updateItem={this.props.updateItem} currentUser={this.props.auth.user}/> diff --git a/client/coral-framework/store/actions/items.js b/client/coral-framework/store/actions/items.js index 07f8e54af..648a1d95e 100644 --- a/client/coral-framework/store/actions/items.js +++ b/client/coral-framework/store/actions/items.js @@ -241,9 +241,45 @@ export function postAction (item_id, action_type, user_id, item_type) { return response.ok ? response.json() : Promise.reject(`${response.status} ${response.statusText}`); } - ) - .then((json)=>{ - return json; - }); + ); + }; +} + +/* +* DeleteAction +* Deletes an action to an item +* +* @params +* id - the id of the item on which the action is taking place +* action - the name of the action +* user - the user performing the action +* host - the coral host +* +* @returns +* A promise resolving to null or an error +* +*/ + +export function deleteAction (item_id, action_type, user_id, item_type) { + return () => { + const action = { + action_type, + user_id + }; + const options = { + method: 'DELETE', + headers: { + 'Content-Type':'application/json' + }, + body: JSON.stringify(action) + }; + + return fetch(`/api/v1/${item_type}/${item_id}/actions`, options) + .then( + response => { + return response.ok ? response.text() + : Promise.reject(`${response.status} ${response.statusText}`); + } + ); }; } diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index 7374def5f..a4869c486 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -4,7 +4,7 @@ import translations from './translations.json'; const name = 'coral-plugin-flags'; -const FlagButton = ({flag, id, postAction, addItem, updateItem, addNotification}) => { +const FlagButton = ({flag, id, postAction, deleteAction, addItem, updateItem, addNotification}) => { const flagged = flag && flag.current_user; const onFlagClick = () => { if (!flagged) { @@ -14,17 +14,23 @@ const FlagButton = ({flag, id, postAction, addItem, updateItem, addNotification} updateItem(action.item_id, action.action_type, action.id, 'comments'); }); addNotification('success', lang.t('flag-notif')); + } else { + deleteAction(id, 'flag', '123', 'comments') + .then(() => { + updateItem(id, 'flag', '', 'comments'); + }); + addNotification('success', lang.t('flag-notif-remove')); } }; - return
- diff --git a/client/coral-plugin-flags/translations.json b/client/coral-plugin-flags/translations.json index 28eb9f8cb..fb2daa883 100644 --- a/client/coral-plugin-flags/translations.json +++ b/client/coral-plugin-flags/translations.json @@ -2,11 +2,13 @@ "en": { "flag": "Flag", "flagged": "Flagged", - "flag-notif": "Thank you for reporting this comment. Our moderation team has been notified and will review it shortly." + "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-notif": "Gracias por marcar este comentario. Nuestro equipo de moderación ha sido notificado y muy pronto lo va a revisar." + "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-plugin-likes/LikeButton.js b/client/coral-plugin-likes/LikeButton.js index ec8528793..9bdf7b84d 100644 --- a/client/coral-plugin-likes/LikeButton.js +++ b/client/coral-plugin-likes/LikeButton.js @@ -4,7 +4,7 @@ import translations from './translations.json'; const name = 'coral-plugin-flags'; -const LikeButton = ({like, id, postAction, addItem, updateItem}) => { +const LikeButton = ({like, id, postAction, deleteAction, addItem, updateItem}) => { const liked = like && like.current_user; const onLikeClick = () => { if (!liked) { @@ -13,6 +13,12 @@ const LikeButton = ({like, id, postAction, addItem, updateItem}) => { addItem({id: action.id, current_user:true, count: like ? like.count + 1 : 1}, 'actions'); updateItem(action.item_id, action.action_type, action.id, 'comments'); }); + } else { + deleteAction(id, 'like', '123', 'comments') + .then(() => { + updateItem(like.id, 'count', like.count - 1, 'actions'); + updateItem(like.id, 'current_user', false, 'actions'); + }); } }; @@ -25,7 +31,7 @@ const LikeButton = ({like, id, postAction, addItem, updateItem}) => { } thumb_up - {like && like.count} + {like && like.count > 0 && like.count}
; }; diff --git a/tests/client/coral-framework/store/itemActions.spec.js b/tests/client/coral-framework/store/itemActions.spec.js index d45212794..33fe15cab 100644 --- a/tests/client/coral-framework/store/itemActions.spec.js +++ b/tests/client/coral-framework/store/itemActions.spec.js @@ -162,6 +162,24 @@ describe('itemActions', () => { expect(err).to.be.truthy; }); }); + }); + describe('deleteAction', () => { + it ('should remove an action', () => { + fetchMock.delete('*', 'Action removed.'); + return actions.deleteAction('abc', 'flag', '123', 'comments')(store.dispatch) + .then(response => { + expect(fetchMock.calls().matched[0][0]).to.equal('/api/v1/comments/abc/actions'); + expect(response).to.equal('Action removed.'); + }); + }); + + it('should handle an error', () => { + fetchMock.post('*', 404); + return actions.postAction('abc', 'flag', '123')(store.dispatch) + .catch((err) => { + expect(err).to.be.truthy; + }); + }); }); });