diff --git a/client/coral-embed-stream/src/components/Comment.js b/client/coral-embed-stream/src/components/Comment.js index 2e854633b..649adb941 100644 --- a/client/coral-embed-stream/src/components/Comment.js +++ b/client/coral-embed-stream/src/components/Comment.js @@ -496,6 +496,7 @@ export default class Comment extends React.Component { fill="commentReactions" data={this.props.data} root={this.props.root} + asset={asset} comment={comment} commentId={comment.id} inline diff --git a/plugins/talk-plugin-featured-comments/client/components/FeaturedButton.js b/plugins/talk-plugin-featured-comments/client/components/FeaturedButton.js new file mode 100644 index 000000000..31f7ee32c --- /dev/null +++ b/plugins/talk-plugin-featured-comments/client/components/FeaturedButton.js @@ -0,0 +1,16 @@ +import React from 'react'; +import withTags from './withTags'; + +class FeaturedButton extends React.Component { + render() { + const {alreadyTagged, deleteTag, postTag} = this.props; + return ( + + ); + } +} + +export default withTags('featured')(FeaturedButton); + \ No newline at end of file diff --git a/plugins/talk-plugin-featured-comments/client/components/FeaturedTag.js b/plugins/talk-plugin-featured-comments/client/components/FeaturedTag.js new file mode 100644 index 000000000..23f62a6d8 --- /dev/null +++ b/plugins/talk-plugin-featured-comments/client/components/FeaturedTag.js @@ -0,0 +1,17 @@ +import React from 'react'; +import styles from './styles.css'; +import {t} from 'plugin-api/beta/client/services'; + +const isFeatured = (tags) => !!tags.filter((t) => t.tag.name === 'FEATURED').length; + +export default (props) => ( + + { + isFeatured(props.comment.tags) && props.depth === 0 ? ( + + Featured + + ) : null + } + +); diff --git a/plugins/talk-plugin-featured-comments/client/components/styles.css b/plugins/talk-plugin-featured-comments/client/components/styles.css new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/talk-plugin-featured-comments/client/components/withTags.js b/plugins/talk-plugin-featured-comments/client/components/withTags.js new file mode 100644 index 000000000..4e7401577 --- /dev/null +++ b/plugins/talk-plugin-featured-comments/client/components/withTags.js @@ -0,0 +1,186 @@ +import React from 'react'; +import {connect} from 'react-redux'; +import {bindActionCreators} from 'redux'; +import {compose, gql} from 'react-apollo'; +import {getDisplayName} from 'coral-framework/helpers/hoc'; +import {capitalize} from 'coral-framework/helpers/strings'; +import withMutation from 'coral-framework/hocs/withMutation'; +import withFragments from 'coral-framework/hocs/withFragments'; +import {showSignInDialog} from 'coral-framework/actions/auth'; +import {addNotification} from 'coral-framework/actions/notification'; + +export default (tag) => (WrappedComponent) => { + if (typeof tag !== 'string') { + console.error('Tag must be a valid string'); + return null; + } + + tag = tag.toLowerCase(); + const Tag = capitalize(tag); + + const COMMENT_FRAGMENT = gql` + fragment Coral_UpdateFragment on Comment { + tags { + tag { + name + } + } + } + `; + + const withAddTag = withMutation( + gql` + mutation AddTag($id: ID!, $asset_id: ID!, $name: String!) { + addTag(tag: {name: $name, id: $id, item_type: COMMENTS, asset_id: $asset_id}) { + ...ModifyTagResponse + } + } + `, { + props: ({mutate}) => ({ + addTag: ({id, name, assetId}) => { + return mutate({ + variables: { + id, + name, + asset_id: assetId + }, + optimisticResponse: { + addTag: { + __typename: 'ModifyTagResponse', + errors: null, + } + }, + update: (proxy) => { + const fragmentId = `Comment_${id}`; + + // Read the data from our cache for this query. + const data = proxy.readFragment({fragment: COMMENT_FRAGMENT, id: fragmentId}); + + data.tags.push({ + tag: { + __typename: 'Tag', + name: Tag.toUpperCase() + }, + __typename: 'TagLink' + }); + + // Write our data back to the cache. + proxy.writeFragment({fragment: COMMENT_FRAGMENT, id: fragmentId, data}); + }, + }); + }}), + }); + + const withRemoveTag = withMutation( + gql` + mutation RemoveTag($id: ID!, $asset_id: ID!, $name: String!) { + removeTag(tag: {name: $name, id: $id, item_type: COMMENTS, asset_id: $asset_id}) { + ...ModifyTagResponse + } + } + `, { + props: ({mutate}) => ({ + removeTag: ({id, name, assetId}) => { + return mutate({ + variables: { + id, + name, + asset_id: assetId + }, + optimisticResponse: { + removeTag: { + __typename: 'ModifyTagResponse', + errors: null, + } + }, + update: (proxy) => { + const fragmentId = `Comment_${id}`; + + // Read the data from our cache for this query. + const data = proxy.readFragment({fragment: COMMENT_FRAGMENT, id: fragmentId}); + + const idx = data.tags.findIndex((i) => i.tag.name === Tag.toUpperCase()); + + data.tags = [...data.tags.slice(0, idx), ...data.tags.slice(idx + 1)]; + + // Write our data back to the cache. + proxy.writeFragment({fragment: COMMENT_FRAGMENT, id: fragmentId, data}); + } + }); + }}), + }); + + class WithTags extends React.Component { + + postTag = () => { + console.log(this.props); + + const {comment, asset} = this.props; + + this.props.addTag({ + id: comment.id, + name: Tag.toUpperCase(), + assetId: asset.id + }); + + console.log('Post Tag'); + } + + deleteTag = () => { + const {comment, asset} = this.props; + + this.props.removeTag({ + id: comment.id, + name: Tag.toUpperCase(), + assetId: asset.id + }); + + console.log('delete Tag'); + } + + + + render() { + const {comment} = this.props; + + const isTagged = (tags) => !!tags.filter((t) => t.tag.name === Tag.toUpperCase()).length; + + const alreadyTagged = isTagged(comment.tags); + + return ; + } + } + + const mapStateToProps = (state) => ({ + user: state.auth.toJS().user, + }); + + const mapDispatchToProps = (dispatch) => + bindActionCreators({showSignInDialog, addNotification}, dispatch); + + const enhance = compose( + withFragments({ + comment: gql` + fragment ${Tag}Button_comment on Comment { + tags { + tag { + name + } + } + }` + }), + connect(mapStateToProps, mapDispatchToProps), + withAddTag, + withRemoveTag + ); + + WithTags.displayName = `WithTags(${getDisplayName(WrappedComponent)})`; + + return enhance(WithTags); +}; diff --git a/plugins/talk-plugin-featured-comments/client/index.js b/plugins/talk-plugin-featured-comments/client/index.js new file mode 100644 index 000000000..613d70d13 --- /dev/null +++ b/plugins/talk-plugin-featured-comments/client/index.js @@ -0,0 +1,11 @@ +import translations from './translations.json'; +import FeaturedTag from './components/FeaturedTag'; +import FeaturedButton from './components/FeaturedButton'; + +export default { + translations, + slots: { + commentInfoBar: [FeaturedTag], + commentReactions: [FeaturedButton] + } +}; diff --git a/plugins/talk-plugin-featured-comments/client/translations.json b/plugins/talk-plugin-featured-comments/client/translations.json new file mode 100644 index 000000000..077404aaa --- /dev/null +++ b/plugins/talk-plugin-featured-comments/client/translations.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file