diff --git a/client/coral-embed-stream/src/Comment.js b/client/coral-embed-stream/src/Comment.js
index 8371cec45..7262d10ed 100644
--- a/client/coral-embed-stream/src/Comment.js
+++ b/client/coral-embed-stream/src/Comment.js
@@ -90,6 +90,7 @@ class Comment extends React.Component {
showSignInDialog,
postLike,
postFlag,
+ postDontAgree,
loadMore,
setActiveReplyBox,
activeReplyBox,
@@ -98,6 +99,7 @@ class Comment extends React.Component {
const like = getActionSummary('LikeActionSummary', comment);
const flag = getActionSummary('FlagActionSummary', comment);
+ const dontagree = getActionSummary('DontAgreeActionSummary', comment);
return (
diff --git a/client/coral-embed-stream/src/Embed.js b/client/coral-embed-stream/src/Embed.js
index 5c72e65d6..ac9c09eac 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, deleteAction} from 'coral-framework/graphql/mutations';
+import {postComment, postFlag, postLike, postDontAgree, deleteAction} 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';
@@ -175,6 +175,7 @@ class Embed extends Component {
currentUser={user}
postLike={this.props.postLike}
postFlag={this.props.postFlag}
+ postDontAgree={this.props.postDontAgree}
getCounts={this.props.getCounts}
updateCountCache={this.props.updateCountCache}
loadMore={this.props.loadMore}
@@ -248,6 +249,7 @@ export default compose(
postComment,
postFlag,
postLike,
+ postDontAgree,
deleteAction,
queryStream
)(Embed);
diff --git a/client/coral-embed-stream/src/Stream.js b/client/coral-embed-stream/src/Stream.js
index 89a637ceb..a7f360d59 100644
--- a/client/coral-embed-stream/src/Stream.js
+++ b/client/coral-embed-stream/src/Stream.js
@@ -60,6 +60,7 @@ class Stream extends React.Component {
addNotification,
postFlag,
postLike,
+ postDontAgree,
loadMore,
deleteAction,
showSignInDialog,
@@ -81,6 +82,7 @@ class Stream extends React.Component {
currentUser={currentUser}
postLike={postLike}
postFlag={postFlag}
+ postDontAgree={postDontAgree}
loadMore={loadMore}
deleteAction={deleteAction}
showSignInDialog={showSignInDialog}
diff --git a/client/coral-framework/graphql/mutations/index.js b/client/coral-framework/graphql/mutations/index.js
index a9d08da85..67af2df4a 100644
--- a/client/coral-framework/graphql/mutations/index.js
+++ b/client/coral-framework/graphql/mutations/index.js
@@ -2,6 +2,7 @@ import {graphql} from 'react-apollo';
import POST_COMMENT from './postComment.graphql';
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 commentView from '../fragments/commentView.graphql';
@@ -100,6 +101,17 @@ export const postFlag = graphql(POST_FLAG, {
}}),
});
+export const postDontAgree = graphql(POST_DONT_AGREE, {
+ props: ({mutate}) => ({
+ postDontAgree: (dontagree) => {
+ return mutate({
+ variables: {
+ dontagree
+ }
+ });
+ }}),
+});
+
export const deleteAction = graphql(DELETE_ACTION, {
props: ({mutate}) => ({
deleteAction: (id) => {
diff --git a/client/coral-framework/graphql/mutations/postDontAgree.graphql b/client/coral-framework/graphql/mutations/postDontAgree.graphql
new file mode 100644
index 000000000..6e36d48b8
--- /dev/null
+++ b/client/coral-framework/graphql/mutations/postDontAgree.graphql
@@ -0,0 +1,10 @@
+mutation CreateDontAgree($dontagree: CreateDontAgreeInput!) {
+ createDontAgree(dontagree:$dontagree) {
+ dontagree {
+ id
+ }
+ errors {
+ translation_key
+ }
+ }
+}
diff --git a/client/coral-plugin-flags/FlagBio.js b/client/coral-plugin-flags/FlagBio.js
deleted file mode 100644
index 2639ab8cf..000000000
--- a/client/coral-plugin-flags/FlagBio.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import React from 'react';
-import FlagButton from './FlagButton';
-import {I18n} from '../coral-framework';
-import translations from './translations.json';
-
-const FlagBio = (props) =>
;
-
-const getPopupMenu = [
- () => {
- return {
- header: lang.t('step-2-header'),
- itemType: 'USERS',
- field: 'bio',
- options: [
- {val: 'This bio is offensive', text: lang.t('bio-offensive')},
- {val: 'I don\'t like this bio', text: lang.t('no-like-bio')},
- {val: 'This looks like an ad/marketing', text: lang.t('marketing')},
- {val: 'other', text: lang.t('other')}
- ],
- button: lang.t('continue'),
- sets: 'reason'
- };
- },
- () => {
- return {
- header: lang.t('step-3-header'),
- text: lang.t('thank-you'),
- button: lang.t('done'),
- };
- }
-];
-
-export default FlagBio;
-
-const lang = new I18n(translations);
diff --git a/client/coral-plugin-flags/FlagButton.js b/client/coral-plugin-flags/FlagButton.js
index e94dfc5fc..537d899cd 100644
--- a/client/coral-plugin-flags/FlagButton.js
+++ b/client/coral-plugin-flags/FlagButton.js
@@ -38,7 +38,7 @@ class FlagButton extends Component {
}
onPopupContinue = () => {
- const {postFlag, id, author_id} = this.props;
+ const {postFlag, postDontAgree, id, author_id} = this.props;
const {itemType, reason, step, posted, message} = this.state;
// Proceed to the next step or close the menu if we've reached the end
@@ -52,7 +52,6 @@ class FlagButton extends Component {
if (itemType && reason && !posted) {
this.setState({posted: true});
- // Set the text from the "other" field if it exists.
let item_id;
switch(itemType) {
case 'COMMENTS':
@@ -63,20 +62,31 @@ class FlagButton extends Component {
break;
}
- // Note: Action metadata has been temporarily removed.
if (itemType === 'COMMENTS') {
this.setState({localPost: 'temp'});
}
- postFlag({
+
+ let action = {
item_id,
item_type: itemType,
- reason,
+ reason: null,
message
- }).then(({data}) => {
- if (itemType === 'COMMENTS') {
- this.setState({localPost: data.createFlag.flag.id});
- }
- });
+ };
+ if (reason === 'I don\'t agree with this comment') {
+ postDontAgree(action)
+ .then(({data}) => {
+ if (itemType === 'COMMENTS') {
+ this.setState({localPost: data.createDontAgree.dontagree.id});
+ }
+ });
+ } else {
+ postFlag({...action, reason})
+ .then(({data}) => {
+ if (itemType === 'COMMENTS') {
+ this.setState({localPost: data.createFlag.flag.id});
+ }
+ });
+ }
}
}
diff --git a/client/coral-plugin-flags/FlagComment.js b/client/coral-plugin-flags/FlagComment.js
index bf3fca286..24fde6b0f 100644
--- a/client/coral-plugin-flags/FlagComment.js
+++ b/client/coral-plugin-flags/FlagComment.js
@@ -20,9 +20,9 @@ const getPopupMenu = [
(itemType) => {
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')},
{val: 'This looks like an ad/marketing', text: lang.t('marketing')},
+ {val: 'I don\'t agree with this comment', text: lang.t('no-agree-comment')},
{val: 'other', text: lang.t('other')}
]
: [
diff --git a/graph/resolvers/action.js b/graph/resolvers/action.js
index 0962f59af..1bb8d077e 100644
--- a/graph/resolvers/action.js
+++ b/graph/resolvers/action.js
@@ -1,6 +1,8 @@
const Action = {
__resolveType({action_type}) {
switch (action_type) {
+ case 'DONTAGREE':
+ return 'DontAgreeAction';
case 'FLAG':
return 'FlagAction';
case 'LIKE':
diff --git a/graph/resolvers/action_summary.js b/graph/resolvers/action_summary.js
index 93848d285..1986a0648 100644
--- a/graph/resolvers/action_summary.js
+++ b/graph/resolvers/action_summary.js
@@ -5,6 +5,8 @@ const ActionSummary = {
return 'FlagActionSummary';
case 'LIKE':
return 'LikeActionSummary';
+ case 'DONTAGREE':
+ return 'DontAgreeActionSummary';
}
},
};
diff --git a/graph/resolvers/dont_agree_action.js b/graph/resolvers/dont_agree_action.js
new file mode 100644
index 000000000..25dc02503
--- /dev/null
+++ b/graph/resolvers/dont_agree_action.js
@@ -0,0 +1,9 @@
+const DontAgreeAction = {
+
+ // Stored in the metadata, extract and return.
+ reason({metadata: {reason}}) {
+ return reason;
+ }
+};
+
+module.exports = DontAgreeAction;
diff --git a/graph/resolvers/dont_agree_action_summary.js b/graph/resolvers/dont_agree_action_summary.js
new file mode 100644
index 000000000..520fdce3b
--- /dev/null
+++ b/graph/resolvers/dont_agree_action_summary.js
@@ -0,0 +1,7 @@
+const DontAgreeActionSummary = {
+ reason({group_id}) {
+ return group_id;
+ }
+};
+
+module.exports = DontAgreeActionSummary;
diff --git a/graph/resolvers/index.js b/graph/resolvers/index.js
index 65461dc76..3bd8c571d 100644
--- a/graph/resolvers/index.js
+++ b/graph/resolvers/index.js
@@ -6,6 +6,8 @@ const Comment = require('./comment');
const Date = require('./date');
const FlagActionSummary = require('./flag_action_summary');
const FlagAction = require('./flag_action');
+const DontAgreeAction = require('./dont_agree_action');
+const DontAgreeActionSummary = require('./dont_agree_action_summary');
const GenericUserError = require('./generic_user_error');
const LikeAction = require('./like_action');
const RootMutation = require('./root_mutation');
@@ -24,6 +26,8 @@ module.exports = {
Date,
FlagActionSummary,
FlagAction,
+ DontAgreeAction,
+ DontAgreeActionSummary,
GenericUserError,
LikeAction,
RootMutation,
diff --git a/graph/resolvers/root_mutation.js b/graph/resolvers/root_mutation.js
index 71ac8b8a6..2462962c6 100644
--- a/graph/resolvers/root_mutation.js
+++ b/graph/resolvers/root_mutation.js
@@ -13,7 +13,6 @@ const wrapResponse = (key) => (promise) => {
}
return res;
}).catch((err) => {
-
if (err instanceof errors.APIError) {
return {
errors: [err]
@@ -38,6 +37,9 @@ const RootMutation = {
createFlag(_, {flag: {item_id, item_type, reason, message}}, {mutators: {Action}}) {
return wrapResponse('flag')(Action.create({item_id, item_type, action_type: 'FLAG', group_id: reason, metadata: {message}}));
},
+ createDontAgree(_, {dontagree: {item_id, item_type, reason, message}}, {mutators: {Action}}) {
+ return wrapResponse('dontagree')(Action.create({item_id, item_type, action_type: 'DONTAGREE', group_id: reason, metadata: {message}}));
+ },
deleteAction(_, {id}, {mutators: {Action}}) {
return wrapResponse(null)(Action.delete({id}));
},
diff --git a/graph/typeDefs.graphql b/graph/typeDefs.graphql
index 7db4dbad8..fbdeb4279 100644
--- a/graph/typeDefs.graphql
+++ b/graph/typeDefs.graphql
@@ -91,6 +91,9 @@ enum ACTION_TYPE {
# Represents a FlagAction.
FLAG
+
+ # Represents a don't agree action
+ DONTAGREE
}
# CommentsQuery allows the ability to query comments by a specific methods.
@@ -187,7 +190,7 @@ type Comment {
## Actions
################################################################################
-# An action rendered against a parent enity item.
+# An action rendered against a parent entity item.
interface Action {
# The ID of the action.
@@ -290,6 +293,28 @@ type FlagAction implements Action {
created_at: Date
}
+# A DONTAGREE action that contains do not agree metadata.
+type DontAgreeAction implements Action {
+
+ # The ID of the DontAgree Action.
+ id: ID!
+
+ # The reason for which the DontAgree Action was created.
+ reason: String
+
+ # An optional message sent with the flagging action by the user.
+ message: String
+
+ # The user who created the action.
+ user: User
+
+ # The time when the DontAgree Action was updated.
+ updated_at: Date
+
+ # The time when the DontAgree Action was created.
+ created_at: Date
+}
+
# Summary for Flag Action with a a unique reason.
type FlagActionSummary implements ActionSummary {
@@ -303,6 +328,19 @@ type FlagActionSummary implements ActionSummary {
current_user: FlagAction
}
+# Summary for Don't Agree Action with a a unique reason.
+type DontAgreeActionSummary implements ActionSummary {
+
+ # The total count of flags with this reason.
+ count: Int!
+
+ # The reason for which the Flag Action was created.
+ reason: String
+
+ # The don't agree action by the current user against the parent entity with this reason.
+ current_user: DontAgreeAction
+}
+
################################################################################
## Settings
################################################################################
@@ -468,18 +506,18 @@ type RootQuery {
# Response defines what can be expected from any response to a mutation action.
interface Response {
- # An array of errors relating to the mutation that occured.
+ # An array of errors relating to the mutation that occurred.
errors: [UserError]
}
# CreateCommentResponse is returned with the comment that was created and any
-# errors that may have occured in the attempt to create it.
+# errors that may have occurred in the attempt to create it.
type CreateCommentResponse implements Response {
# The comment that was created.
comment: Comment
- # An array of errors relating to the mutation that occured.
+ # An array of errors relating to the mutation that occurred.
errors: [UserError]
}
@@ -510,7 +548,7 @@ type CreateLikeResponse implements Response {
# The like that was created.
like: LikeAction
- # An array of errors relating to the mutation that occured.
+ # An array of errors relating to the mutation that occurred.
errors: [UserError]
}
@@ -534,18 +572,46 @@ input CreateFlagInput {
# was created.
type CreateFlagResponse implements Response {
- # The like that was created.
+ # The flag that was created.
flag: FlagAction
- # An array of errors relating to the mutation that occured.
+ # An array of errors relating to the mutation that occurred.
errors: [UserError]
}
+
+# CreateDontAgreeResponse is the response returned with possibly some errors
+# relating to the creating the don't agree action attempt and possibly the don't agree that
+# was created.
+type CreateDontAgreeResponse implements Response {
+
+ # The don't agree that was created.
+ dontagree: DontAgreeAction
+
+ # An array of errors relating to the mutation that occurred.
+ errors: [UserError]
+}
+
+input CreateDontAgreeInput {
+
+ # The item's id for which we are to create a don't agree.
+ item_id: ID!
+
+ # The type of the item for which we are to create the don't agree.
+ item_type: ACTION_ITEM_TYPE!
+
+ # The reason for not agreeing with the item.
+ reason: String
+
+ # An optional message sent with the don't agree action by the user.
+ message: String
+}
+
# DeleteActionResponse is the response returned with possibly some errors
# relating to the delete action attempt.
type DeleteActionResponse implements Response {
- # An array of errors relating to the mutation that occured.
+ # An array of errors relating to the mutation that occurred.
errors: [UserError]
}
@@ -553,7 +619,7 @@ type DeleteActionResponse implements Response {
# relating to the delete action attempt.
type SetUserStatusResponse implements Response {
- # An array of errors relating to the mutation that occured.
+ # An array of errors relating to the mutation that occurred.
errors: [UserError]
}
@@ -561,7 +627,7 @@ type SetUserStatusResponse implements Response {
# relating to the delete action attempt.
type SetCommentStatusResponse implements Response {
- # An array of errors relating to the mutation that occured.
+ # An array of errors relating to the mutation that occurred.
errors: [UserError]
}
@@ -577,6 +643,9 @@ type RootMutation {
# Creates a flag on an entity.
createFlag(flag: CreateFlagInput!): CreateFlagResponse
+ # Creates a don't agree action on an entity.
+ createDontAgree(dontagree: CreateDontAgreeInput!): CreateDontAgreeResponse
+
# Delete an action based on the action id.
deleteAction(id: ID!): DeleteActionResponse