import get from 'lodash/get'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { compose, gql, graphql } from 'react-apollo'; import LikeButton from '../components/LikeButton'; import withFragments from 'coral-framework/hocs/withFragments'; import { showSignInDialog } from 'coral-framework/actions/auth'; const isLikeAction = a => a.__typename === 'LikeActionSummary'; const COMMENT_FRAGMENT = gql` fragment LikeButton_updateFragment on Comment { action_summaries { ... on LikeActionSummary { count current_user { id } } } } `; const withDeleteAction = graphql( gql` mutation deleteAction($id: ID!) { deleteAction(id:$id) { errors { translation_key } } } `, { props: ({ mutate }) => ({ deleteAction: (id, commentId) => { return mutate({ variables: { id }, optimisticResponse: { deleteAction: { __typename: 'DeleteActionResponse', errors: null } }, update: proxy => { const fragmentId = `Comment_${commentId}`; // Read the data from our cache for this query. const data = proxy.readFragment({ fragment: COMMENT_FRAGMENT, id: fragmentId }); // Check whether we liked this comment. const idx = data.action_summaries.findIndex(isLikeAction); if ( idx < 0 || get(data.action_summaries[idx], 'current_user.id') !== id ) { return; } data.action_summaries[idx] = { ...data.action_summaries[idx], count: data.action_summaries[idx].count - 1, current_user: null }; // Write our data back to the cache. proxy.writeFragment({ fragment: COMMENT_FRAGMENT, id: fragmentId, data }); } }); } }) } ); const withPostLike = graphql( gql` mutation createLike($like: CreateLikeInput!) { createLike(like: $like) { like { id } errors { translation_key } } } `, { props: ({ mutate }) => ({ postLike: like => { return mutate({ variables: { like }, optimisticResponse: { createLike: { __typename: 'CreateLikeResponse', errors: null, like: { __typename: 'LikeAction', id: 'pending' } } }, update: (proxy, mutationResult) => { const fragmentId = `Comment_${like.item_id}`; // Read the data from our cache for this query. const data = proxy.readFragment({ fragment: COMMENT_FRAGMENT, id: fragmentId }); // Add our comment from the mutation to the end. let idx = data.action_summaries.findIndex(isLikeAction); // Check whether we already liked this comment. if (idx >= 0 && data.action_summaries[idx].current_user) { return; } if (idx < 0) { // Add initial action when it doesn't exist. data.action_summaries.push({ __typename: 'LikeActionSummary', count: 0, current_user: null }); idx = data.action_summaries.length - 1; } data.action_summaries[idx] = { ...data.action_summaries[idx], count: data.action_summaries[idx].count + 1, current_user: mutationResult.data.createLike.like }; // Write our data back to the cache. proxy.writeFragment({ fragment: COMMENT_FRAGMENT, id: fragmentId, data }); } }); } }) } ); const mapDispatchToProps = dispatch => bindActionCreators({ showSignInDialog }, dispatch); const enhance = compose( withFragments({ root: gql` fragment LikeButton_root on RootQuery { me { status } } `, comment: gql` fragment LikeButton_comment on Comment { action_summaries { ... on LikeActionSummary { count current_user { id } } } }` }), connect(null, mapDispatchToProps), withDeleteAction, withPostLike ); export default enhance(LikeButton);