diff --git a/client/coral-embed-stream/src/Comment.js b/client/coral-embed-stream/src/Comment.js index c5158e31a..6e3744aab 100644 --- a/client/coral-embed-stream/src/Comment.js +++ b/client/coral-embed-stream/src/Comment.js @@ -12,10 +12,14 @@ import PermalinkButton from 'coral-plugin-permalinks/PermalinkButton'; import Content from '../../coral-plugin-commentcontent/CommentContent'; import PubDate from '../../coral-plugin-pubdate/PubDate'; // import {ReplyBox, ReplyButton} from '../../coral-plugin-replies'; -// import FlagComment from '../../coral-plugin-flags/FlagComment'; -// import LikeButton from '../../coral-plugin-likes/LikeButton'; +import FlagComment from '../../coral-plugin-flags/FlagComment'; +import LikeButton from '../../coral-plugin-likes/LikeButton'; -const Comment = ({comment, currentUser, asset, depth}) => { +const getAction = (type, comment) => comment.actions.filter((a) => a.type === type)[0]; + +const Comment = ({comment, currentUser, asset, depth, showSignInDialog, postAction, deleteAction}) => { + const like = getAction('LIKE', comment); + const flag = getAction('FLAG', comment); return (
{
- + {/* + + */} +
- +
{ @@ -49,6 +71,10 @@ const Comment = ({comment, currentUser, asset, depth}) => { depth={depth + 1} asset={asset} currentUser={currentUser} + currentUser={currentUser} + postAction={postAction} + deleteAction={deleteAction} + showSignInDialog={showSignInDialog} key={reply.id} comment={reply} />; }) diff --git a/client/coral-embed-stream/src/Embed.js b/client/coral-embed-stream/src/Embed.js index 5a44f8532..cd55c13cd 100644 --- a/client/coral-embed-stream/src/Embed.js +++ b/client/coral-embed-stream/src/Embed.js @@ -3,7 +3,7 @@ import React, {Component, PropTypes} from 'react'; import {compose} from 'react-apollo'; import {connect} from 'react-redux'; -import {postComment} from './graphql/mutations'; +import {postComment, postAction, deleteAction} from './graphql/mutations'; import {queryStream} from './graphql/queries'; import { @@ -149,6 +149,9 @@ class Embed extends Component { ({ export default compose( connect(mapStateToProps, mapDispatchToProps), postComment, + postAction, + deleteAction, queryStream )(Embed); diff --git a/client/coral-embed-stream/src/Stream.js b/client/coral-embed-stream/src/Stream.js index 78a988553..74a1c7b65 100644 --- a/client/coral-embed-stream/src/Stream.js +++ b/client/coral-embed-stream/src/Stream.js @@ -1,8 +1,7 @@ import React, {PropTypes} from 'react'; import Comment from './Comment'; -const Stream = ({comments, currentUser, asset}) => { - console.log('currentUser', currentUser); +const Stream = ({comments, currentUser, asset, postAction, deleteAction, showSignInDialog}) => { return (
{ @@ -11,6 +10,9 @@ const Stream = ({comments, currentUser, asset}) => { depth={0} asset={asset} currentUser={currentUser} + postAction={postAction} + deleteAction={deleteAction} + showSignInDialog={showSignInDialog} key={comment.id} comment={comment} />; }) diff --git a/client/coral-embed-stream/src/graphql/mutations/deleteAction.graphql b/client/coral-embed-stream/src/graphql/mutations/deleteAction.graphql new file mode 100644 index 000000000..bfce8cf6a --- /dev/null +++ b/client/coral-embed-stream/src/graphql/mutations/deleteAction.graphql @@ -0,0 +1,3 @@ +mutation deleteAction ($id: ID!) { + deleteAction(id:$id) +} diff --git a/client/coral-embed-stream/src/graphql/mutations/index.js b/client/coral-embed-stream/src/graphql/mutations/index.js index 419891c06..d3c0a6080 100644 --- a/client/coral-embed-stream/src/graphql/mutations/index.js +++ b/client/coral-embed-stream/src/graphql/mutations/index.js @@ -1,5 +1,7 @@ import {graphql} from 'react-apollo'; import POST_COMMENT from './postComment.graphql'; +import POST_ACTION from './postAction.graphql'; +import DELETE_ACTION from './deleteAction.graphql'; export const postComment = graphql(POST_COMMENT, { props: ({mutate}) => ({ @@ -13,3 +15,25 @@ export const postComment = graphql(POST_COMMENT, { }); }}), }); + +export const postAction = graphql(POST_ACTION, { + props: ({mutate}) => ({ + postAction: (action) => { + return mutate({ + variables: { + action + } + }); + }}), +}); + +export const deleteAction = graphql(DELETE_ACTION, { + props: ({mutate}) => ({ + deleteAction: (id) => { + return mutate({ + variables: { + id + } + }); + }}), +}); diff --git a/client/coral-embed-stream/src/graphql/mutations/postAction.graphql b/client/coral-embed-stream/src/graphql/mutations/postAction.graphql index 52a0e1735..fff737fa8 100644 --- a/client/coral-embed-stream/src/graphql/mutations/postAction.graphql +++ b/client/coral-embed-stream/src/graphql/mutations/postAction.graphql @@ -1,5 +1,5 @@ -mutation CreateAction ($action: ActionInput) { +mutation CreateAction ($action: CreateActionInput!) { createAction(action:$action) { - ...action + id } } diff --git a/client/coral-embed-stream/src/graphql/queries/index.js b/client/coral-embed-stream/src/graphql/queries/index.js index 47f585449..ecf875aaa 100644 --- a/client/coral-embed-stream/src/graphql/queries/index.js +++ b/client/coral-embed-stream/src/graphql/queries/index.js @@ -3,7 +3,7 @@ import STREAM_QUERY from './streamQuery.graphql'; import Pym from 'pym.js'; const pym = new Pym.Child({polling: 100}); -let url = pym.parentUrl; +let url = pym.parentUrl || 'http://localhost:3000/'; export const queryStream = graphql(STREAM_QUERY, { options: {variables: {asset_url: url}} diff --git a/client/coral-plugin-flags/FlagBio.js b/client/coral-plugin-flags/FlagBio.js index edc0a5286..2639ab8cf 100644 --- a/client/coral-plugin-flags/FlagBio.js +++ b/client/coral-plugin-flags/FlagBio.js @@ -9,7 +9,7 @@ const getPopupMenu = [ () => { return { header: lang.t('step-2-header'), - itemType: 'user', + itemType: 'USERS', field: 'bio', options: [ {val: 'This bio is offensive', text: lang.t('bio-offensive')}, diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js index 8fc747ce1..b0d1cea4d 100644 --- a/client/coral-plugin-flags/FlagButton.js +++ b/client/coral-plugin-flags/FlagButton.js @@ -14,22 +14,31 @@ class FlagButton extends Component { reason: '', note: '', step: 0, - posted: false + localPost: null, + localDelete: false } // When the "report" button is clicked expand the menu onReportClick = () => { - if (!this.props.currentUser) { + const {currentUser, flag, deleteAction} = this.props; + const {localPost, localDelete} = this.state; + const flagged = (flag && flag.current && !localDelete) || localPost; + if (!currentUser) { const offset = document.getElementById(`c_${this.props.id}`).getBoundingClientRect().top - 75; this.props.showSignInDialog(offset); return; } - this.setState({showMenu: !this.state.showMenu}); + if (flagged) { + this.setState((prev) => prev.localPost ? {...prev, localPost: null, step: 0} : {...prev, localDelete: true}); + deleteAction(localPost || flag.current.id); + } else { + this.setState({showMenu: !this.state.showMenu}); + } } onPopupContinue = () => { - const {postAction, addItem, updateItem, flag, id, author_id} = this.props; - const {itemType, field, reason, step, note, posted} = this.state; + const {postAction, id, author_id} = this.props; + const {itemType, reason, step, localPost} = this.state; // Proceed to the next step or close the menu if we've reached the end if (step + 1 >= this.props.getPopupMenu.length) { @@ -39,33 +48,32 @@ class FlagButton extends Component { } // If itemType and reason are both set, post the action - if (itemType && reason && !posted) { + if (itemType && reason && !localPost) { // Set the text from the "other" field if it exists. let item_id; switch(itemType) { - case 'comments': + case 'COMMENTS': item_id = id; break; - case 'users': + case 'USERS': item_id = author_id; break; } - const action = { - action_type: 'flag', - metadata: { - field, - reason, - note + + // Note: Action metadata has been temporarily removed. + if (itemType === 'COMMENTS') { + this.setState({localPost: 'temp'}); + } + postAction({ + item_id, + item_type: itemType, + action_type: 'FLAG' + }).then(({data}) => { + if (itemType === 'COMMENTS') { + this.setState({localPost: data.createAction.id}); } - }; - 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'); - updateItem(action.item_id, action.action_type, id, action.item_type); - this.setState({posted: true}); - }); + }); } } @@ -98,7 +106,8 @@ class FlagButton extends Component { render () { const {flag, getPopupMenu} = this.props; - const flagged = flag && flag.current_user; + const {localPost, localDelete} = this.state; + const flagged = (flag && flag.current && !localDelete) || localPost; const popupMenu = getPopupMenu[this.state.step](this.state.itemType); return
diff --git a/client/coral-plugin-flags/FlagComment.js b/client/coral-plugin-flags/FlagComment.js index 54dc954d9..5ea2e9fa1 100644 --- a/client/coral-plugin-flags/FlagComment.js +++ b/client/coral-plugin-flags/FlagComment.js @@ -10,15 +10,15 @@ const getPopupMenu = [ return { header: lang.t('step-1-header'), options: [ - {val: 'users', text: lang.t('flag-username')}, - {val: 'comments', text: lang.t('flag-comment')} + {val: 'USERS', text: lang.t('flag-username')}, + {val: 'COMMENTS', text: lang.t('flag-comment')} ], button: lang.t('continue'), sets: 'itemType' }; }, (itemType) => { - const options = itemType === 'comments' ? + const options = 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')}, diff --git a/client/coral-plugin-likes/LikeButton.js b/client/coral-plugin-likes/LikeButton.js index fae30c8c7..cc2c6d83e 100644 --- a/client/coral-plugin-likes/LikeButton.js +++ b/client/coral-plugin-likes/LikeButton.js @@ -1,52 +1,76 @@ -import React from 'react'; +import React, {Component, PropTypes} from 'react'; import {I18n} from '../coral-framework'; import translations from './translations.json'; const name = 'coral-plugin-likes'; -const LikeButton = ({like, id, postAction, deleteAction, addItem, showSignInDialog, updateItem, currentUser, banned}) => { - const liked = like && like.current_user; - const onLikeClick = () => { - if (!currentUser) { - const offset = document.getElementById(`c_${id}`).getBoundingClientRect().top - 75; - showSignInDialog(offset); - return; - } - if (banned) { - return; - } - if (!liked) { - 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'); - updateItem(action.item_id, action.action_type, id, 'comments'); - }); - } else { - deleteAction(liked.id) - .then(() => { - updateItem(like.id, 'count', like.count - 1, 'actions'); - updateItem(like.id, 'current_user', false, 'actions'); - }); - } - }; +class LikeButton extends Component { - return
- -
; -}; + if (currentUser.banned) { + return; + } + if (!liked) { + this.setState({localPost: 'temp', localDelete: false}); + postAction({ + item_id: id, + item_type: 'COMMENTS', + action_type: 'LIKE' + }).then(({data}) => { + this.setState({localPost: data.createAction.id}); + }); + } else { + this.setState((prev) => prev.localPost ? {...prev, localPost: null} : {...prev, localDelete: true}); + deleteAction(localPost || like.current.id); + } + }; + + return
+ +
; + } +} export default LikeButton;