Skip to content

Commit 7b01805

Browse files
committed
add mutation mock
1 parent 258266a commit 7b01805

File tree

4 files changed

+198
-6
lines changed

4 files changed

+198
-6
lines changed

package-lock.json

Lines changed: 34 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"apollo-link-schema": "^1.1.0",
1010
"graphql": "^0.13.2",
1111
"graphql-tag": "^2.9.2",
12+
"graphql-tools": "^3.0.1",
1213
"react": "^16.3.2",
1314
"react-apollo": "^2.1.4",
1415
"react-dom": "^16.3.2",

src/App.js

Lines changed: 102 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,124 @@
11
import React from 'react';
22
import gql from 'graphql-tag';
3-
import { Query } from 'react-apollo';
3+
import { Query, Mutation } from 'react-apollo';
44

55
import './App.css';
66

7-
const GET_ORGANIZATION = gql`
7+
const GET_REPOSITORIES_OF_ORGANIZATION = gql`
88
{
99
organization(login: "the-road-to-learn-react") {
10-
name
11-
url
10+
repositories(first: 20) {
11+
edges {
12+
node {
13+
id
14+
name
15+
url
16+
viewerHasStarred
17+
}
18+
}
19+
}
20+
}
21+
}
22+
`;
23+
24+
const STAR_REPOSITORY = gql`
25+
mutation($id: ID!) {
26+
addStar(input: { starrableId: $id }) {
27+
starrable {
28+
id
29+
viewerHasStarred
30+
}
1231
}
1332
}
1433
`;
1534

1635
const App = () => (
17-
<Query query={GET_ORGANIZATION}>
36+
<Query query={GET_REPOSITORIES_OF_ORGANIZATION}>
1837
{({ data: { organization }, loading }) => {
1938
if (loading || !organization) {
2039
return <div>Loading ...</div>;
2140
}
2241

23-
return <a href={organization.url}>{organization.name}</a>;
42+
return (
43+
<Repositories repositories={organization.repositories} />
44+
);
2445
}}
2546
</Query>
2647
);
2748

49+
class Repositories extends React.Component {
50+
state = {
51+
selectedRepositoryIds: [],
52+
};
53+
54+
toggleSelectRepository = (id, isSelected) => {
55+
let { selectedRepositoryIds } = this.state;
56+
57+
selectedRepositoryIds = isSelected
58+
? selectedRepositoryIds.filter(itemId => itemId !== id)
59+
: selectedRepositoryIds.concat(id);
60+
61+
this.setState({ selectedRepositoryIds });
62+
};
63+
64+
render() {
65+
return (
66+
<RepositoryList
67+
repositories={this.props.repositories}
68+
selectedRepositoryIds={this.state.selectedRepositoryIds}
69+
toggleSelectRepository={this.toggleSelectRepository}
70+
/>
71+
);
72+
}
73+
}
74+
75+
const RepositoryList = ({
76+
repositories,
77+
selectedRepositoryIds,
78+
toggleSelectRepository,
79+
}) => (
80+
<ul>
81+
{repositories.edges.map(({ node }) => {
82+
const isSelected = selectedRepositoryIds.includes(node.id);
83+
84+
const rowClassName = ['row'];
85+
86+
if (isSelected) {
87+
rowClassName.push('row_selected');
88+
}
89+
90+
return (
91+
<li className={rowClassName.join(' ')} key={node.id}>
92+
<Select
93+
id={node.id}
94+
isSelected={isSelected}
95+
toggleSelectRepository={toggleSelectRepository}
96+
/>{' '}
97+
<a href={node.url}>{node.name}</a>{' '}
98+
{!node.viewerHasStarred && <Star id={node.id} />}
99+
</li>
100+
);
101+
})}
102+
</ul>
103+
);
104+
105+
const Star = ({ id }) => (
106+
<Mutation mutation={STAR_REPOSITORY} variables={{ id }}>
107+
{starRepository => (
108+
<button type="button" onClick={starRepository}>
109+
Star
110+
</button>
111+
)}
112+
</Mutation>
113+
);
114+
115+
const Select = ({ id, isSelected, toggleSelectRepository }) => (
116+
<button
117+
type="button"
118+
onClick={() => toggleSelectRepository(id, isSelected)}
119+
>
120+
{isSelected ? 'Unselect' : 'Select'}
121+
</button>
122+
);
123+
28124
export default App;

src/schema.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,75 @@ export const typeDefs = `
66
type Organization {
77
name: String!
88
url: String!
9+
repositories: RepositoryConnection!
10+
}
11+
12+
type RepositoryConnection {
13+
edges: [RepositoryEdge!]!
14+
}
15+
16+
type RepositoryEdge {
17+
node: Repository!
18+
}
19+
20+
type Repository {
21+
id: String!
22+
name: String!
23+
url: String!
24+
viewerHasStarred: Boolean!
25+
}
26+
27+
type Mutation {
28+
addStar(input: AddStarInput!): AddStarResult!
29+
}
30+
31+
input AddStarInput {
32+
starrableId: ID!
33+
}
34+
35+
type AddStarResult {
36+
starrable: Starrable!
37+
}
38+
39+
type Starrable {
40+
id: ID!
41+
viewerHasStarred: Boolean!
942
}
1043
`;
1144

1245
export const resolvers = {
46+
Mutation: {
47+
addStar: (parent, { input }) => ({
48+
starrable: {
49+
id: input.starrableId,
50+
viewerHasStarred: true,
51+
},
52+
}),
53+
},
1354
Query: {
1455
organization: (parent, { login }) => ({
1556
name: login,
1657
url: `https://github.com/${login}`,
58+
repositories: {
59+
edges: [
60+
{
61+
node: {
62+
id: '1',
63+
name: 'the-road-to-learn-react',
64+
url: `https://github.com/${login}/the-road-to-learn-react`,
65+
viewerHasStarred: false,
66+
},
67+
},
68+
{
69+
node: {
70+
id: '2',
71+
name: 'the-road-to-learn-react-chinese',
72+
url: `https://github.com/${login}/the-road-to-learn-react-chinese`,
73+
viewerHasStarred: false,
74+
},
75+
},
76+
],
77+
},
1778
}),
1879
},
1980
};

0 commit comments

Comments
 (0)