diff --git a/client/coral-embed-stream/src/components/Comment.js b/client/coral-embed-stream/src/components/Comment.js
index 13d286296..a16dc3886 100644
--- a/client/coral-embed-stream/src/components/Comment.js
+++ b/client/coral-embed-stream/src/components/Comment.js
@@ -65,7 +65,7 @@ class Comment extends React.Component {
parentId: PropTypes.string,
highlighted: PropTypes.string,
addNotification: PropTypes.func.isRequired,
- postItem: PropTypes.func.isRequired,
+ postComment: PropTypes.func.isRequired,
depth: PropTypes.number.isRequired,
asset: PropTypes.shape({
id: PropTypes.string,
@@ -145,7 +145,7 @@ class Comment extends React.Component {
// re-render
this.setState(this.state);
- }, msLeftToEdit);
+ }, msLeftToEdit);
}
}
componentWillUnmount() {
@@ -161,7 +161,7 @@ class Comment extends React.Component {
currentUser,
asset,
depth,
- postItem,
+ postComment,
addNotification,
showSignInDialog,
highlighted,
@@ -286,7 +286,7 @@ class Comment extends React.Component {
}
- {
+ {
this.state.isEditing
?
: null}
@@ -386,7 +386,7 @@ class Comment extends React.Component {
activeReplyBox={activeReplyBox}
addNotification={addNotification}
parentId={comment.id}
- postItem={postItem}
+ postComment={postComment}
editComment={this.props.editComment}
depth={depth + 1}
asset={asset}
@@ -430,7 +430,7 @@ function commentIsStillEditable (comment) {
if ( ! editing) {return false;}
const editableUntil = getEditableUntilDate(comment);
const editWindowExpired = (editableUntil - new Date) < 0;
- return ! editWindowExpired;
+ return ! editWindowExpired;
}
// return number of milliseconds before edit window expires
diff --git a/client/coral-embed-stream/src/components/Stream.js b/client/coral-embed-stream/src/components/Stream.js
index 121aa7993..b7b325cf6 100644
--- a/client/coral-embed-stream/src/components/Stream.js
+++ b/client/coral-embed-stream/src/components/Stream.js
@@ -26,7 +26,7 @@ class Stream extends React.Component {
render() {
const {
root: {asset, asset: {comments}, comment, myIgnoredUsers},
- postItem,
+ postComment,
addNotification,
postFlag,
postDontAgree,
@@ -84,7 +84,7 @@ class Stream extends React.Component {
{user
? ({
variables: {
assetId,
@@ -83,11 +82,7 @@ export const withQuery = graphql(EMBED_QUERY, {
hasComment: commentId !== '',
excludeIgnored: Boolean(auth && auth.user && auth.user.id),
},
- reducer: (previousResult, action, variables) => {
- return reduceEditCommentActionsToUpdateStreamQuery(previousResult, action, variables);
- },
}),
- props: ({data}) => separateDataAndRoot(data)
});
const mapStateToProps = state => ({
@@ -116,88 +111,6 @@ const mapDispatchToProps = dispatch =>
export default compose(
connect(mapStateToProps, mapDispatchToProps),
branch(props => !props.auth.checkedInitialLogin && props.config, renderComponent(Spinner)),
- withQuery
+ withEmbedQuery,
)(EmbedContainer);
-/**
- * Reduce editComment mutation actions
- * producing a new queryStream result where asset.comments reflects the edit
- */
-function reduceEditCommentActionsToUpdateStreamQuery(previousResult, action) {
- if ( ! (action.type === 'APOLLO_MUTATION_RESULT' && action.operationName === 'editComment')) {
- return previousResult;
- }
- const resultHasErrors = (result) => {
- try {
- return result.data.editComment.errors.length > 0;
- } catch (error) {
-
- // expected if no errors;
- return false;
- }
- };
- if (resultHasErrors(action.result)) {
- return previousResult;
- }
- const {variables: {id, edit}, result: {data: {editComment: {comment: {status}}}}} = action;
- const updateCommentWithEdit = (comment, edit) => {
- const {body} = edit;
- const editedComment = update(comment, {
- $merge: {
- body
- },
- editing: {$merge:{edited:true}}
- });
- return editedComment;
- };
- const commentIsStillVisible = (comment) => {
- return ! ((id === comment.id) && (['PREMOD', 'REJECTED'].includes(status)));
- };
- const resultReflectingEdit = update(previousResult, {
- asset: {
- comments: {
- $apply: comments => {
- return comments.filter(commentIsStillVisible).map(comment => {
- let replyWasEditedToBeHidden = false;
- if (comment.id === id) {
- return updateCommentWithEdit(comment, edit);
- }
- const commentWithUpdatedReplies = update(comment, {
- replies: {
- $apply: (comments) => {
- return comments
- .filter(c => {
- if (commentIsStillVisible(c)) {
- return true;
- }
- replyWasEditedToBeHidden = true;
- return false;
- })
- .map(comment => {
- if (comment.id === id) {
- return updateCommentWithEdit(comment, edit);
- }
- return comment;
- });
- }
- },
- });
-
- // If a reply was edited to be hdiden, then this parent needs its replyCount to be decremented.
- if (replyWasEditedToBeHidden) {
- return update(commentWithUpdatedReplies, {
- replyCount: {
- $apply: (replyCount) => {
- return replyCount - 1;
- }
- }
- });
- }
- return commentWithUpdatedReplies;
- });
- }
- }
- }
- });
- return resultReflectingEdit;
-}
diff --git a/client/coral-embed-stream/src/containers/Stream.js b/client/coral-embed-stream/src/containers/Stream.js
index 443008913..f19cc0a34 100644
--- a/client/coral-embed-stream/src/containers/Stream.js
+++ b/client/coral-embed-stream/src/containers/Stream.js
@@ -6,13 +6,17 @@ import uniqBy from 'lodash/uniqBy';
import sortBy from 'lodash/sortBy';
import isNil from 'lodash/isNil';
import {NEW_COMMENT_COUNT_POLL_INTERVAL} from '../constants/stream';
-import {postComment, postFlag, postDontAgree, deleteAction, addCommentTag, removeCommentTag, ignoreUser, editComment} from 'coral-framework/graphql/mutations';
+import {
+ withPostComment, withPostFlag, withPostDontAgree, withDeleteAction,
+ withAddCommentTag, withRemoveCommentTag, withIgnoreUser, withEditComment,
+} from 'coral-framework/graphql/mutations';
+
import {notificationActions, authActions} from 'coral-framework';
import {editName} from 'coral-framework/actions/user';
import {setCommentCountCache, setActiveReplyBox} from '../actions/stream';
import Stream from '../components/Stream';
import Comment from './Comment';
-import withFragments from 'coral-framework/hocs/withFragments';
+import {withFragments} from 'coral-framework/hocs';
import {getDefinitionName} from 'coral-framework/utils';
const {showSignInDialog} = authActions;
@@ -236,13 +240,13 @@ const mapDispatchToProps = dispatch =>
export default compose(
withFragments(fragments),
connect(mapStateToProps, mapDispatchToProps),
- postComment,
- postFlag,
- postDontAgree,
- addCommentTag,
- removeCommentTag,
- ignoreUser,
- deleteAction,
- editComment,
+ withPostComment,
+ withPostFlag,
+ withPostDontAgree,
+ withAddCommentTag,
+ withRemoveCommentTag,
+ withIgnoreUser,
+ withDeleteAction,
+ withEditComment,
)(StreamContainer);
diff --git a/client/coral-embed-stream/src/graphql/index.js b/client/coral-embed-stream/src/graphql/index.js
new file mode 100644
index 000000000..daa8389b3
--- /dev/null
+++ b/client/coral-embed-stream/src/graphql/index.js
@@ -0,0 +1,270 @@
+import {gql} from 'react-apollo';
+import {add} from 'coral-framework/services/graphqlRegistry';
+import update from 'immutability-helper';
+
+const extension = {
+ fragments: {
+ EditCommentResponse: gql`
+ fragment CoralEmbedStream_EditCommentResponse on EditCommentResponse {
+ comment {
+ status
+ }
+ errors {
+ translation_key
+ }
+ }
+ `,
+ StopIgnoringUserResponse: gql`
+ fragment CoralEmbedStream_StopIgnoringUserResponse on StopIgnoringUserResponse {
+ errors {
+ translation_key
+ }
+ }
+ `,
+ IgnoreUserResponse: gql`
+ fragment CoralEmbedStream_IgnoreUserResponse on IgnoreUserResponse {
+ errors {
+ translation_key
+ }
+ }
+ `,
+ RemoveCommentTagResponse: gql`
+ fragment CoralEmbedStream_RemoveCommentTagResponse on RemoveCommentTagResponse {
+ comment {
+ id
+ tags {
+ name
+ }
+ }
+ errors {
+ translation_key
+ }
+ }
+ `,
+ AddCommentTagResponse: gql`
+ fragment CoralEmbedStream_AddCommentTagResponse on AddCommentTagResponse {
+ comment {
+ id
+ tags {
+ name
+ }
+ }
+ errors {
+ translation_key
+ }
+ }
+ `,
+ DeleteActionResponse: gql`
+ fragment CoralEmbedStream_DeleteActionResponse on DeleteActionResponse {
+ errors {
+ translation_key
+ }
+ }
+ `,
+ CreateFlagResponse: gql`
+ fragment CoralEmbedStream_CreateFlagResponse on CreateFlagResponse {
+ flag {
+ id
+ }
+ errors {
+ translation_key
+ }
+ }
+ `,
+ CreateDontAgreeResponse : gql`
+ fragment CoralEmbedStream_CreateDontAgreeResponse on CreateDontAgreeResponse {
+ dontagree {
+ id
+ }
+ errors {
+ translation_key
+ }
+ }
+ `,
+ CreateCommentResponse: gql`
+ fragment CoralEmbedStream_CreateCommentResponse on CreateCommentResponse {
+ comment {
+ ...CoralEmbedStream_CreateCommentResponse_Comment
+ replies {
+ ...CoralEmbedStream_CreateCommentResponse_Comment
+ }
+ }
+ errors {
+ translation_key
+ }
+ }
+
+ fragment CoralEmbedStream_CreateCommentResponse_Comment on Comment {
+ id
+ body
+ created_at
+ status
+ replyCount
+ tags {
+ name
+ }
+ user {
+ id
+ name: username
+ }
+ action_summaries {
+ count
+ current_user {
+ id
+ created_at
+ }
+ }
+ editing {
+ edited
+ editableUntil
+ }
+ }
+ `,
+ },
+ mutations: {
+ IgnoreUser: () => ({
+
+ // TODO: don't rely on refetching.
+ refetchQueries: [
+ 'EmbedQuery', 'myIgnoredUsers',
+ ],
+ }),
+ StopIgnoringUser: () => ({
+
+ // TODO: don't rely on refetching.
+ refetchQueries: [
+ 'EmbedQuery', 'myIgnoredUsers',
+ ],
+ }),
+ PostComment: ({
+ variables: {comment: {asset_id, body, parent_id, tags = []}},
+ state: {auth},
+ }) => ({
+ optimisticResponse: {
+ createComment: {
+ comment: {
+ user: {
+ id: auth.toJS().user.id,
+ name: auth.toJS().user.username
+ },
+ created_at: new Date().toISOString(),
+ body,
+ parent_id,
+ asset_id,
+ action_summaries: [],
+ tags,
+ status: null,
+ id: 'pending'
+ }
+ }
+ },
+ updateQueries: {
+ EmbedQuery: (previousData, {mutationResult: {data: {createComment: {comment}}}}) => {
+ if (previousData.asset.settings.moderation === 'PRE' || comment.status === 'PREMOD' || comment.status === 'REJECTED') {
+ return previousData;
+ }
+
+ let updatedAsset;
+
+ // If posting a reply
+ if (parent_id) {
+ updatedAsset = {
+ ...previousData,
+ asset: {
+ ...previousData.asset,
+ comments: previousData.asset.comments.map((oldComment) => {
+ return oldComment.id === parent_id
+ ? {...oldComment, replies: [...oldComment.replies, comment], replyCount: oldComment.replyCount + 1}
+ : oldComment;
+ })
+ }
+ };
+ } else {
+
+ // If posting a top-level comment
+ updatedAsset = {
+ ...previousData,
+ asset: {
+ ...previousData.asset,
+ commentCount: previousData.asset.commentCount + 1,
+ comments: [comment, ...previousData.asset.comments]
+ }
+ };
+ }
+
+ return updatedAsset;
+ }
+ }
+ }),
+ EditComment: ({
+ variables: {id, edit},
+ }) => ({
+ updateQueries: {
+ EmbedQuery: (previousData, {mutationResult: {data: {editComment: {comment: {status}}}}}) => {
+ const updateCommentWithEdit = (comment, edit) => {
+ const {body} = edit;
+ const editedComment = update(comment, {
+ $merge: {
+ body
+ },
+ editing: {$merge:{edited:true}}
+ });
+ return editedComment;
+ };
+ const commentIsStillVisible = (comment) => {
+ return ! ((id === comment.id) && (['PREMOD', 'REJECTED'].includes(status)));
+ };
+ const resultReflectingEdit = update(previousData, {
+ asset: {
+ comments: {
+ $apply: comments => {
+ return comments.filter(commentIsStillVisible).map(comment => {
+ let replyWasEditedToBeHidden = false;
+ if (comment.id === id) {
+ return updateCommentWithEdit(comment, edit);
+ }
+ const commentWithUpdatedReplies = update(comment, {
+ replies: {
+ $apply: (comments) => {
+ return comments
+ .filter(c => {
+ if (commentIsStillVisible(c)) {
+ return true;
+ }
+ replyWasEditedToBeHidden = true;
+ return false;
+ })
+ .map(comment => {
+ if (comment.id === id) {
+ return updateCommentWithEdit(comment, edit);
+ }
+ return comment;
+ });
+ }
+ },
+ });
+
+ // If a reply was edited to be hdiden, then this parent needs its replyCount to be decremented.
+ if (replyWasEditedToBeHidden) {
+ return update(commentWithUpdatedReplies, {
+ replyCount: {
+ $apply: (replyCount) => {
+ return replyCount - 1;
+ }
+ }
+ });
+ }
+ return commentWithUpdatedReplies;
+ });
+ }
+ }
+ }
+ });
+ return resultReflectingEdit;
+ },
+ },
+ }),
+ },
+};
+
+add(extension);
diff --git a/client/coral-embed-stream/src/index.js b/client/coral-embed-stream/src/index.js
index 52a585fb2..0362f5644 100644
--- a/client/coral-embed-stream/src/index.js
+++ b/client/coral-embed-stream/src/index.js
@@ -4,6 +4,7 @@ import {ApolloProvider} from 'react-apollo';
import {client} from 'coral-framework/services/client';
import {checkLogin} from 'coral-framework/actions/auth';
+import './graphql';
import {addExternalConfig} from 'coral-embed-stream/src/actions/config';
import reducers from './reducers';
diff --git a/client/coral-framework/graphql/fragments.js b/client/coral-framework/graphql/fragments.js
new file mode 100644
index 000000000..f4948ed05
--- /dev/null
+++ b/client/coral-framework/graphql/fragments.js
@@ -0,0 +1,2 @@
+// fragments defined here are automatically registered.
+export default {};
diff --git a/client/coral-framework/graphql/fragments/actionSummaryView.graphql b/client/coral-framework/graphql/fragments/actionSummaryView.graphql
deleted file mode 100644
index 4ac232bf6..000000000
--- a/client/coral-framework/graphql/fragments/actionSummaryView.graphql
+++ /dev/null
@@ -1,8 +0,0 @@
-fragment actionSummaryView on ActionSummary {
- __typename
- count
- current_user {
- id
- created_at
- }
-}
diff --git a/client/coral-framework/graphql/fragments/commentView.graphql b/client/coral-framework/graphql/fragments/commentView.graphql
deleted file mode 100644
index 76f4c8caa..000000000
--- a/client/coral-framework/graphql/fragments/commentView.graphql
+++ /dev/null
@@ -1,22 +0,0 @@
-#import "../fragments/actionSummaryView.graphql"
-
-fragment commentView on Comment {
- id
- body
- created_at
- status
- tags {
- name
- }
- user {
- id
- name: username
- }
- action_summaries {
- ...actionSummaryView
- }
- editing {
- edited
- editableUntil
- }
-}
diff --git a/client/coral-framework/graphql/mutations.js b/client/coral-framework/graphql/mutations.js
new file mode 100644
index 000000000..66e68be97
--- /dev/null
+++ b/client/coral-framework/graphql/mutations.js
@@ -0,0 +1,171 @@
+import {gql} from 'react-apollo';
+import withMutation from '../hocs/withMutation';
+
+export const withPostComment = withMutation(
+ gql`
+ mutation PostComment($comment: CreateCommentInput!) {
+ createComment(comment: $comment) {
+ ...CreateCommentResponse
+ }
+ }
+ `, {
+ props: ({mutate}) => ({
+ postComment: comment => {
+ return mutate({
+ variables: {
+ comment
+ },
+ });
+ }
+ }),
+ });
+
+export const withEditComment = withMutation(
+ gql`
+ mutation EditComment($id: ID!, $asset_id: ID!, $edit: EditCommentInput) {
+ editComment(id:$id, asset_id:$asset_id, edit:$edit) {
+ ...EditCommentResponse
+ }
+ }
+ `, {
+ props: ({mutate}) => ({
+ editComment: (id, asset_id, edit) => {
+ return mutate({
+ variables: {
+ id,
+ asset_id,
+ edit,
+ },
+ });
+ }
+ }),
+ });
+
+export const withPostFlag = withMutation(
+ gql`
+ mutation PostFlag($flag: CreateFlagInput!) {
+ createFlag(flag: $flag) {
+ ...CreateFlagResponse
+ }
+ }
+ `, {
+ props: ({mutate}) => ({
+ postFlag: (flag) => {
+ return mutate({
+ variables: {
+ flag
+ }
+ });
+ }}),
+ });
+
+export const withPostDontAgree = withMutation(
+ gql`
+ mutation CreateDontAgree($dontagree: CreateDontAgreeInput!) {
+ createDontAgree(dontagree: $dontagree) {
+ ...CreateDontAgreeResponse
+ }
+ }
+ `, {
+ props: ({mutate}) => ({
+ postDontAgree: (dontagree) => {
+ return mutate({
+ variables: {
+ dontagree
+ }
+ });
+ }}),
+ });
+
+export const withDeleteAction = withMutation(
+ gql`
+ mutation DeleteAction($id: ID!) {
+ deleteAction(id:$id) {
+ ...DeleteActionResponse
+ }
+ }
+ `, {
+ props: ({mutate}) => ({
+ deleteAction: (id) => {
+ return mutate({
+ variables: {
+ id
+ }
+ });
+ }}),
+ });
+
+export const withAddCommentTag = withMutation(
+ gql`
+ mutation AddCommentTag($id: ID!, $tag: String!) {
+ addCommentTag(id:$id, tag:$tag) {
+ ...AddCommentTagResponse
+ }
+ }
+ `, {
+ props: ({mutate}) => ({
+ addCommentTag: ({id, tag}) => {
+ return mutate({
+ variables: {
+ id,
+ tag
+ }
+ });
+ }}),
+ });
+
+export const withRemoveCommentTag = withMutation(
+ gql`
+ mutation RemoveCommentTag($id: ID!, $tag: String!) {
+ removeCommentTag(id:$id, tag:$tag) {
+ ...RemoveCommentTagResponse
+ }
+ }
+ `, {
+ props: ({mutate}) => ({
+ removeCommentTag: ({id, tag}) => {
+ return mutate({
+ variables: {
+ id,
+ tag
+ }
+ });
+ }}),
+ });
+
+export const withIgnoreUser = withMutation(
+ gql`
+ mutation IgnoreUser($id: ID!) {
+ ignoreUser(id:$id) {
+ ...IgnoreUserResponse
+ }
+ }
+ `, {
+ props: ({mutate}) => ({
+ ignoreUser: ({id}) => {
+ return mutate({
+ variables: {
+ id,
+ },
+ });
+ }}),
+ });
+
+export const withStopIgnoringUser = withMutation(
+ gql`
+ mutation StopIgnoringUser($id: ID!) {
+ stopIgnoringUser(id:$id) {
+ ...StopIgnoringUserResponse
+ }
+ }
+ `, {
+ props: ({mutate}) => ({
+ stopIgnoringUser: ({id}) => {
+ return mutate({
+ variables: {
+ id,
+ },
+ });
+ }}),
+ });
+
diff --git a/client/coral-framework/graphql/mutations/addCommentTag.graphql b/client/coral-framework/graphql/mutations/addCommentTag.graphql
deleted file mode 100644
index 5fd63868e..000000000
--- a/client/coral-framework/graphql/mutations/addCommentTag.graphql
+++ /dev/null
@@ -1,13 +0,0 @@
-mutation AddCommentTag ($id: ID!, $tag: String!) {
- addCommentTag(id:$id, tag:$tag) {
- comment {
- id
- tags {
- name
- }
- }
- errors {
- translation_key
- }
- }
-}
diff --git a/client/coral-framework/graphql/mutations/deleteAction.graphql b/client/coral-framework/graphql/mutations/deleteAction.graphql
deleted file mode 100644
index f8adf371c..000000000
--- a/client/coral-framework/graphql/mutations/deleteAction.graphql
+++ /dev/null
@@ -1,7 +0,0 @@
-mutation deleteAction ($id: ID!) {
- deleteAction(id:$id) {
- errors {
- translation_key
- }
- }
-}
diff --git a/client/coral-framework/graphql/mutations/editComment.graphql b/client/coral-framework/graphql/mutations/editComment.graphql
deleted file mode 100644
index 3cd1ec323..000000000
--- a/client/coral-framework/graphql/mutations/editComment.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-mutation editComment ($id: ID!, $asset_id: ID!, $edit: EditCommentInput) {
- editComment(id:$id, asset_id:$asset_id, edit:$edit) {
- comment {
- status
- }
- errors {
- translation_key
- }
- }
-}
diff --git a/client/coral-framework/graphql/mutations/ignoreUser.graphql b/client/coral-framework/graphql/mutations/ignoreUser.graphql
deleted file mode 100644
index ad3c399f3..000000000
--- a/client/coral-framework/graphql/mutations/ignoreUser.graphql
+++ /dev/null
@@ -1,7 +0,0 @@
-mutation ignoreUser ($id: ID!) {
- ignoreUser(id:$id) {
- errors {
- translation_key
- }
- }
-}
diff --git a/client/coral-framework/graphql/mutations/index.js b/client/coral-framework/graphql/mutations/index.js
deleted file mode 100644
index 4fb87c42c..000000000
--- a/client/coral-framework/graphql/mutations/index.js
+++ /dev/null
@@ -1,191 +0,0 @@
-import {graphql} from 'react-apollo';
-import POST_COMMENT from './postComment.graphql';
-import POST_FLAG from './postFlag.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 IGNORE_USER from './ignoreUser.graphql';
-import STOP_IGNORING_USER from './stopIgnoringUser.graphql';
-import EDIT_COMMENT from './editComment.graphql';
-
-import commentView from '../fragments/commentView.graphql';
-
-export const postComment = graphql(POST_COMMENT, {
- options: () => ({
- fragments: commentView
- }),
- props: ({ownProps, mutate}) => ({
- postItem: comment => {
- const {asset_id, body, parent_id, tags = []} = comment;
- return mutate({
- variables: {
- comment
- },
- optimisticResponse: {
- createComment: {
- comment: {
- user: {
- id: ownProps.auth.user.id,
- name: ownProps.auth.user.username
- },
- created_at: new Date().toISOString(),
- body,
- parent_id,
- asset_id,
- action_summaries: [],
- tags,
- status: null,
- id: 'pending'
- }
- }
- },
- updateQueries: {
- EmbedQuery: (oldData, {mutationResult: {data: {createComment: {comment}}}}) => {
-
- if (oldData.asset.settings.moderation === 'PRE' || comment.status === 'PREMOD' || comment.status === 'REJECTED') {
- return oldData;
- }
-
- let updatedAsset;
-
- // If posting a reply
- if (parent_id) {
- updatedAsset = {
- ...oldData,
- asset: {
- ...oldData.asset,
- comments: oldData.asset.comments.map((oldComment) => {
- return oldComment.id === parent_id
- ? {...oldComment, replies: [...oldComment.replies, comment], replyCount: oldComment.replyCount + 1}
- : oldComment;
- })
- }
- };
- } else {
-
- // If posting a top-level comment
- updatedAsset = {
- ...oldData,
- asset: {
- ...oldData.asset,
- commentCount: oldData.asset.commentCount + 1,
- comments: [comment, ...oldData.asset.comments]
- }
- };
- }
-
- return updatedAsset;
- }
- }
- });
- }
- }),
-});
-
-export const postFlag = graphql(POST_FLAG, {
- props: ({mutate}) => ({
- postFlag: (flag) => {
- return mutate({
- variables: {
- 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) => {
- return mutate({
- variables: {
- id
- }
- });
- }}),
-});
-
-export const addCommentTag = graphql(ADD_COMMENT_TAG, {
- props: ({mutate}) => ({
- addCommentTag: ({id, tag}) => {
- return mutate({
- variables: {
- id,
- tag
- }
- });
- }}),
-});
-
-export const removeCommentTag = graphql(REMOVE_COMMENT_TAG, {
- props: ({mutate}) => ({
- removeCommentTag: ({id, tag}) => {
- return mutate({
- variables: {
- id,
- tag
- }
- });
- }}),
-});
-
-// TODO: don't rely on refetching.
-export const ignoreUser = graphql(IGNORE_USER, {
- props: ({mutate}) => ({
- ignoreUser: ({id}) => {
- return mutate({
- variables: {
- id,
- },
- refetchQueries: [
- 'EmbedQuery', 'myIgnoredUsers',
- ]
- });
- }}),
-});
-
-// TODO: don't rely on refetching.
-export const stopIgnoringUser = graphql(STOP_IGNORING_USER, {
- props: ({mutate}) => {
- return {
- stopIgnoringUser: ({id}) => {
- return mutate({
- variables: {
- id,
- },
- refetchQueries: [
- 'EmbedQuery', 'myIgnoredUsers',
- ]
- });
- }
- };
- }
-});
-
-export const editComment = graphql(EDIT_COMMENT, {
- props: ({mutate}) => {
- return {
- editComment: (id, asset_id, edit) => {
- return mutate({
- variables: {
- id,
- asset_id,
- edit,
- },
- refetchQueries: []
- });
- }
- };
- }
-});
diff --git a/client/coral-framework/graphql/mutations/postComment.graphql b/client/coral-framework/graphql/mutations/postComment.graphql
deleted file mode 100644
index f98558804..000000000
--- a/client/coral-framework/graphql/mutations/postComment.graphql
+++ /dev/null
@@ -1,16 +0,0 @@
-#import "../fragments/commentView.graphql"
-
-mutation CreateComment ($comment: CreateCommentInput!) {
- createComment(comment: $comment) {
- comment {
- ...commentView
- replyCount
- replies {
- ...commentView
- }
- }
- errors {
- translation_key
- }
- }
-}
diff --git a/client/coral-framework/graphql/mutations/postDontAgree.graphql b/client/coral-framework/graphql/mutations/postDontAgree.graphql
deleted file mode 100644
index 6e36d48b8..000000000
--- a/client/coral-framework/graphql/mutations/postDontAgree.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-mutation CreateDontAgree($dontagree: CreateDontAgreeInput!) {
- createDontAgree(dontagree:$dontagree) {
- dontagree {
- id
- }
- errors {
- translation_key
- }
- }
-}
diff --git a/client/coral-framework/graphql/mutations/postFlag.graphql b/client/coral-framework/graphql/mutations/postFlag.graphql
deleted file mode 100644
index cabc2feef..000000000
--- a/client/coral-framework/graphql/mutations/postFlag.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-mutation CreateFlag($flag: CreateFlagInput!) {
- createFlag(flag:$flag) {
- flag {
- id
- }
- errors {
- translation_key
- }
- }
-}
diff --git a/client/coral-framework/graphql/mutations/removeCommentTag.graphql b/client/coral-framework/graphql/mutations/removeCommentTag.graphql
deleted file mode 100644
index 3826b0703..000000000
--- a/client/coral-framework/graphql/mutations/removeCommentTag.graphql
+++ /dev/null
@@ -1,13 +0,0 @@
-mutation RemoveCommentTag ($id: ID!, $tag: String!) {
- removeCommentTag(id:$id, tag:$tag) {
- comment {
- id
- tags {
- name
- }
- }
- errors {
- translation_key
- }
- }
-}
diff --git a/client/coral-framework/graphql/mutations/stopIgnoringUser.graphql b/client/coral-framework/graphql/mutations/stopIgnoringUser.graphql
deleted file mode 100644
index 042452ff5..000000000
--- a/client/coral-framework/graphql/mutations/stopIgnoringUser.graphql
+++ /dev/null
@@ -1,7 +0,0 @@
-mutation stopIgnoringUser ($id: ID!) {
- stopIgnoringUser(id:$id) {
- errors {
- translation_key
- }
- }
-}
diff --git a/client/coral-framework/graphql/queries/index.js b/client/coral-framework/graphql/queries/index.js
deleted file mode 100644
index d76614a68..000000000
--- a/client/coral-framework/graphql/queries/index.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import {graphql} from 'react-apollo';
-import MY_COMMENT_HISTORY from './myCommentHistory.graphql';
-import MY_IGNORED_USERS from './myIgnoredUsers.graphql';
-
-export const myCommentHistory = graphql(MY_COMMENT_HISTORY, {});
-
-export const myIgnoredUsers = graphql(MY_IGNORED_USERS, {
- props: ({data}) => {
- return ({
- myIgnoredUsersData: data
- });
- }
-});
diff --git a/client/coral-framework/graphql/queries/myCommentHistory.graphql b/client/coral-framework/graphql/queries/myCommentHistory.graphql
deleted file mode 100644
index 0b37b192a..000000000
--- a/client/coral-framework/graphql/queries/myCommentHistory.graphql
+++ /dev/null
@@ -1,14 +0,0 @@
-query myCommentHistory {
- me {
- comments {
- id
- body
- asset {
- id
- title
- url
- }
- created_at
- }
- }
-}
diff --git a/client/coral-framework/graphql/queries/myIgnoredUsers.graphql b/client/coral-framework/graphql/queries/myIgnoredUsers.graphql
deleted file mode 100644
index d81531e37..000000000
--- a/client/coral-framework/graphql/queries/myIgnoredUsers.graphql
+++ /dev/null
@@ -1,6 +0,0 @@
-query myIgnoredUsers {
- myIgnoredUsers {
- id,
- username,
- }
-}
diff --git a/client/coral-framework/helpers/plugins.js b/client/coral-framework/helpers/plugins.js
index d701b933f..bde7f9d68 100644
--- a/client/coral-framework/helpers/plugins.js
+++ b/client/coral-framework/helpers/plugins.js
@@ -3,9 +3,9 @@ import merge from 'lodash/merge';
import flatten from 'lodash/flatten';
import flattenDeep from 'lodash/flattenDeep';
import uniq from 'lodash/uniq';
+import pick from 'lodash/pick';
import plugins from 'pluginsConfig';
-import {gql} from 'react-apollo';
-import {getDefinitionName} from 'coral-framework/utils';
+import {getDefinitionName, mergeDocuments} from 'coral-framework/utils';
export const pluginReducers = merge(
...plugins
@@ -25,19 +25,28 @@ export function getSlotElements(slot, props = {}) {
}
function getComponentFragments(components) {
- return components
+ const res = components
.map(c => c.fragments)
.filter(fragments => fragments)
.reduce((res, fragments) => {
Object.keys(fragments).forEach(key => {
if (!(key in res)) {
- res[key] = {spreads: '', definitions: ''};
+ res[key] = {spreads: [], definitions: []};
}
- res[key].spreads += `...${getDefinitionName(fragments[key])}\n`;
- res[key].definitions = gql`${res[key].definitions}${fragments[key]}`;
+ res[key].spreads.push(getDefinitionName(fragments[key]));
+ res[key].definitions.push(fragments[key]);
});
return res;
}, {});
+
+ Object.keys(res).forEach(key => {
+
+ // Assemble arguments for `gql` to call it directly without using template literals.
+ res[key].spreads = `...${res[key].spreads.join('\n...')}\n`;
+ res[key].definitions = mergeDocuments(res[key].definitions);
+ });
+
+ return res;
}
/**
@@ -73,3 +82,9 @@ export function getSlotsFragments(slots) {
};
}
+export function getGraphQLExtensions() {
+ return plugins
+ .map(o => pick(o.module, ['mutations', 'queries', 'fragments']))
+ .filter(o => o);
+}
+
diff --git a/client/coral-framework/hocs/index.js b/client/coral-framework/hocs/index.js
index 831c356d2..ef4c2ac74 100644
--- a/client/coral-framework/hocs/index.js
+++ b/client/coral-framework/hocs/index.js
@@ -1,7 +1,5 @@
-import withFragments from './withFragments';
-import withReaction from './withReaction';
+export {default as withFragments} from './withFragments';
+export {default as withMutation} from './withMutation';
+export {default as withQuery} from './withQuery';
+export {default as withReaction} from './withReaction';
-export default {
- withFragments,
- withReaction
-};
diff --git a/client/coral-framework/hocs/withMutation.js b/client/coral-framework/hocs/withMutation.js
new file mode 100644
index 000000000..c08a53614
--- /dev/null
+++ b/client/coral-framework/hocs/withMutation.js
@@ -0,0 +1,96 @@
+import * as React from 'react';
+import {graphql} from 'react-apollo';
+import merge from 'lodash/merge';
+import uniq from 'lodash/uniq';
+import flatten from 'lodash/flatten';
+import isEmpty from 'lodash/isEmpty';
+import {getMutationOptions, resolveFragments} from 'coral-framework/services/graphqlRegistry';
+import {store} from 'coral-framework/services/store';
+import {getDefinitionName} from '../utils';
+
+/**
+ * Exports a HOC with the same signature as `graphql`, that will
+ * apply mutation options registered in the graphRegistry.
+ */
+export default (document, config) => WrappedComponent => {
+ config = {
+ ...config,
+ options: config.options || {},
+ props: config.props || (data => ({mutate: data.mutate()})),
+ };
+ const wrappedProps = (data) => {
+ const name = getDefinitionName(document);
+ const callbacks = getMutationOptions(name);
+ const mutate = (base) => {
+ const variables = base.variables || config.options.variables;
+ const configs = callbacks.map(cb => cb({variables, state: store.getState()}));
+
+ const optimisticResponse = merge(
+ base.optimisticResponse || config.options.optimisticResponse,
+ ...configs.map(cfg => cfg.optimisticResponse),
+ );
+
+ const refetchQueries = flatten(uniq([
+ base.refetchQueries || config.options.refetchQueries,
+ ...configs.map(cfg => cfg.refetchQueries),
+ ].filter(i => i)));
+
+ const updateCallbacks =
+ [base.update || config.options.update]
+ .concat(...configs.map(cfg => cfg.update))
+ .filter(i => i);
+
+ const update = (proxy, result) => {
+ updateCallbacks.forEach(cb => cb(proxy, result));
+ };
+
+ const updateQueries =
+ [
+ base.updateQueries || config.options.updateQueries,
+ ...configs.map(cfg => cfg.updateQueries)
+ ]
+ .filter(i => i)
+ .reduce((res, map) => {
+ Object.keys(map).forEach(key => {
+ if (!(key in res)) {
+ res[key] = map[key];
+ } else {
+ const existing = res[key];
+ res[key] = (prev, result) => {
+ const next = existing(prev, result);
+ return map[key](next, result);
+ };
+ }
+ });
+ return res;
+ }, {});
+
+ const wrappedConfig = {
+ variables,
+ optimisticResponse,
+ refetchQueries,
+ updateQueries,
+ update,
+ };
+ if (isEmpty(wrappedConfig.optimisticResponse)) {
+ delete wrappedConfig.optimisticResponse;
+ }
+ return data.mutate(wrappedConfig);
+ };
+ return config.props({...data, mutate});
+ };
+
+ // Lazily resolve fragments from graphRegistry to support circular dependencies.
+ let memoized = null;
+ const getWrapped = () => {
+ if (!memoized) {
+ memoized = graphql(resolveFragments(document), {...config, props: wrappedProps})(WrappedComponent);
+ }
+ return memoized;
+ };
+
+ return (props) => {
+ const Wrapped = getWrapped();
+ return ;
+ };
+};
diff --git a/client/coral-framework/hocs/withQuery.js b/client/coral-framework/hocs/withQuery.js
new file mode 100644
index 000000000..a29d25241
--- /dev/null
+++ b/client/coral-framework/hocs/withQuery.js
@@ -0,0 +1,49 @@
+import * as React from 'react';
+import {graphql} from 'react-apollo';
+import {getQueryOptions, resolveFragments} from 'coral-framework/services/graphqlRegistry';
+import {getDefinitionName, separateDataAndRoot} from '../utils';
+
+/**
+ * Exports a HOC with the same signature as `graphql`, that will
+ * apply query options registered in the graphRegistry.
+ */
+export default (document, config) => WrappedComponent => {
+ config = {
+ ...config,
+ options: config.options || {},
+ props: config.props || (({data}) => separateDataAndRoot(data)),
+ };
+
+ const wrappedOptions = (data) => {
+ const base = (typeof config.options === 'function') ? config.options(data) : config.options;
+ const name = getDefinitionName(document);
+ const configs = getQueryOptions(name);
+ const reducerCallbacks =
+ [base.reducer || (i => i)]
+ .concat(...configs.map(cfg => cfg.reducer))
+ .filter(i => i);
+
+ const reducer = reducerCallbacks.reduce(
+ (a, b) => (prev, ...rest) =>
+ b(a(prev, ...rest), ...rest),
+ );
+
+ return {
+ ...base,
+ reducer,
+ };
+ };
+
+ let memoized = null;
+ const getWrapped = () => {
+ if (!memoized) {
+ memoized = graphql(resolveFragments(document), {...config, options: wrappedOptions})(WrappedComponent);
+ }
+ return memoized;
+ };
+
+ return (props) => {
+ const Wrapped = getWrapped();
+ return ;
+ };
+};
diff --git a/client/coral-framework/index.js b/client/coral-framework/index.js
index 46ee704f4..b85b69bcd 100644
--- a/client/coral-framework/index.js
+++ b/client/coral-framework/index.js
@@ -1,7 +1,6 @@
import pym from './services/PymConnection';
import I18n from './modules/i18n/i18n';
import actions from './actions';
-import hocs from './hocs';
// TODO (bc): Deprecate old actions. Spreading actions is now needed.
@@ -9,6 +8,5 @@ export default {
pym,
I18n,
actions,
- ...hocs,
...actions
};
diff --git a/client/coral-framework/services/graphqlRegistry.js b/client/coral-framework/services/graphqlRegistry.js
new file mode 100644
index 000000000..78d27d038
--- /dev/null
+++ b/client/coral-framework/services/graphqlRegistry.js
@@ -0,0 +1,198 @@
+import {getDefinitionName, mergeDocuments} from 'coral-framework/utils';
+import {getGraphQLExtensions} from 'coral-framework/helpers/plugins';
+import globalFragments from 'coral-framework/graphql/fragments';
+import uniq from 'lodash/uniq';
+
+const fragments = {};
+const mutationOptions = {};
+const queryOptions = {};
+
+const getTypeName = (ast) => ast.definitions[0].typeCondition.name.value;
+
+/**
+ * Add fragment
+ *
+ * Example:
+ * addFragment('MyFragment', gql`
+ * fragment Plugin_MyFragment on Comment {
+ * body
+ * }
+ * `);
+ */
+export function addFragment(key, document) {
+ const type = getTypeName(document);
+ const name = getDefinitionName(document);
+ if (!(key in fragments)) {
+ fragments[key] = {type, names: [name], documents: [document]};
+ } else {
+ if (type !== fragments[key].type) {
+ console.error(`Type mismatch ${type} !== ${fragments[key].type}`);
+ }
+ fragments[key].names.push(name);
+ fragments[key].documents.push(document);
+ }
+}
+
+/**
+ * Add mutation options.
+ *
+ * Example:
+ * // state is the current redux state, which is sometimes
+ * // necessary to fill the optimistic response.
+ * addMutationOptions('PostComment', ({variables, state}) => ({
+ * optimisticResponse: {
+ * CreateComment: {
+ * extra: '',
+ * },
+ * },
+ * refetchQueries: [],
+ * updateQueries: {
+ * EmbedQuery: (previous, data) => {
+ * return previous;
+ * },
+ * },
+ * update: (proxy, result) => {
+ * },
+ * })
+ */
+export function addMutationOptions(key, config) {
+ if (!(key in mutationOptions)) {
+ mutationOptions[key] = [config];
+ } else {
+ mutationOptions[key].push(config);
+ }
+}
+
+/**
+ * Add query options.
+ *
+ * Example:
+ * addQueryOptions('EmbedQuery', {
+ * reducer: (previousResult, action, variables) => previousResult,
+ * });
+ */
+export function addQueryOptions(key, config) {
+ if (!(key in queryOptions)) {
+ queryOptions[key] = [config];
+ } else {
+ queryOptions[key].push(config);
+ }
+}
+
+/**
+ * Add all fragments, mutation options, and query options defined in the object.
+ *
+ * Example:
+ * add({
+ * fragments: {
+ * CreateCommentResponse: gql`
+ * fragment CoralRandomEmoji_CreateCommentResponse on CreateCommentResponse {
+ * [...]
+ * }`,
+ * },
+ * mutations: {
+ * // state is the current redux state, which is sometimes
+ * // necessary to fill the optimistic response.
+ * PostComment: ({variables, state}) => ({
+ * optimisticResponse: {
+ * [...]
+ * },
+ * refetchQueries: [],
+ * updateQueries: {
+ * EmbedQuery: (previous, data) => {
+ * return previous;
+ * },
+ * },
+ * update: (proxy, result) => {
+ * },
+ * })
+ * },
+ * queries: {
+ * EmbedQuery: {
+ * reducer: (previousResult, action, variables) => {
+ * return previousResult;
+ * },
+ * },
+ * },
+ * });
+ */
+export function add(extension) {
+ Object.keys(extension.fragments || []).forEach(key => addFragment(key, extension.fragments[key]));
+ Object.keys(extension.mutations || []).forEach(key => addMutationOptions(key, extension.mutations[key]));
+ Object.keys(extension.queries || []).forEach(key => addQueryOptions(key, extension.queries[key]));
+}
+
+/**
+ * Get a list of mutation options.
+ */
+export function getMutationOptions(key) {
+ init();
+ return mutationOptions[key] || [];
+}
+
+/**
+ * Get a list of query options.
+ */
+export function getQueryOptions(key) {
+ init();
+ return queryOptions[key] || [];
+}
+
+/**
+ * Get a document with a fragment named `key`, which contains
+ * all fragments added under this key.
+ */
+export function getFragmentDocument(key) {
+ init();
+
+ if (!(key in fragments)) {
+ return '';
+ }
+
+ let documents = fragments[key] ? fragments[key].documents : [];
+ let fields = fragments[key] ? `...${fragments[key].names.join('\n...')}\n` : ' __typename';
+
+ // Assemble arguments for `gql` to call it directly without using template literals.
+ const main = `
+ fragment ${key} on ${fragments[key].type} {
+ ${fields}
+ }
+ `;
+ return mergeDocuments([main, ...documents]);
+}
+
+// The fragments and configs are lazily loaded to allow circular dependencies to work.
+// TODO: We might want to change this to an explicit add after we have lazy Queries and Mutations.
+let initialized = false;
+
+function init() {
+ if (initialized) { return; }
+ initialized = true;
+
+ // Add fragments from framework.
+ [globalFragments].forEach(map =>
+ Object.keys(map).forEach(key => addFragment(key, map[key]))
+ );
+
+ // Add configs from plugins.
+ getGraphQLExtensions().forEach(ext => add(ext));
+}
+
+export function resolveFragments(document) {
+ if (document.loc.source) {
+
+ // resolve fragments from registry
+ const matchedSubFragments = document.loc.source.body.match(/\.\.\.(.*)/g) || [];
+ const subFragments =
+ uniq(matchedSubFragments.map(f => f.replace('...', '')))
+ .map(key => getFragmentDocument(key))
+ .filter(i => i);
+
+ if (subFragments.length > 0) {
+ return mergeDocuments([document, ...subFragments]);
+ }
+ } else {
+ console.warn('Can only resolve fragments from documents definied using the gql tag.');
+ }
+ return document;
+}
diff --git a/client/coral-framework/utils/index.js b/client/coral-framework/utils/index.js
index 598fb59ab..70ce89bf7 100644
--- a/client/coral-framework/utils/index.js
+++ b/client/coral-framework/utils/index.js
@@ -1,3 +1,5 @@
+import {gql} from 'react-apollo';
+
export const getTotalActionCount = (type, comment) => {
return comment.action_summaries
.filter(s => s.__typename === type)
@@ -61,3 +63,11 @@ export function separateDataAndRoot(
root,
};
}
+
+export function mergeDocuments(documents) {
+ const main = typeof documents[0] === 'string' ? documents[0] : documents[0].loc.source.body;
+ const substitutions = documents.slice(1);
+ const literals = [main, ...substitutions.map(() => '\n')];
+ return gql.apply(null, [literals, ...substitutions]);
+}
+
diff --git a/client/coral-plugin-commentbox/CommentBox.js b/client/coral-plugin-commentbox/CommentBox.js
index e703a3058..34c08cc57 100644
--- a/client/coral-plugin-commentbox/CommentBox.js
+++ b/client/coral-plugin-commentbox/CommentBox.js
@@ -43,7 +43,7 @@ class CommentBox extends React.Component {
postComment = ({body}) => {
const {
commentPostedHandler,
- postItem,
+ postComment,
setCommentCountCache,
commentCountCache,
isReply,
@@ -64,7 +64,7 @@ class CommentBox extends React.Component {
// Execute preSubmit Hooks
this.state.hooks.preSubmit.forEach(hook => hook());
- postItem(comment, 'comments')
+ postComment(comment, 'comments')
.then(({data}) => {
const postedComment = data.createComment.comment;
@@ -181,7 +181,7 @@ CommentBox.propTypes = {
charCountEnable: PropTypes.bool.isRequired,
maxCharCount: PropTypes.number,
commentPostedHandler: PropTypes.func,
- postItem: PropTypes.func.isRequired,
+ postComment: PropTypes.func.isRequired,
cancelButtonClicked: PropTypes.func,
assetId: PropTypes.string.isRequired,
parentId: PropTypes.string,
diff --git a/client/coral-plugin-replies/ReplyBox.js b/client/coral-plugin-replies/ReplyBox.js
index d6e2b5631..97667f932 100644
--- a/client/coral-plugin-replies/ReplyBox.js
+++ b/client/coral-plugin-replies/ReplyBox.js
@@ -12,7 +12,7 @@ class ReplyBox extends Component {
render() {
const {
styles,
- postItem,
+ postComment,
assetId,
authorId,
addNotification,
@@ -32,7 +32,7 @@ class ReplyBox extends Component {
addNotification={addNotification}
authorId={authorId}
assetId={assetId}
- postItem={postItem}
+ postComment={postComment}
isReply={true} />
;
}
@@ -46,7 +46,7 @@ ReplyBox.propTypes = {
parentId: PropTypes.string,
addNotification: PropTypes.func.isRequired,
authorId: PropTypes.string.isRequired,
- postItem: PropTypes.func.isRequired,
+ postComment: PropTypes.func.isRequired,
assetId: PropTypes.string.isRequired
};
diff --git a/client/coral-settings/containers/ProfileContainer.js b/client/coral-settings/containers/ProfileContainer.js
index 39e615725..f9c8d892f 100644
--- a/client/coral-settings/containers/ProfileContainer.js
+++ b/client/coral-settings/containers/ProfileContainer.js
@@ -1,11 +1,10 @@
import {connect} from 'react-redux';
-import {compose} from 'react-apollo';
+import {compose, graphql, gql} from 'react-apollo';
import React, {Component} from 'react';
import I18n from 'coral-framework/modules/i18n/i18n';
import {bindActionCreators} from 'redux';
-import {myCommentHistory, myIgnoredUsers} from 'coral-framework/graphql/queries';
-import {stopIgnoringUser} from 'coral-framework/graphql/mutations';
+import {withStopIgnoringUser} from 'coral-framework/graphql/mutations';
import {link} from 'coral-framework/services/PymConnection';
import NotLoggedIn from '../components/NotLoggedIn';
@@ -88,6 +87,38 @@ class ProfileContainer extends Component {
}
}
+// TODO: These currently relies on refetching (see ignoreUser and stopIgnoringUser mutations).
+//
+const withMyIgnoredUsersQuery = graphql(gql`
+ query myIgnoredUsers {
+ myIgnoredUsers {
+ id,
+ username,
+ }
+ }`, {
+ props: ({data}) => {
+ return ({
+ myIgnoredUsersData: data
+ });
+ }
+ });
+
+const withMyCommentHistoryQuery = graphql(gql`
+ query myCommentHistory {
+ me {
+ comments {
+ id
+ body
+ asset {
+ id
+ title
+ url
+ }
+ created_at
+ }
+ }
+ }`);
+
const mapStateToProps = state => ({
user: state.user.toJS(),
asset: state.asset.toJS(),
@@ -99,7 +130,7 @@ const mapDispatchToProps = dispatch =>
export default compose(
connect(mapStateToProps, mapDispatchToProps),
- myCommentHistory,
- myIgnoredUsers,
- stopIgnoringUser,
+ withMyCommentHistoryQuery,
+ withMyIgnoredUsersQuery,
+ withStopIgnoringUser,
)(ProfileContainer);
diff --git a/plugins/coral-plugin-respect/client/containers/RespectButton.js b/plugins/coral-plugin-respect/client/containers/RespectButton.js
index 38be8a978..fcb7b2a57 100644
--- a/plugins/coral-plugin-respect/client/containers/RespectButton.js
+++ b/plugins/coral-plugin-respect/client/containers/RespectButton.js
@@ -1,15 +1,15 @@
-import {compose, gql, graphql} from 'react-apollo';
+import {compose, gql} from 'react-apollo';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import get from 'lodash/get';
-import withFragments from 'coral-framework/hocs/withFragments';
+import {withFragments, withMutation} from 'coral-framework/hocs';
import {showSignInDialog} from 'coral-framework/actions/auth';
import RespectButton from '../components/RespectButton';
const isRespectAction = (a) => a.__typename === 'RespectActionSummary';
const COMMENT_FRAGMENT = gql`
- fragment RespectButton_updateFragment on Comment {
+ fragment CoralRespect_UpdateFragment on Comment {
action_summaries {
... on RespectActionSummary {
count
@@ -21,8 +21,8 @@ const COMMENT_FRAGMENT = gql`
}
`;
-const withDeleteAction = graphql(gql`
- mutation deleteAction($id: ID!) {
+const withDeleteAction = withMutation(gql`
+ mutation CoralRespect_DeleteAction($id: ID!) {
deleteAction(id:$id) {
errors {
translation_key
@@ -66,8 +66,8 @@ const withDeleteAction = graphql(gql`
}),
});
-const withPostRespect = graphql(gql`
- mutation createRespect($respect: CreateRespectInput!) {
+const withPostRespect = withMutation(gql`
+ mutation CoralRespect_CreateRespect($respect: CreateRespectInput!) {
createRespect(respect: $respect) {
respect {
id
@@ -137,14 +137,14 @@ const mapDispatchToProps = dispatch =>
const enhance = compose(
withFragments({
root: gql`
- fragment RespectButton_root on RootQuery {
+ fragment CoralRespect_RespectButton_root on RootQuery {
me {
status
}
}
`,
comment: gql`
- fragment RespectButton_comment on Comment {
+ fragment CoralRespect_RespectButton_comment on Comment {
action_summaries {
... on RespectActionSummary {
count