decidim-comments 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +33 -0
- data/app/assets/javascripts/decidim/comments/bundle.js +44 -44
- data/app/assets/javascripts/decidim/comments/bundle.js.map +1 -1
- data/app/assets/javascripts/decidim/comments/comments.js.erb +2 -0
- data/app/frontend/application/{apollo_client.js → apollo_client.ts} +5 -5
- data/app/frontend/application/application.component.test.tsx +36 -0
- data/app/frontend/application/application.component.tsx +37 -0
- data/app/frontend/application/icon.component.test.tsx +49 -0
- data/app/frontend/application/icon.component.tsx +35 -0
- data/app/frontend/comments/{add_comment_form.component.test.jsx → add_comment_form.component.test.tsx} +98 -92
- data/app/frontend/comments/{add_comment_form.component.jsx → add_comment_form.component.tsx} +152 -153
- data/app/frontend/comments/{comment.component.test.jsx → comment.component.test.tsx} +59 -71
- data/app/frontend/comments/{comment.component.jsx → comment.component.tsx} +114 -116
- data/app/frontend/comments/comment_order_selector.component.test.tsx +21 -0
- data/app/frontend/comments/comment_order_selector.component.tsx +88 -0
- data/app/frontend/comments/comment_thread.component.test.tsx +65 -0
- data/app/frontend/comments/comment_thread.component.tsx +70 -0
- data/app/frontend/comments/{comments.component.test.jsx → comments.component.test.tsx} +38 -81
- data/app/frontend/comments/{comments.component.jsx → comments.component.tsx} +49 -63
- data/app/frontend/comments/down_vote_button.component.test.tsx +39 -0
- data/app/frontend/comments/down_vote_button.component.tsx +89 -0
- data/app/frontend/comments/up_vote_button.component.test.tsx +39 -0
- data/app/frontend/comments/up_vote_button.component.tsx +89 -0
- data/app/frontend/comments/vote_button.component.tsx +36 -0
- data/app/frontend/comments/{vote_button_component.test.jsx → vote_button_component.test.tsx} +16 -20
- data/app/frontend/entry.ts +19 -0
- data/app/frontend/{comments → fragments}/add_comment_form_commentable.fragment.graphql +1 -1
- data/app/frontend/{comments → fragments}/add_comment_form_session.fragment.graphql +1 -1
- data/app/frontend/{comments → fragments}/comment.fragment.graphql +3 -1
- data/app/frontend/{comments → fragments}/comment_data.fragment.graphql +6 -3
- data/app/frontend/{comments → fragments}/comment_thread.fragment.graphql +3 -1
- data/app/frontend/{comments/down_vote.fragment.graphql → fragments/down_vote_button.fragment.graphql} +2 -2
- data/app/frontend/{comments/up_vote.fragment.graphql → fragments/up_vote_button.fragment.graphql} +2 -2
- data/app/frontend/{comments/add_comment_form.mutation.graphql → mutations/add_comment.mutation.graphql} +3 -1
- data/app/frontend/{comments → mutations}/down_vote.mutation.graphql +3 -1
- data/app/frontend/{comments → mutations}/up_vote.mutation.graphql +3 -1
- data/app/frontend/{comments → queries}/comments.query.graphql +4 -1
- data/app/frontend/support/{asset_url.js → asset_url.ts} +1 -1
- data/app/frontend/support/{generate_comments_data.js → generate_comments_data.ts} +11 -6
- data/app/frontend/support/{generate_user_data.js → generate_user_data.ts} +2 -2
- data/app/frontend/support/{generate_user_group_data.js → generate_user_group_data.ts} +2 -2
- data/app/frontend/support/graphql_transformer.js +32 -0
- data/app/frontend/support/load_translations.ts +44 -0
- data/app/frontend/support/{require_all.js → require_all.ts} +1 -1
- data/app/frontend/support/{resolve_graphql_query.js → resolve_graphql_query.ts} +7 -7
- data/app/frontend/support/schema.ts +119 -0
- data/config/locales/eu.yml +29 -5
- metadata +49 -51
- data/app/frontend/application/application.component.jsx +0 -37
- data/app/frontend/application/application.component.test.jsx +0 -33
- data/app/frontend/application/icon.component.jsx +0 -26
- data/app/frontend/application/icon.component.test.jsx +0 -53
- data/app/frontend/comments/comment_order_selector.component.jsx +0 -72
- data/app/frontend/comments/comment_order_selector.component.test.jsx +0 -20
- data/app/frontend/comments/comment_thread.component.jsx +0 -75
- data/app/frontend/comments/comment_thread.component.test.jsx +0 -83
- data/app/frontend/comments/down_vote_button.component.jsx +0 -98
- data/app/frontend/comments/down_vote_button.component.test.jsx +0 -48
- data/app/frontend/comments/featured_comment.component.jsx +0 -23
- data/app/frontend/comments/featured_comment.component.test.jsx +0 -15
- data/app/frontend/comments/up_vote_button.component.jsx +0 -98
- data/app/frontend/comments/up_vote_button.component.test.jsx +0 -48
- data/app/frontend/comments/vote_button.component.jsx +0 -32
- data/app/frontend/entry.js +0 -17
- data/app/frontend/entry.test.js +0 -31
- data/app/frontend/support/load_translations.js +0 -23
- data/app/frontend/support/stub_component.js +0 -29
@@ -1,16 +1,24 @@
|
|
1
|
-
import
|
2
|
-
import { graphql }
|
3
|
-
import gql from 'graphql-tag';
|
4
|
-
import { filter } from 'graphql-anywhere';
|
5
|
-
import { I18n } from 'react-i18nify';
|
1
|
+
import * as React from "react";
|
2
|
+
import { graphql } from "react-apollo";
|
6
3
|
|
7
|
-
import Application
|
4
|
+
import Application from "../application/application.component";
|
8
5
|
|
9
|
-
import
|
10
|
-
import
|
11
|
-
import
|
6
|
+
import AddCommentForm from "./add_comment_form.component";
|
7
|
+
import CommentOrderSelector from "./comment_order_selector.component";
|
8
|
+
import CommentThread from "./comment_thread.component";
|
12
9
|
|
13
|
-
import
|
10
|
+
import {
|
11
|
+
GetCommentsQuery,
|
12
|
+
GetCommentsQueryVariables,
|
13
|
+
} from "../support/schema";
|
14
|
+
|
15
|
+
const { I18n } = require("react-i18nify");
|
16
|
+
|
17
|
+
interface CommentsProps extends GetCommentsQuery {
|
18
|
+
loading?: boolean;
|
19
|
+
orderBy: string;
|
20
|
+
reorderComments: (orderBy: string) => void;
|
21
|
+
};
|
14
22
|
|
15
23
|
/**
|
16
24
|
* The core class of the Decidim Comments engine.
|
@@ -19,14 +27,22 @@ import commentsQuery from './comments.query.graphql';
|
|
19
27
|
* @class
|
20
28
|
* @augments Component
|
21
29
|
*/
|
22
|
-
export class Comments extends Component {
|
23
|
-
|
30
|
+
export class Comments extends React.Component<CommentsProps, undefined> {
|
31
|
+
public static defaultProps: any = {
|
32
|
+
loading: false,
|
33
|
+
session: null,
|
34
|
+
commentable: {
|
35
|
+
comments: [],
|
36
|
+
},
|
37
|
+
};
|
38
|
+
|
39
|
+
public render() {
|
24
40
|
const { commentable: { comments }, reorderComments, orderBy, loading } = this.props;
|
25
41
|
let commentClasses = "comments";
|
26
42
|
let commentHeader = I18n.t("components.comments.title", { count: comments.length });
|
27
43
|
|
28
44
|
if (loading) {
|
29
|
-
commentClasses += " loading-comments"
|
45
|
+
commentClasses += " loading-comments";
|
30
46
|
commentHeader = I18n.t("components.comments.loading");
|
31
47
|
}
|
32
48
|
|
@@ -35,7 +51,7 @@ export class Comments extends Component {
|
|
35
51
|
<section className={commentClasses}>
|
36
52
|
<div className="row collapse order-by">
|
37
53
|
<h2 className="order-by__text section-heading">
|
38
|
-
{
|
54
|
+
{commentHeader}
|
39
55
|
</h2>
|
40
56
|
<CommentOrderSelector
|
41
57
|
reorderComments={reorderComments}
|
@@ -55,13 +71,13 @@ export class Comments extends Component {
|
|
55
71
|
* @private
|
56
72
|
* @returns {Void|DOMElement} - A warning message or nothing.
|
57
73
|
*/
|
58
|
-
_renderBlockedCommentsWarning() {
|
74
|
+
private _renderBlockedCommentsWarning() {
|
59
75
|
const { commentable: { acceptsNewComments } } = this.props;
|
60
76
|
|
61
77
|
if (!acceptsNewComments) {
|
62
78
|
return (
|
63
79
|
<div className="callout warning">
|
64
|
-
<p>{
|
80
|
+
<p>{I18n.t("components.comments.blocked_comments_warning")}</p>
|
65
81
|
</div>
|
66
82
|
);
|
67
83
|
}
|
@@ -74,17 +90,17 @@ export class Comments extends Component {
|
|
74
90
|
* @private
|
75
91
|
* @returns {ReactComponent[]} - A collection of CommentThread components
|
76
92
|
*/
|
77
|
-
_renderCommentThreads() {
|
93
|
+
private _renderCommentThreads() {
|
78
94
|
const { session, commentable: { comments, commentsHaveVotes } } = this.props;
|
79
95
|
|
80
96
|
return comments.map((comment) => (
|
81
97
|
<CommentThread
|
82
98
|
key={comment.id}
|
83
|
-
comment={
|
99
|
+
comment={comment}
|
84
100
|
session={session}
|
85
101
|
votable={commentsHaveVotes}
|
86
102
|
/>
|
87
|
-
))
|
103
|
+
));
|
88
104
|
}
|
89
105
|
|
90
106
|
/**
|
@@ -92,7 +108,7 @@ export class Comments extends Component {
|
|
92
108
|
* @private
|
93
109
|
* @returns {Void|ReactComponent} - A AddCommentForm component or nothing
|
94
110
|
*/
|
95
|
-
_renderAddCommentForm() {
|
111
|
+
private _renderAddCommentForm() {
|
96
112
|
const { session, commentable } = this.props;
|
97
113
|
const { acceptsNewComments, commentsHaveAlignment } = commentable;
|
98
114
|
|
@@ -110,31 +126,6 @@ export class Comments extends Component {
|
|
110
126
|
}
|
111
127
|
}
|
112
128
|
|
113
|
-
Comments.propTypes = {
|
114
|
-
loading: PropTypes.bool,
|
115
|
-
session: PropTypes.shape({
|
116
|
-
user: PropTypes.any.isRequired
|
117
|
-
}),
|
118
|
-
commentable: PropTypes.shape({
|
119
|
-
acceptsNewComments: PropTypes.bool,
|
120
|
-
commentsHaveAlignment: PropTypes.bool,
|
121
|
-
commentsHaveVotes: PropTypes.bool,
|
122
|
-
comments: PropTypes.arrayOf(PropTypes.shape({
|
123
|
-
id: PropTypes.string.isRequired
|
124
|
-
}))
|
125
|
-
}),
|
126
|
-
orderBy: PropTypes.string.isRequired,
|
127
|
-
reorderComments: PropTypes.func.isRequired
|
128
|
-
};
|
129
|
-
|
130
|
-
Comments.defaultProps = {
|
131
|
-
loading: false,
|
132
|
-
session: null,
|
133
|
-
commentable: {
|
134
|
-
comments: []
|
135
|
-
}
|
136
|
-
};
|
137
|
-
|
138
129
|
/**
|
139
130
|
* Wrap the Comments component with a GraphQL query and children
|
140
131
|
* fragments.
|
@@ -142,34 +133,35 @@ Comments.defaultProps = {
|
|
142
133
|
|
143
134
|
window.Comments = Comments;
|
144
135
|
|
145
|
-
const
|
146
|
-
|
147
|
-
|
148
|
-
${AddCommentForm.fragments.commentable}
|
149
|
-
${CommentThread.fragments.comment}
|
150
|
-
`, {
|
136
|
+
export const commentsQuery = require("../queries/comments.query.graphql");
|
137
|
+
|
138
|
+
const CommentsWithData: any = graphql(commentsQuery, {
|
151
139
|
options: {
|
152
|
-
pollInterval: 15000
|
140
|
+
pollInterval: 15000,
|
153
141
|
},
|
154
142
|
props: ({ ownProps, data: { loading, session, commentable, refetch }}) => ({
|
155
143
|
loading,
|
156
144
|
session,
|
157
145
|
commentable,
|
158
146
|
orderBy: ownProps.orderBy,
|
159
|
-
reorderComments: (orderBy) => {
|
147
|
+
reorderComments: (orderBy: string) => {
|
160
148
|
return refetch({
|
161
|
-
orderBy
|
149
|
+
orderBy,
|
162
150
|
});
|
163
|
-
}
|
164
|
-
})
|
151
|
+
},
|
152
|
+
}),
|
165
153
|
})(Comments);
|
166
154
|
|
155
|
+
export interface CommentsApplicationProps extends GetCommentsQueryVariables {
|
156
|
+
locale: string;
|
157
|
+
}
|
158
|
+
|
167
159
|
/**
|
168
160
|
* Wrap the CommentsWithData component within an Application component to
|
169
161
|
* connect it with Apollo client and store.
|
170
162
|
* @returns {ReactComponent} - A component wrapped within an Application component
|
171
163
|
*/
|
172
|
-
const CommentsApplication = ({ locale, commentableId, commentableType }) => (
|
164
|
+
const CommentsApplication: React.SFC<CommentsApplicationProps> = ({ locale, commentableId, commentableType }) => (
|
173
165
|
<Application locale={locale}>
|
174
166
|
<CommentsWithData
|
175
167
|
commentableId={commentableId}
|
@@ -179,10 +171,4 @@ const CommentsApplication = ({ locale, commentableId, commentableType }) => (
|
|
179
171
|
</Application>
|
180
172
|
);
|
181
173
|
|
182
|
-
CommentsApplication.propTypes = {
|
183
|
-
locale: PropTypes.string.isRequired,
|
184
|
-
commentableId: PropTypes.string.isRequired,
|
185
|
-
commentableType: PropTypes.string.isRequired
|
186
|
-
};
|
187
|
-
|
188
174
|
export default CommentsApplication;
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import { shallow } from "enzyme";
|
2
|
+
import * as React from "react";
|
3
|
+
|
4
|
+
import { DownVoteButton } from "./down_vote_button.component";
|
5
|
+
import VoteButton from "./vote_button.component";
|
6
|
+
|
7
|
+
import generateCommentsData from "../support/generate_comments_data";
|
8
|
+
|
9
|
+
import { DownVoteFragment } from "../support/schema";
|
10
|
+
|
11
|
+
describe("<DownVoteButton />", () => {
|
12
|
+
let comment: DownVoteFragment;
|
13
|
+
const downVote = jasmine.createSpy("downVote");
|
14
|
+
|
15
|
+
beforeEach(() => {
|
16
|
+
let commentsData = generateCommentsData(1);
|
17
|
+
|
18
|
+
comment = commentsData[0];
|
19
|
+
});
|
20
|
+
|
21
|
+
it("should render a VoteButton component with the correct props", () => {
|
22
|
+
const wrapper = shallow(<DownVoteButton comment={comment} downVote={downVote} />);
|
23
|
+
expect(wrapper.find(VoteButton).prop("buttonClassName")).toEqual("comment__votes--down");
|
24
|
+
expect(wrapper.find(VoteButton).prop("iconName")).toEqual("icon-chevron-bottom");
|
25
|
+
expect(wrapper.find(VoteButton).prop("votes")).toEqual(comment.downVotes);
|
26
|
+
});
|
27
|
+
|
28
|
+
it("should pass disabled prop as true if comment downVoted is true", () => {
|
29
|
+
comment.downVoted = true;
|
30
|
+
const wrapper = shallow(<DownVoteButton comment={comment} downVote={downVote} />);
|
31
|
+
expect(wrapper.find(VoteButton).prop("disabled")).toBeTruthy();
|
32
|
+
});
|
33
|
+
|
34
|
+
it("should pass disabled prop as true if comment downVoted is true", () => {
|
35
|
+
comment.downVoted = true;
|
36
|
+
const wrapper = shallow(<DownVoteButton comment={comment} downVote={downVote} />);
|
37
|
+
expect(wrapper.find(VoteButton).prop("disabled")).toBeTruthy();
|
38
|
+
});
|
39
|
+
});
|
@@ -0,0 +1,89 @@
|
|
1
|
+
import * as React from "react";
|
2
|
+
import { graphql } from "react-apollo";
|
3
|
+
|
4
|
+
import VoteButton from "./vote_button.component";
|
5
|
+
|
6
|
+
import {
|
7
|
+
CommentFragment,
|
8
|
+
DownVoteFragment,
|
9
|
+
DownVoteMutation,
|
10
|
+
GetCommentsQuery,
|
11
|
+
} from "../support/schema";
|
12
|
+
|
13
|
+
interface DownVoteButtonProps {
|
14
|
+
comment: DownVoteFragment;
|
15
|
+
downVote?: () => void;
|
16
|
+
}
|
17
|
+
|
18
|
+
export const DownVoteButton: React.SFC<DownVoteButtonProps> = ({
|
19
|
+
comment: { downVotes, upVoted, downVoted },
|
20
|
+
downVote,
|
21
|
+
}) => {
|
22
|
+
let selectedClass = "";
|
23
|
+
|
24
|
+
if (downVoted) {
|
25
|
+
selectedClass = "is-vote-selected";
|
26
|
+
} else if (upVoted) {
|
27
|
+
selectedClass = "is-vote-notselected";
|
28
|
+
}
|
29
|
+
|
30
|
+
return (
|
31
|
+
<VoteButton
|
32
|
+
buttonClassName="comment__votes--down"
|
33
|
+
iconName="icon-chevron-bottom"
|
34
|
+
votes={downVotes}
|
35
|
+
voteAction={downVote}
|
36
|
+
disabled={upVoted || downVoted}
|
37
|
+
selectedClass={selectedClass}
|
38
|
+
/>
|
39
|
+
);
|
40
|
+
};
|
41
|
+
|
42
|
+
const downVoteMutation = require("../mutations/down_vote.mutation.graphql");
|
43
|
+
|
44
|
+
const DownVoteButtonWithMutation = graphql(downVoteMutation, {
|
45
|
+
props: ({ ownProps, mutate }) => ({
|
46
|
+
downVote: () => mutate({
|
47
|
+
variables: {
|
48
|
+
id: ownProps.comment.id,
|
49
|
+
},
|
50
|
+
optimisticResponse: {
|
51
|
+
__typename: "Mutation",
|
52
|
+
comment: {
|
53
|
+
__typename: "CommentMutation",
|
54
|
+
downVote: {
|
55
|
+
__typename: "Comment",
|
56
|
+
...ownProps.comment,
|
57
|
+
downVotes: ownProps.comment.downVotes + 1,
|
58
|
+
downVoted: true,
|
59
|
+
},
|
60
|
+
},
|
61
|
+
},
|
62
|
+
updateQueries: {
|
63
|
+
GetComments: (prev: GetCommentsQuery, { mutationResult: { data } }: { mutationResult: { data: DownVoteMutation }}) => {
|
64
|
+
const commentReducer = (comment: CommentFragment): CommentFragment => {
|
65
|
+
const replies = comment.comments || [];
|
66
|
+
|
67
|
+
if (comment.id === ownProps.comment.id && data.comment) {
|
68
|
+
return data.comment.downVote;
|
69
|
+
}
|
70
|
+
return {
|
71
|
+
...comment,
|
72
|
+
comments: replies.map(commentReducer),
|
73
|
+
};
|
74
|
+
};
|
75
|
+
|
76
|
+
return {
|
77
|
+
...prev,
|
78
|
+
commentable: {
|
79
|
+
...prev.commentable,
|
80
|
+
comments: prev.commentable.comments.map(commentReducer),
|
81
|
+
},
|
82
|
+
};
|
83
|
+
},
|
84
|
+
},
|
85
|
+
}),
|
86
|
+
}),
|
87
|
+
})(DownVoteButton);
|
88
|
+
|
89
|
+
export default DownVoteButtonWithMutation;
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import { shallow } from "enzyme";
|
2
|
+
import * as React from "react";
|
3
|
+
|
4
|
+
import { UpVoteButton } from "./up_vote_button.component";
|
5
|
+
import VoteButton from "./vote_button.component";
|
6
|
+
|
7
|
+
import generateCommentsData from "../support/generate_comments_data";
|
8
|
+
|
9
|
+
import { UpVoteFragment } from "../support/schema";
|
10
|
+
|
11
|
+
describe("<UpVoteButton />", () => {
|
12
|
+
let comment: UpVoteFragment;
|
13
|
+
const upVote = jasmine.createSpy("upVote");
|
14
|
+
|
15
|
+
beforeEach(() => {
|
16
|
+
let commentsData = generateCommentsData(1);
|
17
|
+
|
18
|
+
comment = commentsData[0];
|
19
|
+
});
|
20
|
+
|
21
|
+
it("should render a VoteButton component with the correct props", () => {
|
22
|
+
const wrapper = shallow(<UpVoteButton comment={comment} upVote={upVote} />);
|
23
|
+
expect(wrapper.find(VoteButton).prop("buttonClassName")).toEqual("comment__votes--up");
|
24
|
+
expect(wrapper.find(VoteButton).prop("iconName")).toEqual("icon-chevron-top");
|
25
|
+
expect(wrapper.find(VoteButton).prop("votes")).toEqual(comment.upVotes);
|
26
|
+
});
|
27
|
+
|
28
|
+
it("should pass disabled prop as true if comment upVoted is true", () => {
|
29
|
+
comment.upVoted = true;
|
30
|
+
const wrapper = shallow(<UpVoteButton comment={comment} upVote={upVote} />);
|
31
|
+
expect(wrapper.find(VoteButton).prop("disabled")).toBeTruthy();
|
32
|
+
});
|
33
|
+
|
34
|
+
it("should pass disabled prop as true if comment downVoted is true", () => {
|
35
|
+
comment.downVoted = true;
|
36
|
+
const wrapper = shallow(<UpVoteButton comment={comment} upVote={upVote} />);
|
37
|
+
expect(wrapper.find(VoteButton).prop("disabled")).toBeTruthy();
|
38
|
+
});
|
39
|
+
});
|
@@ -0,0 +1,89 @@
|
|
1
|
+
import * as React from "react";
|
2
|
+
import { graphql } from "react-apollo";
|
3
|
+
|
4
|
+
import VoteButton from "./vote_button.component";
|
5
|
+
|
6
|
+
import {
|
7
|
+
CommentFragment,
|
8
|
+
GetCommentsQuery,
|
9
|
+
UpVoteFragment,
|
10
|
+
UpVoteMutation,
|
11
|
+
} from "../support/schema";
|
12
|
+
|
13
|
+
interface UpVoteButtonProps {
|
14
|
+
comment: UpVoteFragment;
|
15
|
+
upVote?: () => void;
|
16
|
+
}
|
17
|
+
|
18
|
+
export const UpVoteButton: React.SFC<UpVoteButtonProps> = ({
|
19
|
+
comment: { upVotes, upVoted, downVoted },
|
20
|
+
upVote,
|
21
|
+
}) => {
|
22
|
+
let selectedClass = "";
|
23
|
+
|
24
|
+
if (upVoted) {
|
25
|
+
selectedClass = "is-vote-selected";
|
26
|
+
} else if (downVoted) {
|
27
|
+
selectedClass = "is-vote-notselected";
|
28
|
+
}
|
29
|
+
|
30
|
+
return (
|
31
|
+
<VoteButton
|
32
|
+
buttonClassName="comment__votes--up"
|
33
|
+
iconName="icon-chevron-top"
|
34
|
+
votes={upVotes}
|
35
|
+
voteAction={upVote}
|
36
|
+
disabled={upVoted || downVoted}
|
37
|
+
selectedClass={selectedClass}
|
38
|
+
/>
|
39
|
+
);
|
40
|
+
};
|
41
|
+
|
42
|
+
const upVoteMutation = require("../mutations/up_vote.mutation.graphql");
|
43
|
+
|
44
|
+
const UpVoteButtonWithMutation = graphql(upVoteMutation, {
|
45
|
+
props: ({ ownProps, mutate }) => ({
|
46
|
+
upVote: () => mutate({
|
47
|
+
variables: {
|
48
|
+
id: ownProps.comment.id,
|
49
|
+
},
|
50
|
+
optimisticResponse: {
|
51
|
+
__typename: "Mutation",
|
52
|
+
comment: {
|
53
|
+
__typename: "CommentMutation",
|
54
|
+
upVote: {
|
55
|
+
__typename: "Comment",
|
56
|
+
...ownProps.comment,
|
57
|
+
upVotes: ownProps.comment.upVotes + 1,
|
58
|
+
upVoted: true,
|
59
|
+
},
|
60
|
+
},
|
61
|
+
},
|
62
|
+
updateQueries: {
|
63
|
+
GetComments: (prev: GetCommentsQuery, { mutationResult: { data } }: { mutationResult: { data: UpVoteMutation}}) => {
|
64
|
+
const commentReducer = (comment: CommentFragment): CommentFragment => {
|
65
|
+
const replies = comment.comments || [];
|
66
|
+
|
67
|
+
if (comment.id === ownProps.comment.id && data.comment) {
|
68
|
+
return data.comment.upVote;
|
69
|
+
}
|
70
|
+
return {
|
71
|
+
...comment,
|
72
|
+
comments: replies.map(commentReducer),
|
73
|
+
};
|
74
|
+
};
|
75
|
+
|
76
|
+
return {
|
77
|
+
...prev,
|
78
|
+
commentable: {
|
79
|
+
...prev.commentable,
|
80
|
+
comments: prev.commentable.comments.map(commentReducer),
|
81
|
+
},
|
82
|
+
};
|
83
|
+
},
|
84
|
+
},
|
85
|
+
}),
|
86
|
+
}),
|
87
|
+
})(UpVoteButton);
|
88
|
+
|
89
|
+
export default UpVoteButtonWithMutation;
|