diff --git a/client/coral-embed-stream/src/Comment.js b/client/coral-embed-stream/src/Comment.js
index 0c7591ddf..e4ca10743 100644
--- a/client/coral-embed-stream/src/Comment.js
+++ b/client/coral-embed-stream/src/Comment.js
@@ -17,7 +17,7 @@ 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 BestButton, {IfUserCanModifyBest} from 'coral-plugin-best/BestButton';
+import {BestButton, IfUserCanModifyBest, BEST_TAG, commentIsBest} from 'coral-plugin-best/BestButton';
import LoadMore from 'coral-embed-stream/src/LoadMore';
import styles from './Comment.css';
@@ -74,7 +74,13 @@ class Comment extends React.Component {
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired
}).isRequired
- }).isRequired
+ }).isRequired,
+
+ // dispatch action to add a tag to a comment
+ addCommentTag: React.PropTypes.func,
+
+ // dispatch action to remove a tag from a comment
+ removeCommentTag: React.PropTypes.func,
}
render () {
@@ -93,13 +99,27 @@ class Comment extends React.Component {
loadMore,
setActiveReplyBox,
activeReplyBox,
- deleteAction
+ deleteAction,
+ addCommentTag,
+ removeCommentTag,
} = this.props;
const like = getActionSummary('LikeActionSummary', comment);
const flag = getActionSummary('FlagActionSummary', comment);
const dontagree = getActionSummary('DontAgreeActionSummary', comment);
+ // @TODO(bengo) Should I do this for addCommentTag and/or best button
+
+ // @TODO(bengo) Would be best to only create these funcs on prop change
+ const addBestTag = () => addCommentTag({
+ comment_id: comment.id,
+ tag: BEST_TAG,
+ });
+ const removeBestTag = () => removeCommentTag({
+ comment_id: comment.id,
+ tag: BEST_TAG,
+ });
+
return (
diff --git a/client/coral-embed-stream/src/Embed.js b/client/coral-embed-stream/src/Embed.js
index ac9c09eac..3290e2c8e 100644
--- a/client/coral-embed-stream/src/Embed.js
+++ b/client/coral-embed-stream/src/Embed.js
@@ -13,7 +13,7 @@ const {addNotification, clearNotification} = notificationActions;
const {fetchAssetSuccess} = assetActions;
import {queryStream} from 'coral-framework/graphql/queries';
-import {postComment, postFlag, postLike, postDontAgree, deleteAction} from 'coral-framework/graphql/mutations';
+import {postComment, postFlag, postLike, postDontAgree, deleteAction, addCommentTag, removeCommentTag} from 'coral-framework/graphql/mutations';
import {editName} from 'coral-framework/actions/user';
import {updateCountCache} from 'coral-framework/actions/asset';
import {Notification, notificationActions, authActions, assetActions, pym} from 'coral-framework';
@@ -54,7 +54,13 @@ class Embed extends Component {
data: React.PropTypes.shape({
loading: React.PropTypes.bool,
error: React.PropTypes.object
- }).isRequired
+ }).isRequired,
+
+ // dispatch action to add a tag to a comment
+ addCommentTag: React.PropTypes.func,
+
+ // dispatch action to remove a tag from a comment
+ removeCommentTag: React.PropTypes.func,
}
componentDidMount () {
@@ -176,6 +182,8 @@ class Embed extends Component {
postLike={this.props.postLike}
postFlag={this.props.postFlag}
postDontAgree={this.props.postDontAgree}
+ addCommentTag={this.props.addCommentTag}
+ removeCommentTag={this.props.removeCommentTag}
getCounts={this.props.getCounts}
updateCountCache={this.props.updateCountCache}
loadMore={this.props.loadMore}
@@ -250,6 +258,8 @@ export default compose(
postFlag,
postLike,
postDontAgree,
+ addCommentTag,
+ removeCommentTag,
deleteAction,
queryStream
)(Embed);
diff --git a/client/coral-embed-stream/src/Stream.js b/client/coral-embed-stream/src/Stream.js
index a7f360d59..a1756c50e 100644
--- a/client/coral-embed-stream/src/Stream.js
+++ b/client/coral-embed-stream/src/Stream.js
@@ -13,7 +13,13 @@ class Stream extends React.Component {
currentUser: PropTypes.shape({
username: PropTypes.string,
id: PropTypes.string
- })
+ }),
+
+ // dispatch action to add a tag to a comment
+ addCommentTag: React.PropTypes.func,
+
+ // dispatch action to remove a tag from a comment
+ removeCommentTag: React.PropTypes.func,
}
constructor(props) {
@@ -64,7 +70,9 @@ class Stream extends React.Component {
loadMore,
deleteAction,
showSignInDialog,
- refetch
+ refetch,
+ addCommentTag,
+ removeCommentTag,
} = this.props;
return (
@@ -83,6 +91,8 @@ class Stream extends React.Component {
postLike={postLike}
postFlag={postFlag}
postDontAgree={postDontAgree}
+ addCommentTag={addCommentTag}
+ removeCommentTag={removeCommentTag}
loadMore={loadMore}
deleteAction={deleteAction}
showSignInDialog={showSignInDialog}
diff --git a/client/coral-embed-stream/style/default.css b/client/coral-embed-stream/style/default.css
index 46edc44e1..143b0f78c 100644
--- a/client/coral-embed-stream/style/default.css
+++ b/client/coral-embed-stream/style/default.css
@@ -217,6 +217,10 @@ hr {
cursor: pointer;
}
+.comment__action-button[disabled] {
+ cursor: inherit;
+}
+
.comment__action-button--nowrap {
white-space: nowrap;
}
diff --git a/client/coral-framework/graphql/mutations/addCommentTag.graphql b/client/coral-framework/graphql/mutations/addCommentTag.graphql
new file mode 100644
index 000000000..27d369775
--- /dev/null
+++ b/client/coral-framework/graphql/mutations/addCommentTag.graphql
@@ -0,0 +1,12 @@
+mutation AddCommentTag ($comment_id: ID!, $tag: String!) {
+ addCommentTag(comment_id:$comment_id, tag:$tag) {
+ comment {
+ tags {
+ name
+ }
+ }
+ errors {
+ translation_key
+ }
+ }
+}
diff --git a/client/coral-framework/graphql/mutations/index.js b/client/coral-framework/graphql/mutations/index.js
index 67af2df4a..b65a6a339 100644
--- a/client/coral-framework/graphql/mutations/index.js
+++ b/client/coral-framework/graphql/mutations/index.js
@@ -4,6 +4,8 @@ import POST_FLAG from './postFlag.graphql';
import POST_LIKE from './postLike.graphql';
import POST_DONT_AGREE from './postDontAgree.graphql';
import DELETE_ACTION from './deleteAction.graphql';
+import ADD_COMMENT_TAG from './addCommentTag.graphql';
+import REMOVE_COMMENT_TAG from './removeCommentTag.graphql';
import commentView from '../fragments/commentView.graphql';
@@ -122,3 +124,25 @@ export const deleteAction = graphql(DELETE_ACTION, {
});
}}),
});
+
+export const addCommentTag = graphql(ADD_COMMENT_TAG, {
+ props: ({mutate}) => ({
+ addCommentTag: (tag) => {
+ return mutate({
+ variables: {
+ tag
+ }
+ });
+ }}),
+});
+
+export const removeCommentTag = graphql(REMOVE_COMMENT_TAG, {
+ props: ({mutate}) => ({
+ removeCommentTag: (tag) => {
+ return mutate({
+ variables: {
+ tag
+ }
+ });
+ }}),
+});
diff --git a/client/coral-framework/graphql/mutations/removeCommentTag.graphql b/client/coral-framework/graphql/mutations/removeCommentTag.graphql
new file mode 100644
index 000000000..2871a2fae
--- /dev/null
+++ b/client/coral-framework/graphql/mutations/removeCommentTag.graphql
@@ -0,0 +1,12 @@
+mutation RemoveCommentTag ($comment_id: ID!, $tag: String!) {
+ removeCommentTag(comment_id:$comment_id, tag:$tag) {
+ comment {
+ tags {
+ name
+ }
+ }
+ errors {
+ translation_key
+ }
+ }
+}
diff --git a/client/coral-plugin-best/BestButton.js b/client/coral-plugin-best/BestButton.js
index 3010db7c6..9af8b1638 100644
--- a/client/coral-plugin-best/BestButton.js
+++ b/client/coral-plugin-best/BestButton.js
@@ -3,6 +3,10 @@ import {I18n} from '../coral-framework';
import translations from './translations.json';
import classnames from 'classnames';
+// tag string for best comments
+export const BEST_TAG = 'BEST';
+export const commentIsBest = ({tags} = {}) => Array.isArray(tags) && tags.some(t => t === BEST_TAG);
+
const name = 'coral-plugin-best';
const lang = new I18n(translations);
@@ -21,17 +25,17 @@ export const IfUserCanModifyBest = ({user, children}) => {
* Button that lets a moderator tag a comment as "Best".
* Used to recognize really good comments.
*/
-class BestButton extends Component {
+export class BestButton extends Component {
static propTypes = {
// whether the comment is already tagged as best
isBest: PropTypes.bool.isRequired,
// set that this comment is best
- setBestTag: PropTypes.func.isRequired,
+ addBest: PropTypes.func.isRequired,
// remove the best status
- removeBestTag: PropTypes.func.isRequired,
+ removeBest: PropTypes.func.isRequired,
}
state = {
@@ -40,18 +44,30 @@ class BestButton extends Component {
constructor(props) {
super(props);
- this.onClickSetBest = this.onClickSetBest.bind(this);
- this.onClickUnsetBest = this.onClickUnsetBest.bind(this);
+ this.onClickAddBest = this.onClickAddBest.bind(this);
+ this.onClickRemoveBest = this.onClickRemoveBest.bind(this);
}
- onClickSetBest(e) {
+ async onClickAddBest(e) {
e.preventDefault();
- this.setState({isBest: true});
+ const {addBest} = this.props;
+ if ( ! addBest) {
+ console.warn('BestButton#onClickAddBest called even though there is no addBest prop. doing nothing');
+ return;
+ }
+ const addBestRet = await addBest();
+ console.log('addBestRet', addBestRet);
}
- onClickUnsetBest(e) {
+ async onClickRemoveBest(e) {
e.preventDefault();
- this.setState({isBest: false});
+ const {removeBest} = this.props;
+ if ( ! removeBest) {
+ console.warn('BestButton#onClickAddBest called even though there is no removeBest prop. doing nothing');
+ return;
+ }
+ const removeBestRet = await removeBest();
+ console.log('removeBestRet', removeBestRet);
}
render() {
@@ -59,10 +75,12 @@ class BestButton extends Component {
// @TODO(bengo) Consider adding the comment__action classes to other buttons to add cursor:pointer and never wrap the icons
// @TODO(bengo) Should I reuse another element like coral-ui button? Just doing what LikeButton does for now
// Oh. I think that's styled for the admin. Don't use coral-ui button until the whole comment bottom bar does.
- const {isBest} = this.state;
+ let {isBest} = this.state;
+ const {addBest, removeBest} = this.props;
return
-
;
}
}
-
-export default BestButton;