├── .gitignore
├── LICENSE
├── README.md
├── config.go
├── db_logic.go
├── db_main.go
├── db_struct.go
├── go.mod
├── go.sum
├── gql_logic.go
├── gql_schema.go
├── gql_struct.go
├── main.go
├── public
├── asset-manifest.json
├── favicon.ico
├── index.html
├── manifest.json
├── precache-manifest.322cc1a0981814470fa95698ad009295.js
├── service-worker.js
└── static
│ ├── css
│ ├── main.e344f020.chunk.css
│ └── main.e344f020.chunk.css.map
│ └── js
│ ├── 2.3cd3ed05.chunk.js
│ ├── 2.3cd3ed05.chunk.js.map
│ ├── main.ef6f36c7.chunk.js
│ ├── main.ef6f36c7.chunk.js.map
│ ├── runtime~main.a8a9905a.js
│ └── runtime~main.a8a9905a.js.map
├── sec_http.go
├── sec_password.go
├── sec_token.go
└── util.go
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, build with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Jonathan Hecl
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Golang+GraphQL+MongoDB Server 1.0.0
2 |
3 | Uses the following packages:
4 | - go.mongodb.org/mongo-driver/mongo - MongoDB Driver API
5 | - github.com/graphql-go/graphql - GraphQL
6 | - github.com/dgrijalva/jwt-go - JSON Web Tokens (JWT)
7 | - golang.org/x/crypto/bcrypt - Package bcrypt
8 |
9 | # Features!
10 |
11 | - Authorization Header
12 | - SignUp/SignIn users
13 | - Users Profiles
14 | - List recipes
15 | - Recipe pages
16 | - Add/Edit/Delete recipes
17 | - Like/Unlike recipes
18 |
19 | ### Config.go file
20 |
21 | ```
22 | var config = configModel{
23 | mongoUri: "mongodb://admin:admin@localhost:37812/react-recipes", // Mongo Uri
24 | mongoDb: "react-recipes", // DB name
25 | tokenSecret: "secret", // Secret to use in Tokens
26 | tokenExp: "1h", // Expiration of Token
27 | serveUri: ":4444", // Serve
28 | }
29 | ```
30 |
31 | ### Models
32 |
33 | #### Recipe
34 |
35 | |key|type|
36 | |-|-|
37 | |_id|ID|
38 | |name|string|
39 | |imageUrl|string|
40 | |category|string|
41 | |description|string|
42 | |instructions|string|
43 | |createdDate|unixtime|
44 | |likes|int|
45 | |username|string|
46 |
47 | #### User
48 |
49 | |key|type|
50 | |-|-|
51 | |_id|ID|
52 | |username|string|
53 | |password|string|
54 | |email|string|
55 | |joinDate|unixtime|
56 | |favorites|array[Recipe]|
57 |
58 | ### GraphQL
59 |
60 | #### getAllRecipes
61 | ```
62 | {
63 | getAllRecipes {
64 | ...MinimalRecipe
65 | }
66 | }
67 |
68 | fragment MinimalRecipe on Recipe {
69 | _id
70 | name
71 | imageUrl
72 | category
73 | }
74 | ```
75 |
76 | #### searchRecipes
77 | ```
78 | query ($searchTerm: String) {
79 | searchRecipes(searchTerm: $searchTerm) {
80 | _id
81 | name
82 | likes
83 | }
84 | }
85 | ```
86 |
87 | #### getRecipe
88 | ```
89 | query ($_id: ID!) {
90 | getRecipe(_id: $_id) {
91 | ...CompleteRecipe
92 | }
93 | }
94 |
95 | fragment CompleteRecipe on Recipe {
96 | _id
97 | name
98 | imageUrl
99 | category
100 | description
101 | instructions
102 | createdDate
103 | likes
104 | username
105 | }
106 | ```
107 |
108 | #### signupUser
109 | ```
110 | mutation ($username: String!, $email: String!, $password: String!) {
111 | signupUser(username: $username, email: $email, password: $password) {
112 | token
113 | }
114 | }
115 | ```
116 |
117 | #### signinUser
118 | ```
119 | mutation ($username: String!, $password: String!) {
120 | signinUser(username: $username, password: $password) {
121 | token
122 | }
123 | }
124 | ```
125 |
126 | #### getCurrentUser (require authorization header)
127 | ```
128 | {
129 | getCurrentUser {
130 | username
131 | joinDate
132 | email
133 | favorites {
134 | _id
135 | name
136 | }
137 | }
138 | }
139 | ```
140 |
141 | #### addRecipe (require authorization header)
142 | _username not used, obtained by Token Authorization._
143 | ```
144 | mutation ($name: String!, $imageUrl: String!, $category: String!, $description: String!, $instructions: String!, $username: String) {
145 | addRecipe(name: $name, imageUrl: $imageUrl, category: $category, description: $description, instructions: $instructions, username: $username) {
146 | ...MinimalRecipe
147 | }
148 | }
149 |
150 | fragment MinimalRecipe on Recipe {
151 | _id
152 | name
153 | imageUrl
154 | category
155 | }
156 |
157 | ```
158 |
159 | #### updateUserRecipe (require authorization header)
160 | ```
161 | mutation ($_id: ID!, $name: String!, $imageUrl: String!, $category: String!, $description: String!, $instructions: String!) {
162 | updateUserRecipe(_id: $_id, name: $name, imageUrl: $imageUrl, category: $category, description: $description, instructions: $instructions) {
163 | ...CompleteRecipe
164 | }
165 | }
166 |
167 | fragment CompleteRecipe on Recipe {
168 | _id
169 | name
170 | imageUrl
171 | category
172 | description
173 | instructions
174 | createdDate
175 | likes
176 | username
177 | }
178 | ```
179 |
180 | #### getUserRecipe (require authorization header)
181 | ```
182 | query ($username: String!) {
183 | getUserRecipes(username: $username) {
184 | ...CompleteRecipe
185 | }
186 | }
187 |
188 | fragment CompleteRecipe on Recipe {
189 | _id
190 | name
191 | imageUrl
192 | category
193 | description
194 | instructions
195 | createdDate
196 | likes
197 | username
198 | }
199 | ```
200 |
201 | #### likeRecipe (require authorization header)
202 | _username not used, obtained by Token Authorization._
203 | ```
204 | mutation ($_id: ID!, $username: String!) {
205 | likeRecipe(_id: $_id, username: $username) {
206 | ...LikeRecipe
207 | }
208 | }
209 |
210 | fragment LikeRecipe on Recipe {
211 | _id
212 | likes
213 | }
214 | ```
215 |
216 | #### unlikeRecipe (require authorization header)
217 | _username not used, obtained by Token Authorization._
218 | ```
219 | mutation ($_id: ID!, $username: String!) {
220 | unlikeRecipe(_id: $_id, username: $username) {
221 | ...LikeRecipe
222 | }
223 | }
224 |
225 | fragment LikeRecipe on Recipe {
226 | _id
227 | likes
228 | }
229 | ```
230 |
231 | #### deleteUserRecipe (require authorization header)
232 | ```
233 | mutation ($_id: ID!) {
234 | deleteUserRecipe(_id: $_id) {
235 | _id
236 | }
237 | }
238 | ```
239 |
240 | License
241 | ----
242 |
243 | MIT
244 |
--------------------------------------------------------------------------------
/config.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | type configModel struct {
4 | mongoUri string
5 | mongoDb string
6 | tokenSecret string
7 | tokenExp string
8 | serveUri string
9 | }
10 |
11 | var config = configModel{
12 | mongoUri: "mongodb://admin:123456@localhost:37812/react-recipes", // Mongo Uri example: mongodb://admin:123456@localhost:37812/react-recipes
13 | mongoDb: "react-recipes", // DB name
14 | tokenSecret: "secret", // Secret to use in Tokens
15 | tokenExp: "1h", // Expiration of Token
16 | serveUri: ":4444", // Serve
17 | }
18 |
--------------------------------------------------------------------------------
/db_logic.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "time"
7 |
8 | "go.mongodb.org/mongo-driver/bson"
9 | "go.mongodb.org/mongo-driver/bson/primitive"
10 | "go.mongodb.org/mongo-driver/mongo/options"
11 | )
12 |
13 | // Queries
14 |
15 | // getAllRecipes
16 | func (db mongoDB) getAllRecipes() (interface{}, error) {
17 | var results []RecipeModel
18 | var err error
19 |
20 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
21 | cur, err := db.recipes.Find(ctx, bson.D{}, options.Find())
22 | if err != nil {
23 | return nil, err
24 | }
25 | for cur.Next(ctx) {
26 | var elem RecipeModel
27 | err = cur.Decode(&elem)
28 | if err != nil {
29 | return nil, err
30 | }
31 | results = append(results, elem)
32 | }
33 | if err = cur.Err(); err != nil {
34 | return nil, err
35 | }
36 | cur.Close(ctx)
37 | return results, nil
38 | }
39 |
40 | // getRecipe
41 | func (db mongoDB) getRecipe(_id string) (interface{}, error) {
42 | var results RecipeModel
43 | var err error
44 |
45 | id, err := primitive.ObjectIDFromHex(_id)
46 | if err != nil {
47 | return nil, err
48 | }
49 | q := bson.M{"_id": id}
50 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
51 | err = db.recipes.FindOne(ctx, q).Decode(&results)
52 | if err != nil {
53 | return nil, err
54 | }
55 | return results, nil
56 | }
57 |
58 | // searchRecipes
59 | func (db mongoDB) searchRecipes(searchTerm string) (interface{}, error) {
60 | var err error
61 | var results []RecipeModel
62 |
63 | q := bson.M{"$text": bson.M{"$search": searchTerm}}
64 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
65 | cur, err := db.recipes.Find(ctx, q, options.Find())
66 | if err != nil {
67 | return nil, err
68 | }
69 | for cur.Next(ctx) {
70 | var elem RecipeModel
71 | err := cur.Decode(&elem)
72 | if err != nil {
73 | return nil, err
74 | }
75 | results = append(results, elem)
76 | }
77 | if err := cur.Err(); err != nil {
78 | return nil, err
79 | }
80 | cur.Close(ctx)
81 | return results, nil
82 | }
83 |
84 | // getCurrentUser
85 | func (db mongoDB) getCurrentUser(username string) (interface{}, error) {
86 | var err error
87 | var results UserModel
88 |
89 | q := bson.M{"username": username}
90 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
91 | err = db.users.FindOne(ctx, q).Decode(&results)
92 | if err != nil {
93 | return nil, err
94 | }
95 | var favorites []RecipeModel
96 | for e, _ := range results.Favorites {
97 | var recipe RecipeModel
98 |
99 | _id := results.Favorites[e].(primitive.ObjectID)
100 | q := bson.M{"_id": _id}
101 | if c, _ := db.recipes.CountDocuments(context.Background(), q); c > 0 {
102 | ctx, _ = context.WithTimeout(context.Background(), 30*time.Second)
103 | err := db.recipes.FindOne(ctx, q).Decode(&recipe)
104 | if err != nil {
105 | return nil, err
106 | }
107 | favorites = append(favorites, recipe)
108 | }
109 | }
110 | favi := make([]interface{}, len(favorites))
111 | for i, fav := range favorites {
112 | favi[i] = fav
113 | }
114 | results.Favorites = favi
115 | return results, nil
116 | }
117 |
118 | // getUserRecipes
119 | func (db mongoDB) getUserRecipes(username string) (interface{}, error) {
120 | var err error
121 | var results []RecipeModel
122 |
123 | q := bson.M{"username": username}
124 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
125 | cur, err := db.recipes.Find(ctx, q, options.Find())
126 | if err != nil {
127 | return nil, err
128 | }
129 | for cur.Next(ctx) {
130 | var elem RecipeModel
131 | err := cur.Decode(&elem)
132 | if err != nil {
133 | return nil, err
134 | }
135 | results = append(results, elem)
136 | }
137 | if err := cur.Err(); err != nil {
138 | return nil, err
139 | }
140 | cur.Close(ctx)
141 | return results, nil
142 | }
143 |
144 | // Mutations
145 |
146 | // addRecipe
147 | func (db mongoDB) addRecipe(username string, name string, imageUrl string, category string, description string, instructions string) (interface{}, error) {
148 | var err error
149 | var results RecipeModel
150 |
151 | results.ID = primitive.NewObjectID()
152 | results.Name = name
153 | results.ImageUrl = imageUrl
154 | results.Category = category
155 | results.Description = description
156 | results.Instructions = instructions
157 | results.CreatedDate = time.Now()
158 | results.Username = username
159 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
160 | _, err = db.recipes.InsertOne(ctx, results)
161 | if err != nil {
162 | return nil, err
163 | }
164 | return results, nil
165 | }
166 |
167 | // likeRecipe
168 | func (db mongoDB) likeRecipe(_id string, username string) (interface{}, error) {
169 | var err error
170 | var results RecipeModel
171 |
172 | id, err := primitive.ObjectIDFromHex(_id)
173 | if err != nil {
174 | return nil, err
175 | }
176 | q := bson.M{"_id": id}
177 | q2 := bson.M{"$inc": bson.M{"likes": 1}}
178 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
179 | err = db.recipes.FindOneAndUpdate(ctx, q, q2).Decode(&results)
180 | if err != nil {
181 | return nil, err
182 | }
183 | //results.Likes++
184 | q = bson.M{"username": username}
185 | q2 = bson.M{"$addToSet": bson.M{"favorites": id}}
186 | ctx, _ = context.WithTimeout(context.Background(), 30*time.Second)
187 | err = db.users.FindOneAndUpdate(ctx, q, q2).Err()
188 | if err != nil {
189 | return nil, err
190 | }
191 | return results, nil
192 | }
193 |
194 | // unlikeRecipe
195 | func (db mongoDB) unlikeRecipe(_id string, username string) (interface{}, error) {
196 | var err error
197 | var results RecipeModel
198 |
199 | id, err := primitive.ObjectIDFromHex(_id)
200 | if err != nil {
201 | return nil, err
202 | }
203 | q := bson.M{"_id": id}
204 | q2 := bson.M{"$inc": bson.M{"likes": -1}}
205 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
206 | err = db.recipes.FindOneAndUpdate(ctx, q, q2).Decode(&results)
207 | if err != nil {
208 | return nil, err
209 | }
210 | //results.Likes--
211 | q = bson.M{"username": username}
212 | q2 = bson.M{"$pull": bson.M{"favorites": id}}
213 | ctx, _ = context.WithTimeout(context.Background(), 30*time.Second)
214 | err = db.users.FindOneAndUpdate(ctx, q, q2).Err()
215 | if err != nil {
216 | return nil, err
217 | }
218 | return results, nil
219 | }
220 |
221 | // deleteUserRecipe
222 | func (db mongoDB) deleteUserRecipe(_id string, user string) (interface{}, error) {
223 | var err error
224 | var results RecipeModel
225 |
226 | id, err := primitive.ObjectIDFromHex(_id)
227 | if err != nil {
228 | return nil, err
229 | }
230 | q := bson.M{"_id": id, "username": user}
231 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
232 | err = db.recipes.FindOneAndDelete(ctx, q).Decode(&results)
233 | if err != nil {
234 | return nil, err
235 | }
236 | q = bson.M{"favorites": id}
237 | ctx, _ = context.WithTimeout(context.Background(), 30*time.Second)
238 | cur, err := db.users.Find(ctx, q, options.Find())
239 | if err != nil {
240 | return nil, err
241 | }
242 | for cur.Next(ctx) {
243 | var elem UserModel
244 | err := cur.Decode(&elem)
245 | if err != nil {
246 | return nil, err
247 | }
248 | q = bson.M{"username": elem.Username}
249 | q2 := bson.M{"$pull": bson.M{"favorites": id}}
250 | ctx2, _ := context.WithTimeout(context.Background(), 30*time.Second)
251 | err = db.users.FindOneAndUpdate(ctx2, q, q2).Err()
252 | if err != nil {
253 | return nil, err
254 | }
255 | }
256 | if err := cur.Err(); err != nil {
257 | return nil, err
258 | }
259 | cur.Close(ctx)
260 |
261 | return results, nil
262 | }
263 |
264 | // updateUserRecipe
265 | func (db mongoDB) updateUserRecipe(_id string, user string, name string, imageUrl string, category string, description string, instructions string) (interface{}, error) {
266 | var err error
267 | var results RecipeModel
268 |
269 | id, err := primitive.ObjectIDFromHex(_id)
270 | if err != nil {
271 | return nil, err
272 | }
273 | q := bson.M{"_id": id, "username": user}
274 | q2 := bson.M{"$set": bson.M{"name": name,
275 | "imageUrl": imageUrl,
276 | "category": category,
277 | "description": description,
278 | "instructions": instructions,
279 | }}
280 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
281 | err = db.recipes.FindOneAndUpdate(ctx, q, q2).Decode(&results)
282 | if err != nil {
283 | return nil, err
284 | }
285 | results.Name = name
286 | results.ImageUrl = imageUrl
287 | results.Category = category
288 | results.Description = description
289 | results.Instructions = instructions
290 | return results, nil
291 | }
292 |
293 | // signinUser
294 | func (db mongoDB) signinUser(username string, password string) (interface{}, error) {
295 | var err error
296 | var results UserModel
297 |
298 | q := bson.M{"username": username}
299 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
300 | if err = db.users.FindOne(ctx, q).Decode(&results); err != nil {
301 | return nil, fmt.Errorf("User not found.")
302 | }
303 | if err = comparePassword(password, results.Password); err != nil {
304 | return nil, fmt.Errorf("Invalid password.")
305 | }
306 | results.Token, err = createToken(results.Username, results.Email)
307 | return results, nil
308 | }
309 |
310 | // signupUser
311 | func (db mongoDB) signupUser(username string, password string, email string) (interface{}, error) {
312 | var err error
313 | var results UserModel
314 |
315 | q := bson.M{"username": username}
316 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
317 | if err := db.users.FindOne(ctx, q).Decode(&results); err == nil {
318 | return nil, fmt.Errorf("User already exists.")
319 | }
320 | q = bson.M{"email": email}
321 | ctx, _ = context.WithTimeout(context.Background(), 30*time.Second)
322 | if err := db.users.FindOne(ctx, q).Decode(&results); err == nil {
323 | return nil, fmt.Errorf("Email already exists.")
324 | }
325 | pass, err := generatePassword(password)
326 | if err != nil {
327 | return nil, err
328 | }
329 | results.ID = primitive.NewObjectID()
330 | results.Username = username
331 | results.Password = pass
332 | results.Email = email
333 | results.JoinDate = time.Now()
334 | results.Favorites = make([]interface{}, 0)
335 | ctx, _ = context.WithTimeout(context.Background(), 30*time.Second)
336 | _, err = db.users.InsertOne(ctx, results)
337 | if err != nil {
338 | return nil, err
339 | }
340 | results.Token, err = createToken(results.Username, results.Email)
341 | return results, nil
342 | }
343 |
--------------------------------------------------------------------------------
/db_main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "log"
6 |
7 | "go.mongodb.org/mongo-driver/mongo"
8 | "go.mongodb.org/mongo-driver/mongo/options"
9 | )
10 |
11 | type mongoDB struct {
12 | session *mongo.Client
13 | users *mongo.Collection
14 | recipes *mongo.Collection
15 | }
16 |
17 | // Connect to MongoDB
18 | func connectDB() mongoDB {
19 | client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(config.mongoUri))
20 | if err != nil {
21 | log.Fatal(err)
22 | }
23 | err = client.Ping(context.Background(), nil)
24 | if err != nil {
25 | log.Fatal(err)
26 | }
27 | return mongoDB{
28 | session: client,
29 | recipes: client.Database(config.mongoDb).Collection("recipes"),
30 | users: client.Database(config.mongoDb).Collection("users"),
31 | }
32 | }
33 |
34 | // Disconnect to MongoDB
35 | func (db mongoDB) closeDB() {
36 | err := db.session.Disconnect(context.Background())
37 | if err != nil {
38 | log.Fatal(err)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/db_struct.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "time"
5 |
6 | "go.mongodb.org/mongo-driver/bson/primitive"
7 | )
8 |
9 | // RecipeModel struct
10 | type RecipeModel struct {
11 | ID primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
12 | Name string `bson:"name" json:"name,omitempty"`
13 | ImageUrl string `bson:"imageUrl" json:"imageUrl,omitempty"`
14 | Category string `bson:"category" json:"category,omitempty"`
15 | Description string `bson:"description" json:"description,omitempty"`
16 | Instructions string `bson:"instructions" json:"instructions,omitempty"`
17 | CreatedDate time.Time `bson:"createdDate,omitempty" json:"createdDate,omitempty"`
18 | Likes int `bson:"likes,omitempty" json:"likes,omitempty"`
19 | Username string `bson:"username,omitempty" json:"username,omitempty"`
20 | }
21 |
22 | // UserModel struct
23 | type UserModel struct {
24 | ID primitive.ObjectID `bson:"_id" json:"_id,omitempty"`
25 | Username string `bson:"username" json:"username,omitempty"`
26 | Password string `bson:"password" json:"password,omitempty"`
27 | Email string `bson:"email" json:"email,omitempty"`
28 | JoinDate time.Time `bson:"joinDate" json:"joinDate,omitempty"`
29 | Favorites []interface{} `bson:"favorites" json:"favorites,omitempty" model:"RecipeModel"`
30 | Token string `json:"token,omitempty"` // graphql only
31 | }
32 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module MGG
2 |
3 | go 1.12
4 |
5 | require (
6 | github.com/dgrijalva/jwt-go v3.2.0+incompatible
7 | github.com/go-stack/stack v1.8.0 // indirect
8 | github.com/golang/snappy v0.0.1 // indirect
9 | github.com/google/go-cmp v0.2.0 // indirect
10 | github.com/graphql-go/graphql v0.7.8
11 | github.com/graphql-go/handler v0.2.3
12 | github.com/stretchr/testify v1.3.0 // indirect
13 | github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65 // indirect
14 | github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c // indirect
15 | github.com/xdg/stringprep v1.0.0 // indirect
16 | go.mongodb.org/mongo-driver v1.0.0
17 | golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c
18 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 // indirect
19 | golang.org/x/text v0.3.0 // indirect
20 | )
21 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3 | github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
4 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
5 | github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
6 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
7 | github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
8 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
9 | github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
10 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
11 | github.com/graphql-go/graphql v0.7.8 h1:769CR/2JNAhLG9+aa8pfLkKdR0H+r5lsQqling5WwpU=
12 | github.com/graphql-go/graphql v0.7.8/go.mod h1:k6yrAYQaSP59DC5UVxbgxESlmVyojThKdORUqGDGmrI=
13 | github.com/graphql-go/handler v0.2.3 h1:CANh8WPnl5M9uA25c2GBhPqJhE53Fg0Iue/fRNla71E=
14 | github.com/graphql-go/handler v0.2.3/go.mod h1:leLF6RpV5uZMN1CdImAxuiayrYYhOk33bZciaUGaXeU=
15 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
16 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
17 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
18 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
19 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
20 | github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65 h1:rQ229MBgvW68s1/g6f1/63TgYwYxfF4E+bi/KC19P8g=
21 | github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
22 | github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
23 | github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
24 | github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
25 | github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
26 | go.mongodb.org/mongo-driver v1.0.0 h1:KxPRDyfB2xXnDE2My8acoOWBQkfv3tz0SaWTRZjJR0c=
27 | go.mongodb.org/mongo-driver v1.0.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
28 | golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
29 | golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
30 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
31 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
32 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
33 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
34 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
35 |
--------------------------------------------------------------------------------
/gql_logic.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/graphql-go/graphql"
5 | )
6 |
7 | // Queries
8 |
9 | // getAllRecipes
10 | func getAllRecipes(_ graphql.ResolveParams) (interface{}, error) {
11 | var err error
12 | var results interface{}
13 |
14 | results, err = db.getAllRecipes()
15 | if err != nil {
16 | return nil, err
17 | }
18 | return results, nil
19 | }
20 |
21 | // getRecipe
22 | func getRecipe(p graphql.ResolveParams) (interface{}, error) {
23 | var err error
24 | var results interface{}
25 |
26 | id := p.Args["_id"].(string)
27 | if err := isRequired(map[string]string{
28 | "_id": id}); err != nil {
29 | return nil, err
30 | }
31 | results, err = db.getRecipe(id)
32 | if err != nil {
33 | return nil, err
34 | }
35 | return results, nil
36 | }
37 |
38 | // searchRecipes
39 | func searchRecipes(p graphql.ResolveParams) (interface{}, error) {
40 | var err error
41 | var results interface{}
42 |
43 | searchTerm := p.Args["searchTerm"].(string)
44 | results, err = db.searchRecipes(searchTerm)
45 | if err != nil {
46 | return nil, err
47 | }
48 | return results, nil
49 | }
50 |
51 | // getCurrentUser
52 | func getCurrentUser(p graphql.ResolveParams) (interface{}, error) {
53 | var err error
54 | var results interface{}
55 |
56 | user := p.Context.Value("username").(string)
57 | if len(user) == 0 {
58 | return nil, nil
59 | }
60 | results, err = db.getCurrentUser(user)
61 | if err != nil {
62 | return results, err
63 | }
64 | return results, nil
65 | }
66 |
67 | // getUserRecipes
68 | func getUserRecipes(p graphql.ResolveParams) (interface{}, error) {
69 | var err error
70 | var results interface{}
71 |
72 | user := p.Args["username"].(string)
73 | if err := isRequired(map[string]string{
74 | "username": user}); err != nil {
75 | return nil, err
76 | }
77 | results, err = db.getUserRecipes(user)
78 | if err != nil {
79 | return nil, err
80 | }
81 | return results, nil
82 | }
83 |
84 | // Mutations
85 |
86 | // addRecipe
87 | func addRecipe(p graphql.ResolveParams) (interface{}, error) {
88 | var err error
89 | var results interface{}
90 |
91 | user := p.Context.Value("username").(string) // Obtained by Token Authorization
92 | name := p.Args["name"].(string)
93 | imageUrl := p.Args["imageUrl"].(string)
94 | category := p.Args["category"].(string)
95 | description := p.Args["description"].(string)
96 | instructions := p.Args["instructions"].(string)
97 | if err := isRequired(map[string]string{
98 | "session": user,
99 | "name": name,
100 | "imageUrl": imageUrl,
101 | "category": category,
102 | "description": description,
103 | "instructions": instructions}); err != nil {
104 | return nil, err
105 | }
106 | results, err = db.addRecipe(user, name, imageUrl, category, description, instructions)
107 | if err != nil {
108 | return nil, err
109 | }
110 | return results, nil
111 | }
112 |
113 | // likeRecipe
114 | func likeRecipe(p graphql.ResolveParams) (interface{}, error) {
115 | var err error
116 | var results interface{}
117 |
118 | user := p.Context.Value("username").(string) // Obtained by Token Authorization
119 | id := p.Args["_id"].(string)
120 | if err := isRequired(map[string]string{
121 | "session": user,
122 | "ID": id}); err != nil {
123 | return nil, err
124 | }
125 | results, err = db.likeRecipe(id, user)
126 | if err != nil {
127 | return nil, err
128 | }
129 | return results, nil
130 | }
131 |
132 | // unlikeRecipe
133 | func unlikeRecipe(p graphql.ResolveParams) (interface{}, error) {
134 | var err error
135 | var results interface{}
136 |
137 | user := p.Context.Value("username").(string) // Obtained by Token Authorization
138 | id := p.Args["_id"].(string)
139 | if err := isRequired(map[string]string{
140 | "session": user,
141 | "ID": id}); err != nil {
142 | return nil, err
143 | }
144 | results, err = db.unlikeRecipe(id, user)
145 | if err != nil {
146 | return nil, err
147 | }
148 | return results, nil
149 | }
150 |
151 | // deleteUserRecipe
152 | func deleteUserRecipe(p graphql.ResolveParams) (interface{}, error) {
153 | var err error
154 | var results interface{}
155 |
156 | user := p.Context.Value("username").(string) // Obtained by Token Authorization
157 | id := p.Args["_id"].(string)
158 | if err := isRequired(map[string]string{
159 | "session": user,
160 | "ID": id}); err != nil {
161 | return nil, err
162 | }
163 | results, err = db.deleteUserRecipe(id, user)
164 | if err != nil {
165 | return nil, err
166 | }
167 | return results, nil
168 | }
169 |
170 | // updateUserRecipe
171 | func updateUserRecipe(p graphql.ResolveParams) (interface{}, error) {
172 | var err error
173 | var results interface{}
174 |
175 | user := p.Context.Value("username").(string) // Obtained by Token Authorization
176 | id := p.Args["_id"].(string)
177 | name := p.Args["name"].(string)
178 | imageUrl := p.Args["imageUrl"].(string)
179 | category := p.Args["category"].(string)
180 | description := p.Args["description"].(string)
181 | instructions := p.Args["instructions"].(string)
182 | if err := isRequired(map[string]string{
183 | "session": user,
184 | "ID": id,
185 | "name": name,
186 | "imageUrl": imageUrl,
187 | "category": category,
188 | "description": description,
189 | "instructions": instructions}); err != nil {
190 | return nil, err
191 | }
192 | results, err = db.updateUserRecipe(id, user, name, imageUrl, category, description, instructions)
193 | if err != nil {
194 | return nil, err
195 | }
196 | return results, nil
197 | }
198 |
199 | // signinUser
200 | func signinUser(p graphql.ResolveParams) (interface{}, error) {
201 | var err error
202 | var results interface{}
203 |
204 | user := p.Args["username"].(string)
205 | pass := p.Args["password"].(string)
206 | if err := isRequired(map[string]string{
207 | "username": user,
208 | "password": pass}); err != nil {
209 | return nil, err
210 | }
211 | results, err = db.signinUser(user, pass)
212 | if err != nil {
213 | return nil, err
214 | }
215 | return results, nil
216 | }
217 |
218 | // signupUser
219 | func signupUser(p graphql.ResolveParams) (interface{}, error) {
220 | var err error
221 | var results interface{}
222 |
223 | user := p.Args["username"].(string)
224 | pass := p.Args["password"].(string)
225 | email := p.Args["email"].(string)
226 | if err := isRequired(map[string]string{
227 | "username": user,
228 | "password": pass,
229 | "email": email,
230 | }); err != nil {
231 | return nil, err
232 | }
233 | results, err = db.signupUser(user, pass, email)
234 | if err != nil {
235 | return nil, err
236 | }
237 | return results, nil
238 | }
239 |
--------------------------------------------------------------------------------
/gql_schema.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 |
6 | "github.com/graphql-go/graphql"
7 | )
8 |
9 | // Init the schema of GraphQL
10 | func initSchema() graphql.Schema {
11 | graphqlSchema, err := graphql.NewSchema(graphql.SchemaConfig{
12 | Query: graphql.NewObject(graphql.ObjectConfig{
13 | Name: "Query",
14 | Fields: graphql.Fields{
15 | "getAllRecipes": &graphql.Field{
16 | Type: graphql.NewList(RecipeType),
17 | Args: graphql.FieldConfigArgument{},
18 | Resolve: getAllRecipes,
19 | },
20 | "getRecipe": &graphql.Field{
21 | Type: RecipeType,
22 | Args: graphql.FieldConfigArgument{
23 | "_id": &graphql.ArgumentConfig{
24 | Type: graphql.NewNonNull(ID),
25 | }},
26 | Resolve: getRecipe,
27 | },
28 | "searchRecipes": &graphql.Field{
29 | Type: graphql.NewList(RecipeType),
30 | Args: graphql.FieldConfigArgument{
31 | "searchTerm": &graphql.ArgumentConfig{
32 | Type: graphql.String,
33 | }},
34 | Resolve: searchRecipes,
35 | },
36 | "getCurrentUser": &graphql.Field{
37 | Type: UserType,
38 | Args: graphql.FieldConfigArgument{},
39 | Resolve: getCurrentUser,
40 | },
41 | "getUserRecipes": &graphql.Field{
42 | Type: graphql.NewList(RecipeType),
43 | Args: graphql.FieldConfigArgument{
44 | "username": &graphql.ArgumentConfig{
45 | Type: graphql.NewNonNull(graphql.String),
46 | }},
47 | Resolve: getUserRecipes,
48 | },
49 | },
50 | }),
51 | Mutation: graphql.NewObject(graphql.ObjectConfig{
52 | Name: "Mutation",
53 | Fields: graphql.Fields{
54 | "addRecipe": &graphql.Field{
55 | Type: RecipeType,
56 | Args: graphql.FieldConfigArgument{
57 | "name": &graphql.ArgumentConfig{
58 | Type: graphql.NewNonNull(graphql.String),
59 | },
60 | "imageUrl": &graphql.ArgumentConfig{
61 | Type: graphql.NewNonNull(graphql.String),
62 | },
63 | "category": &graphql.ArgumentConfig{
64 | Type: graphql.NewNonNull(graphql.String),
65 | },
66 | "description": &graphql.ArgumentConfig{
67 | Type: graphql.NewNonNull(graphql.String),
68 | },
69 | "instructions": &graphql.ArgumentConfig{
70 | Type: graphql.NewNonNull(graphql.String),
71 | },
72 | "username": &graphql.ArgumentConfig{
73 | Type: graphql.String,
74 | }},
75 | Resolve: addRecipe,
76 | },
77 | "likeRecipe": &graphql.Field{
78 | Type: RecipeType,
79 | Args: graphql.FieldConfigArgument{
80 | "_id": &graphql.ArgumentConfig{
81 | Type: graphql.NewNonNull(ID),
82 | },
83 | "username": &graphql.ArgumentConfig{
84 | Type: graphql.NewNonNull(graphql.String),
85 | }},
86 | Resolve: likeRecipe,
87 | },
88 | "unlikeRecipe": &graphql.Field{
89 | Type: RecipeType,
90 | Args: graphql.FieldConfigArgument{
91 | "_id": &graphql.ArgumentConfig{
92 | Type: graphql.NewNonNull(ID),
93 | },
94 | "username": &graphql.ArgumentConfig{
95 | Type: graphql.NewNonNull(graphql.String),
96 | }},
97 | Resolve: unlikeRecipe,
98 | },
99 | "deleteUserRecipe": &graphql.Field{
100 | Type: RecipeType,
101 | Args: graphql.FieldConfigArgument{
102 | "_id": &graphql.ArgumentConfig{
103 | Type: graphql.NewNonNull(ID),
104 | }},
105 | Resolve: deleteUserRecipe,
106 | },
107 | "updateUserRecipe": &graphql.Field{
108 | Type: RecipeType,
109 | Args: graphql.FieldConfigArgument{
110 | "_id": &graphql.ArgumentConfig{
111 | Type: graphql.NewNonNull(ID),
112 | },
113 | "name": &graphql.ArgumentConfig{
114 | Type: graphql.NewNonNull(graphql.String),
115 | },
116 | "imageUrl": &graphql.ArgumentConfig{
117 | Type: graphql.NewNonNull(graphql.String),
118 | },
119 | "category": &graphql.ArgumentConfig{
120 | Type: graphql.NewNonNull(graphql.String),
121 | },
122 | "description": &graphql.ArgumentConfig{
123 | Type: graphql.NewNonNull(graphql.String),
124 | },
125 | "instructions": &graphql.ArgumentConfig{
126 | Type: graphql.NewNonNull(graphql.String),
127 | }},
128 | Resolve: updateUserRecipe,
129 | },
130 | "signinUser": &graphql.Field{
131 | Type: UserType,
132 | Args: graphql.FieldConfigArgument{
133 | "username": &graphql.ArgumentConfig{
134 | Type: graphql.NewNonNull(graphql.String),
135 | },
136 | "password": &graphql.ArgumentConfig{
137 | Type: graphql.NewNonNull(graphql.String),
138 | }},
139 | Resolve: signinUser,
140 | },
141 | "signupUser": &graphql.Field{
142 | Type: UserType,
143 | Args: graphql.FieldConfigArgument{
144 | "username": &graphql.ArgumentConfig{
145 | Type: graphql.NewNonNull(graphql.String),
146 | },
147 | "password": &graphql.ArgumentConfig{
148 | Type: graphql.NewNonNull(graphql.String),
149 | },
150 | "email": &graphql.ArgumentConfig{
151 | Type: graphql.NewNonNull(graphql.String),
152 | }},
153 | Resolve: signupUser,
154 | },
155 | },
156 | }),
157 | Types: []graphql.Type{ID},
158 | })
159 | if err != nil {
160 | log.Fatal(err)
161 | }
162 | return graphqlSchema
163 |
164 | }
165 |
--------------------------------------------------------------------------------
/gql_struct.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "errors"
5 | "log"
6 |
7 | "github.com/graphql-go/graphql"
8 | "github.com/graphql-go/graphql/language/ast"
9 | "github.com/graphql-go/graphql/language/kinds"
10 | )
11 |
12 | // _validate for ID support
13 | func _validate(value string) error {
14 | if len(value) < 3 {
15 | return errors.New("The minimum length required is 3")
16 | }
17 | return nil
18 | }
19 |
20 | // ID support
21 | var ID = graphql.NewScalar(graphql.ScalarConfig{
22 | Name: "ID",
23 | Description: "The `id` scalar type represents a ID Object.",
24 | Serialize: func(value interface{}) interface{} {
25 | return value
26 | },
27 | ParseValue: func(value interface{}) interface{} {
28 | var err error
29 | switch value.(type) {
30 | case string:
31 | err = _validate(value.(string))
32 | default:
33 | err = errors.New("Must be of type string.")
34 | }
35 | if err != nil {
36 | log.Fatal(err)
37 | }
38 | return value
39 | },
40 | ParseLiteral: func(valueAst ast.Value) interface{} {
41 | if valueAst.GetKind() == kinds.StringValue {
42 | err := _validate(valueAst.GetValue().(string))
43 | if err != nil {
44 | log.Fatal(err)
45 | }
46 | return valueAst
47 | } else {
48 | log.Fatal("Must be of type string.")
49 | return nil
50 | }
51 | },
52 | })
53 |
54 | // RecipeType
55 | var RecipeType = graphql.NewObject(graphql.ObjectConfig{
56 | Name: "Recipe",
57 | Fields: graphql.Fields{
58 | "_id": &graphql.Field{
59 | Type: ID,
60 | },
61 | "name": &graphql.Field{
62 | Type: graphql.String,
63 | },
64 | "imageUrl": &graphql.Field{
65 | Type: graphql.String,
66 | },
67 | "category": &graphql.Field{
68 | Type: graphql.String,
69 | },
70 | "description": &graphql.Field{
71 | Type: graphql.String,
72 | },
73 | "instructions": &graphql.Field{
74 | Type: graphql.String,
75 | },
76 | "createdDate": &graphql.Field{
77 | Type: graphql.String,
78 | },
79 | "likes": &graphql.Field{
80 | Type: graphql.Int,
81 | },
82 | "username": &graphql.Field{
83 | Type: graphql.String,
84 | },
85 | },
86 | })
87 |
88 | // UserType
89 | var UserType = graphql.NewObject(graphql.ObjectConfig{
90 | Name: "User",
91 | Fields: graphql.Fields{
92 | "_id": &graphql.Field{
93 | Type: ID,
94 | },
95 | "username": &graphql.Field{
96 | Type: graphql.String,
97 | },
98 | "password": &graphql.Field{
99 | Type: graphql.String,
100 | },
101 | "email": &graphql.Field{
102 | Type: graphql.String,
103 | },
104 | "joinDate": &graphql.Field{
105 | Type: graphql.String,
106 | },
107 | "favorites": &graphql.Field{
108 | Type: graphql.NewList(RecipeType),
109 | },
110 | "token": &graphql.Field{ // graphql only
111 | Type: graphql.String,
112 | },
113 | },
114 | })
115 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "net/http"
7 |
8 | "github.com/graphql-go/handler"
9 | )
10 |
11 | var db mongoDB
12 |
13 | func main() {
14 | fmt.Println("Golang+GraphQL+MongoDB Server v1.0.0")
15 |
16 | // MongoDB
17 | db = connectDB()
18 | defer db.closeDB()
19 |
20 | // GraphQL
21 | schema := initSchema()
22 | h := handler.New(&handler.Config{
23 | Schema: &schema,
24 | Pretty: true,
25 | GraphiQL: true, // GraphiQL interface
26 | })
27 |
28 | // Serve
29 | http.Handle("/", http.FileServer(http.Dir("./public"))) // Serve the frontend in /public
30 | http.Handle("/graphql", disableCors(headerAuthorization(h)))
31 | err := http.ListenAndServe(config.serveUri, nil)
32 | if err != nil {
33 | log.Fatal("ListenAndServe: ", err)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/public/asset-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "main.css": "/static/css/main.e344f020.chunk.css",
3 | "main.js": "/static/js/main.ef6f36c7.chunk.js",
4 | "main.js.map": "/static/js/main.ef6f36c7.chunk.js.map",
5 | "runtime~main.js": "/static/js/runtime~main.a8a9905a.js",
6 | "runtime~main.js.map": "/static/js/runtime~main.a8a9905a.js.map",
7 | "static/js/2.3cd3ed05.chunk.js": "/static/js/2.3cd3ed05.chunk.js",
8 | "static/js/2.3cd3ed05.chunk.js.map": "/static/js/2.3cd3ed05.chunk.js.map",
9 | "index.html": "/index.html",
10 | "precache-manifest.322cc1a0981814470fa95698ad009295.js": "/precache-manifest.322cc1a0981814470fa95698ad009295.js",
11 | "service-worker.js": "/service-worker.js",
12 | "static/css/main.e344f020.chunk.css.map": "/static/css/main.e344f020.chunk.css.map"
13 | }
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jonathanhecl/golang-graphql-mongodb/881bce86d92e9a69b4018512f0e6aecd4e55944c/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
React App
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/public/precache-manifest.322cc1a0981814470fa95698ad009295.js:
--------------------------------------------------------------------------------
1 | self.__precacheManifest = [
2 | {
3 | "revision": "42ac5946195a7306e2a5",
4 | "url": "/static/js/runtime~main.a8a9905a.js"
5 | },
6 | {
7 | "revision": "2b45352816a04acb534c",
8 | "url": "/static/js/main.ef6f36c7.chunk.js"
9 | },
10 | {
11 | "revision": "c9934e8f8ddb7edec47a",
12 | "url": "/static/js/2.3cd3ed05.chunk.js"
13 | },
14 | {
15 | "revision": "2b45352816a04acb534c",
16 | "url": "/static/css/main.e344f020.chunk.css"
17 | },
18 | {
19 | "revision": "06c8a5df0b6f57b6c1768c28411f9e89",
20 | "url": "/index.html"
21 | }
22 | ];
--------------------------------------------------------------------------------
/public/service-worker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Welcome to your Workbox-powered service worker!
3 | *
4 | * You'll need to register this file in your web app and you should
5 | * disable HTTP caching for this file too.
6 | * See https://goo.gl/nhQhGp
7 | *
8 | * The rest of the code is auto-generated. Please don't update this file
9 | * directly; instead, make changes to your Workbox build configuration
10 | * and re-run your build process.
11 | * See https://goo.gl/2aRDsh
12 | */
13 |
14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.6.3/workbox-sw.js");
15 |
16 | importScripts(
17 | "/precache-manifest.322cc1a0981814470fa95698ad009295.js"
18 | );
19 |
20 | workbox.clientsClaim();
21 |
22 | /**
23 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to
24 | * requests for URLs in the manifest.
25 | * See https://goo.gl/S9QRab
26 | */
27 | self.__precacheManifest = [].concat(self.__precacheManifest || []);
28 | workbox.precaching.suppressWarnings();
29 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
30 |
31 | workbox.routing.registerNavigationRoute("/index.html", {
32 |
33 | blacklist: [/^\/_/,/\/[^\/]+\.[^\/]+$/],
34 | });
35 |
--------------------------------------------------------------------------------
/public/static/css/main.e344f020.chunk.css:
--------------------------------------------------------------------------------
1 | body{margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.App,nav{text-align:center}nav{padding-bottom:.2em;padding-top:2em;background-color:#efefef;box-shadow:-3px 3px 10px 0 hsla(0,0%,65.9%,.7)}nav ul{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-evenly;justify-content:space-evenly;-webkit-flex-wrap:wrap;flex-wrap:wrap}li,p{font-size:2rem}ul{list-style:none}input,select,textarea{padding:.4em .2em;font-size:2rem}nav a,nav a:link{text-decoration:none;font-size:2.5rem;font-weight:100}.active{font-weight:700}.form{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;-webkit-flex-direction:column;flex-direction:column}.delete-button{color:red;cursor:pointer}.main-title{padding:.5em;color:#1eaedb;margin:0;-webkit-text-decoration-line:underline;text-decoration-line:underline;-webkit-text-decoration-style:dotted;text-decoration-style:dotted}.cards{display:grid;margin:1.5em 3em;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));grid-auto-rows:150px;grid-auto-flow:row dense;grid-gap:2em;grid-auto-rows:300px}.card{position:relative;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:flex-end;justify-content:flex-end;box-shadow:-3px 3px 10px 0 hsla(0,0%,65.9%,.4);text-align:center;background:#ddd;transition:all .3s}.card:hover{-webkit-transform:scale(1.05);transform:scale(1.05)}.card:after{content:"";position:absolute;width:100%;height:100%;background-color:#000;opacity:.25;transition:opacity .3s ease-in-out}.card:hover:after{opacity:0}.card-text{position:relative;z-index:1;color:#272525;background:#f5f5f5;letter-spacing:1px}.card-text a{text-decoration:none}.card-text h4{margin:0;padding:.2em}.Lunch{background:#24c6dc;background:linear-gradient(90deg,#514a9d,#24c6dc)}.Lunch,.Snack{width:20%;margin:20px;z-index:1;padding:7px;border-radius:5px;color:#fff}.Snack{background:#50c9c3;background:linear-gradient(90deg,#50928f,#026964)}.Breakfast{width:100px;background:#9d50bb}.Breakfast,.Dinner{margin:20px;z-index:1;color:#fff;padding:7px;border-radius:50px 120px 120px}.Dinner{width:20%;background:linear-gradient(90deg,#b24592,#f15f79)}.recipe-image,.recipe-image:after{height:60vh;width:100%}.recipe-image:after{content:"";position:absolute;opacity:.25;transition:opacity .3s ease-in-out}.recipe{text-align:center;background:#f5f5f5;padding:1em}.recipe h1{font-size:2.5rem;text-align:center}.recipe-header{overflow:hidden;background-image:url(https://bit.ly/2JqRbuI)}.recipe-header>p{margin:0}.recipe-description{font-size:2rem;color:#2f4f4f;padding:1em;font-weight:200;background:#fff;box-shadow:2px 2px 2px 2px rgba(0,0,0,.2);font-style:italic}.recipe-name{color:#1eaedb;text-decoration:underline;-webkit-text-decoration-style:wavy;text-decoration-style:wavy}.recipe-instructions{text-align:left;padding:0 2em}.recipe-instructions *{padding-bottom:.5em}.recipe-instructions__title{font-weight:200;letter-spacing:2px;color:#1eaedb;text-decoration:underline}.like-button{position:fixed;right:1em;bottom:1em;font-size:2rem;background-color:#f15f79;color:#fff!important}.search{font-size:3rem;transition:width .2s ease-in;margin:2em;width:10em}.search:focus{width:12em}.spinner{text-align:center;padding:5em}.modal{position:fixed;left:0;top:0;right:0;bottom:0;background-color:rgba(0,0,0,.65);visibility:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden;opacity:0;transition:opacity .15s ease-in-out}.modal.modal-open{visibility:visible;-webkit-backface-visibility:visible;backface-visibility:visible;opacity:1;z-index:1}.modal-inner{position:relative;height:100%;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;align-items:center}.modal-content{background-color:#fff;max-width:35em;padding:1em 1.5em;position:relative;margin:2em;box-shadow:0 0 10px 0 rgba(0,0,0,.35)}.modal-content-inner{padding-top:1em;margin-bottom:0}.modal-content-inner input{width:500px}.modal-buttons{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:flex-end;justify-content:flex-end;-webkit-align-items:center;align-items:center}.modal-buttons button{margin-left:1em}.modal-buttons button:first-child{margin-left:0}
2 | /*# sourceMappingURL=main.e344f020.chunk.css.map */
--------------------------------------------------------------------------------
/public/static/css/main.e344f020.chunk.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["E:/Clouds/GitLab/LOCALTEST/react-recipes-master/client/src/E:/Clouds/GitLab/LOCALTEST/react-recipes-master/client/src/index.css","main.e344f020.chunk.css","E:/Clouds/GitLab/LOCALTEST/react-recipes-master/client/src/components/E:/Clouds/GitLab/LOCALTEST/react-recipes-master/client/src/components/App.css"],"names":[],"mappings":"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","file":"main.e344f020.chunk.css","sourcesContent":["body {\n margin: 0;\n padding: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n monospace;\n}\n","body {\n margin: 0;\n padding: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n monospace;\n}\n\n/*\n.App {\n text-align: center;\n}\n\n.center {\n text-align: center;\n}\n\nform.form {\n display: inline-grid;\n}\n\n.active {\n font-weight: bold;\n}\n\nnav {\n text-align: center;\n}\n\nnav > ul {\n display: inline-flex;\n list-style: none;\n}\n\nnav > ul > li {\n margin-right: 1em;\n}\n\n.App ul {\n list-style: none;\n} \n*/\n\n/********************************************/\n\n.App {\n text-align: center;\n}\n\nnav {\n text-align: center;\n padding-bottom: 0.2em;\n padding-top: 2em;\n background-color: #efefef;\n box-shadow: -3px 3px 10px 0px rgba(168, 168, 168, 0.7);\n}\n\nnav ul {\n display: -webkit-flex;\n display: flex;\n -webkit-align-items: center;\n align-items: center;\n -webkit-justify-content: space-evenly;\n justify-content: space-evenly;\n -webkit-flex-wrap: wrap;\n flex-wrap: wrap;\n}\n\np,\nli {\n font-size: 2rem;\n}\n\nul {\n list-style: none;\n}\n\ninput,\nselect,\ntextarea {\n padding: 0.4em 0.2em;\n font-size: 2rem;\n}\n\nnav a,\nnav a:link {\n text-decoration: none;\n font-size: 2.5rem;\n font-weight: 100;\n}\n\n.active {\n font-weight: bold;\n}\n\n.form {\n display: -webkit-flex;\n display: flex;\n -webkit-align-items: center;\n align-items: center;\n -webkit-justify-content: center;\n justify-content: center;\n -webkit-flex-direction: column;\n flex-direction: column;\n}\n\n.delete-button {\n color: red;\n cursor: pointer;\n}\n\n/* App */\n\n.main-title {\n padding: 0.5em;\n color: #1eaedb;\n margin: 0;\n -webkit-text-decoration-line: underline;\n text-decoration-line: underline;\n -webkit-text-decoration-style: dotted;\n text-decoration-style: dotted;\n}\n\n.cards {\n display: grid;\n margin: 1.5em 3em;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n grid-auto-rows: 150px;\n grid-auto-flow: row dense;\n grid-gap: 2em;\n grid-auto-rows: 300px;\n}\n\n.card {\n position: relative;\n display: -webkit-flex;\n display: flex;\n -webkit-flex-direction: column;\n flex-direction: column;\n -webkit-justify-content: flex-end;\n justify-content: flex-end;\n box-shadow: -3px 3px 10px 0px rgba(168, 168, 168, 0.4);\n text-align: center;\n background: #ddd;\n transition: all 0.3s;\n}\n\n.card:hover {\n -webkit-transform: scale(1.05);\n transform: scale(1.05);\n}\n\n.card:after {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 100%;\n background-color: black;\n opacity: 0.25;\n transition: opacity 0.3s ease-in-out;\n}\n\n.card:hover:after {\n opacity: 0;\n}\n\n.card-text {\n position: relative;\n z-index: 1;\n color: rgb(39, 37, 37);\n background: whitesmoke;\n letter-spacing: 1px;\n}\n\n.card-text a {\n text-decoration: none;\n}\n\n.card-text h4 {\n margin: 0;\n padding: 0.2em;\n}\n\n.Lunch {\n width: 20%;\n margin: 20px;\n z-index: 1;\n padding: 7px;\n border-radius: 5px;\n color: white;\n background: #24c6dc;\n background: linear-gradient(to right, #514a9d, #24c6dc);\n}\n\n.Snack {\n width: 20%;\n margin: 20px;\n z-index: 1;\n padding: 7px;\n border-radius: 5px;\n color: white;\n background: #50c9c3;\n background: linear-gradient(to right, rgb(80, 146, 143), rgb(2, 105, 100));\n}\n\n.Breakfast {\n width: 100px;\n margin: 20px;\n z-index: 1;\n color: white;\n padding: 7px;\n background: #9d50bb;\n border-radius: 50px 120px 120px;\n}\n\n.Dinner {\n width: 20%;\n margin: 20px;\n z-index: 1;\n padding: 7px;\n color: white;\n background: linear-gradient(to right, #b24592, #f15f79);\n border-radius: 50px 120px 120px;\n}\n\n/* Recipe Page */\n\n.recipe-image {\n height: 60vh;\n width: 100%;\n}\n\n.recipe-image:after {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 60vh;\n opacity: 0.25;\n transition: opacity 0.3s ease-in-out;\n}\n\n.recipe {\n text-align: center;\n background: whitesmoke;\n padding: 1em;\n}\n\n.recipe h1 {\n font-size: 2.5rem;\n text-align: center;\n}\n\n.recipe-header {\n overflow: hidden;\n background-image: url(https://bit.ly/2JqRbuI);\n}\n\n.recipe-header > p {\n margin: 0;\n}\n\n.recipe-description {\n font-size: 2rem;\n color: darkslategray;\n padding: 1em;\n font-weight: 200;\n background: white;\n box-shadow: 2px 2px 2px 2px rgba(0, 0, 0, 0.2);\n font-style: italic;\n}\n\n.recipe-name {\n color: #1eaedb;\n text-decoration: underline;\n -webkit-text-decoration-style: wavy;\n text-decoration-style: wavy;\n}\n\n.recipe-instructions {\n text-align: left;\n padding: 0 2em;\n}\n\n.recipe-instructions * {\n padding-bottom: 0.5em;\n}\n\n.recipe-instructions__title {\n font-weight: 200;\n letter-spacing: 2px;\n color: #1eaedb;\n text-decoration: underline;\n}\n\n.like-button {\n position: fixed;\n right: 1em;\n bottom: 1em;\n font-size: 2rem;\n background-color: #f15f79;\n color: white !important;\n}\n\n/* Search */\n\n.search {\n font-size: 3rem;\n transition: width 0.2s ease-in;\n margin: 2em;\n width: 10em;\n}\n\n.search:focus {\n width: 12em;\n}\n\n.spinner {\n text-align: center;\n padding: 5em;\n}\n\n/* User Recipes */\n\n.modal {\n position: fixed;\n left: 0;\n top: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.65);\n visibility: hidden;\n -webkit-backface-visibility: hidden;\n backface-visibility: hidden;\n opacity: 0;\n transition: opacity 0.15s ease-in-out;\n}\n\n.modal.modal-open {\n visibility: visible;\n -webkit-backface-visibility: visible;\n backface-visibility: visible;\n opacity: 1;\n z-index: 1;\n}\n\n.modal-inner {\n position: relative;\n height: 100%;\n display: -webkit-flex;\n display: flex;\n -webkit-flex-direction: column;\n flex-direction: column;\n -webkit-justify-content: center;\n justify-content: center;\n -webkit-align-items: center;\n align-items: center;\n}\n\n.modal-content {\n background-color: white;\n max-width: 35em;\n padding: 1em 1.5em;\n position: relative;\n margin: 2em;\n box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.35);\n}\n\n.modal-content-inner {\n padding-top: 1em;\n margin-bottom: 0;\n}\n\n.modal-content-inner input {\n width: 500px;\n}\n\n.modal-buttons {\n display: -webkit-flex;\n display: flex;\n -webkit-flex-direction: row;\n flex-direction: row;\n -webkit-justify-content: flex-end;\n justify-content: flex-end;\n -webkit-align-items: center;\n align-items: center;\n}\n\n.modal-buttons button {\n margin-left: 1em;\n}\n\n.modal-buttons button:first-child {\n margin-left: 0;\n}\n\n","/*\n.App {\n text-align: center;\n}\n\n.center {\n text-align: center;\n}\n\nform.form {\n display: inline-grid;\n}\n\n.active {\n font-weight: bold;\n}\n\nnav {\n text-align: center;\n}\n\nnav > ul {\n display: inline-flex;\n list-style: none;\n}\n\nnav > ul > li {\n margin-right: 1em;\n}\n\n.App ul {\n list-style: none;\n} \n*/\n\n/********************************************/\n\n.App {\n text-align: center;\n}\n\nnav {\n text-align: center;\n padding-bottom: 0.2em;\n padding-top: 2em;\n background-color: #efefef;\n box-shadow: -3px 3px 10px 0px rgba(168, 168, 168, 0.7);\n}\n\nnav ul {\n display: flex;\n align-items: center;\n justify-content: space-evenly;\n flex-wrap: wrap;\n}\n\np,\nli {\n font-size: 2rem;\n}\n\nul {\n list-style: none;\n}\n\ninput,\nselect,\ntextarea {\n padding: 0.4em 0.2em;\n font-size: 2rem;\n}\n\nnav a,\nnav a:link {\n text-decoration: none;\n font-size: 2.5rem;\n font-weight: 100;\n}\n\n.active {\n font-weight: bold;\n}\n\n.form {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n}\n\n.delete-button {\n color: red;\n cursor: pointer;\n}\n\n/* App */\n\n.main-title {\n padding: 0.5em;\n color: #1eaedb;\n margin: 0;\n text-decoration-line: underline;\n text-decoration-style: dotted;\n}\n\n.cards {\n display: grid;\n margin: 1.5em 3em;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n grid-auto-rows: 150px;\n grid-auto-flow: row dense;\n grid-gap: 2em;\n grid-auto-rows: 300px;\n}\n\n.card {\n position: relative;\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n box-shadow: -3px 3px 10px 0px rgba(168, 168, 168, 0.4);\n text-align: center;\n background: #ddd;\n transition: all 0.3s;\n}\n\n.card:hover {\n transform: scale(1.05);\n}\n\n.card:after {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 100%;\n background-color: black;\n opacity: 0.25;\n transition: opacity 0.3s ease-in-out;\n}\n\n.card:hover:after {\n opacity: 0;\n}\n\n.card-text {\n position: relative;\n z-index: 1;\n color: rgb(39, 37, 37);\n background: whitesmoke;\n letter-spacing: 1px;\n}\n\n.card-text a {\n text-decoration: none;\n}\n\n.card-text h4 {\n margin: 0;\n padding: 0.2em;\n}\n\n.Lunch {\n width: 20%;\n margin: 20px;\n z-index: 1;\n padding: 7px;\n border-radius: 5px;\n color: white;\n background: #24c6dc;\n background: linear-gradient(to right, #514a9d, #24c6dc);\n}\n\n.Snack {\n width: 20%;\n margin: 20px;\n z-index: 1;\n padding: 7px;\n border-radius: 5px;\n color: white;\n background: #50c9c3;\n background: linear-gradient(to right, rgb(80, 146, 143), rgb(2, 105, 100));\n}\n\n.Breakfast {\n width: 100px;\n margin: 20px;\n z-index: 1;\n color: white;\n padding: 7px;\n background: #9d50bb;\n border-radius: 50px 120px 120px;\n}\n\n.Dinner {\n width: 20%;\n margin: 20px;\n z-index: 1;\n padding: 7px;\n color: white;\n background: linear-gradient(to right, #b24592, #f15f79);\n border-radius: 50px 120px 120px;\n}\n\n/* Recipe Page */\n\n.recipe-image {\n height: 60vh;\n width: 100%;\n}\n\n.recipe-image:after {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 60vh;\n opacity: 0.25;\n transition: opacity 0.3s ease-in-out;\n}\n\n.recipe {\n text-align: center;\n background: whitesmoke;\n padding: 1em;\n}\n\n.recipe h1 {\n font-size: 2.5rem;\n text-align: center;\n}\n\n.recipe-header {\n overflow: hidden;\n background-image: url(https://bit.ly/2JqRbuI);\n}\n\n.recipe-header > p {\n margin: 0;\n}\n\n.recipe-description {\n font-size: 2rem;\n color: darkslategray;\n padding: 1em;\n font-weight: 200;\n background: white;\n box-shadow: 2px 2px 2px 2px rgba(0, 0, 0, 0.2);\n font-style: italic;\n}\n\n.recipe-name {\n color: #1eaedb;\n text-decoration: underline;\n text-decoration-style: wavy;\n}\n\n.recipe-instructions {\n text-align: left;\n padding: 0 2em;\n}\n\n.recipe-instructions * {\n padding-bottom: 0.5em;\n}\n\n.recipe-instructions__title {\n font-weight: 200;\n letter-spacing: 2px;\n color: #1eaedb;\n text-decoration: underline;\n}\n\n.like-button {\n position: fixed;\n right: 1em;\n bottom: 1em;\n font-size: 2rem;\n background-color: #f15f79;\n color: white !important;\n}\n\n/* Search */\n\n.search {\n font-size: 3rem;\n transition: width 0.2s ease-in;\n margin: 2em;\n width: 10em;\n}\n\n.search:focus {\n width: 12em;\n}\n\n.spinner {\n text-align: center;\n padding: 5em;\n}\n\n/* User Recipes */\n\n.modal {\n position: fixed;\n left: 0;\n top: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.65);\n visibility: hidden;\n backface-visibility: hidden;\n opacity: 0;\n transition: opacity 0.15s ease-in-out;\n}\n\n.modal.modal-open {\n visibility: visible;\n backface-visibility: visible;\n opacity: 1;\n z-index: 1;\n}\n\n.modal-inner {\n position: relative;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n}\n\n.modal-content {\n background-color: white;\n max-width: 35em;\n padding: 1em 1.5em;\n position: relative;\n margin: 2em;\n box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.35);\n}\n\n.modal-content-inner {\n padding-top: 1em;\n margin-bottom: 0;\n}\n\n.modal-content-inner input {\n width: 500px;\n}\n\n.modal-buttons {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n align-items: center;\n}\n\n.modal-buttons button {\n margin-left: 1em;\n}\n\n.modal-buttons button:first-child {\n margin-left: 0;\n}\n"]}
--------------------------------------------------------------------------------
/public/static/js/main.ef6f36c7.chunk.js:
--------------------------------------------------------------------------------
1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[0],{106:function(e,t,n){"use strict";n.r(t);var a=n(0),r=n.n(a),c=n(40),i=n.n(c),l=n(110),u=n(111),o=n(54),s=n(109),m=(n(61),n(15)),p=n(16),d=n(18),h=n(17),f=n(19),g=n(37),E=(n(62),n(5)),v=n(11),b=n(9);function y(){var e=Object(v.a)(["\n fragment LikeRecipe on Recipe {\n _id\n likes\n }\n "]);return y=function(){return e},e}function j(){var e=Object(v.a)(["\n fragment MinimalRecipe on Recipe {\n _id\n name\n imageUrl\n category\n }\n "]);return j=function(){return e},e}function O(){var e=Object(v.a)(["\n fragment CompleteRecipe on Recipe {\n _id\n name\n imageUrl\n category\n description\n instructions\n createdDate\n likes\n username\n }\n "]);return O=function(){return e},e}var k={recipe:Object(b.b)(O()),minRecipe:Object(b.b)(j()),like:Object(b.b)(y())};function C(){var e=Object(v.a)(["\n mutation($username: String!, $email: String!, $password: String!) {\n signupUser(username: $username, email: $email, password: $password) {\n token\n }\n }\n"]);return C=function(){return e},e}function S(){var e=Object(v.a)(["\n mutation($username: String!, $password: String!) {\n signinUser(username: $username, password: $password) {\n token\n }\n }\n"]);return S=function(){return e},e}function R(){var e=Object(v.a)(["\n query($username: String!) {\n getUserRecipes(username: $username) {\n ...CompleteRecipe\n }\n }\n ","\n"]);return R=function(){return e},e}function w(){var e=Object(v.a)(["\n query {\n getCurrentUser {\n username\n joinDate\n email\n favorites {\n _id\n name\n }\n }\n }\n"]);return w=function(){return e},e}function U(){var e=Object(v.a)(["\n mutation(\n $_id: ID!\n $name: String!\n $imageUrl: String!\n $category: String!\n $description: String!\n $instructions: String!\n ) {\n updateUserRecipe(\n _id: $_id\n name: $name\n imageUrl: $imageUrl\n category: $category\n description: $description\n instructions: $instructions\n ) {\n ...CompleteRecipe\n }\n }\n ","\n"]);return U=function(){return e},e}function _(){var e=Object(v.a)(["\n mutation($_id: ID!) {\n deleteUserRecipe(_id: $_id) {\n _id\n }\n }\n"]);return _=function(){return e},e}function $(){var e=Object(v.a)(["\n mutation($_id: ID!, $username: String!) {\n unlikeRecipe(_id: $_id, username: $username) {\n ...LikeRecipe\n }\n }\n ","\n"]);return $=function(){return e},e}function N(){var e=Object(v.a)(["\n mutation($_id: ID!, $username: String!) {\n likeRecipe(_id: $_id, username: $username) {\n ...LikeRecipe\n }\n }\n ","\n"]);return N=function(){return e},e}function A(){var e=Object(v.a)(["\n mutation(\n $name: String!\n $imageUrl: String!\n $category: String!\n $description: String!\n $instructions: String!\n $username: String\n ) {\n addRecipe(\n name: $name\n imageUrl: $imageUrl\n category: $category\n description: $description\n instructions: $instructions\n username: $username\n ) {\n ...MinimalRecipe\n }\n }\n ","\n"]);return A=function(){return e},e}function D(){var e=Object(v.a)(["\n query($searchTerm: String) {\n searchRecipes(searchTerm: $searchTerm) {\n _id\n name\n likes\n }\n }\n"]);return D=function(){return e},e}function x(){var e=Object(v.a)(["\n query($_id: ID!) {\n getRecipe(_id: $_id) {\n ...CompleteRecipe\n }\n }\n ","\n"]);return x=function(){return e},e}function q(){var e=Object(v.a)(["\n query {\n getAllRecipes {\n ...MinimalRecipe\n }\n }\n ","\n"]);return q=function(){return e},e}var I=Object(b.b)(q(),k.minRecipe),L=Object(b.b)(x(),k.recipe),F=Object(b.b)(D()),M=Object(b.b)(A(),k.minRecipe),Q=Object(b.b)(N(),k.like),B=Object(b.b)($(),k.like),T=Object(b.b)(_()),P=Object(b.b)(U(),k.recipe),Y=Object(b.b)(w()),H=Object(b.b)(R(),k.recipe),J=Object(b.b)(S()),z=Object(b.b)(C()),G=n(41),W=g.a.li({shown:{opacity:1},hidden:{opacity:0}}),K=function(e){var t=e._id,n=e.name,a=e.imageUrl,c=e.category;return r.a.createElement(W,{style:{background:"url(".concat(a,") center center / cover no-repeat")},className:"card"},r.a.createElement("span",{className:c},c),r.a.createElement("div",{className:"card-text"},r.a.createElement(G.a,{to:"/recipes/".concat(t)},r.a.createElement("h4",null,n))))},V=n(52),X=function(){return r.a.createElement("div",{className:"spinner"},r.a.createElement(V.PulseLoader,{color:"#1eaedb",size:30,margin:"3px"}))},Z=g.a.ul({shown:{x:"0%",staggerChildren:100},hidden:{x:"-100%"}}),ee=function(e){function t(){var e,n;Object(m.a)(this,t);for(var a=arguments.length,r=new Array(a),c=0;c-1;n.setState({liked:c,username:t})}},n.handleClick=function(e,t){n.setState(function(e){return{liked:!e.liked}},function(){return n.handleLike(e,t)})},n.handleLike=function(e,t){n.state.liked?e().then(function(){var e=Object(ae.a)(ne.a.mark(function e(t){return ne.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t.data,e.next=3,n.props.refetch();case 3:case"end":return e.stop()}},e)}));return function(t){return e.apply(this,arguments)}}()):t().then(function(){var e=Object(ae.a)(ne.a.mark(function e(t){return ne.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t.data,e.next=3,n.props.refetch();case 3:case"end":return e.stop()}},e)}));return function(t){return e.apply(this,arguments)}}())},n.updateLike=function(e,t){var a=t.data.likeRecipe,r=n.props._id,c=e.readQuery({query:L,variables:{_id:r}}).getRecipe;e.writeQuery({query:L,variables:{_id:r},data:{getRecipe:Object(ce.a)({},c,{likes:a.likes+1})}})},n.updateUnlike=function(e,t){var a=t.data.unlikeRecipe,r=n.props._id,c=e.readQuery({query:L,variables:{_id:r}}).getRecipe;e.writeQuery({query:L,variables:{_id:r},data:{getRecipe:Object(ce.a)({},c,{likes:a.likes-1})}})},n}return Object(f.a)(t,e),Object(p.a)(t,[{key:"render",value:function(){var e=this,t=this.state,n=t.username,a=t.liked,c=this.props._id;return r.a.createElement(E.c,{mutation:B,variables:{_id:c,username:n},update:this.updateUnlike},function(t){return r.a.createElement(E.c,{mutation:Q,variables:{_id:c,username:n},update:e.updateLike},function(c){return n&&r.a.createElement("button",{className:"like-button",onClick:function(){return e.handleClick(c,t)}},a?"Unlike":"Like")})})}}]),t}(r.a.Component)),Se=Object(ie.a)(function(e){var t=e.match.params._id;return r.a.createElement(E.d,{query:L,variables:{_id:t}},function(e){var n=e.data,a=e.loading,c=e.error;return a?r.a.createElement(X,null):c?r.a.createElement("div",{className:"App"},"Error"):r.a.createElement("div",{className:"App"},r.a.createElement("div",{style:{background:"url(".concat(n.getRecipe.imageUrl,") center center / cover no-repeat")},className:"recipe-image"}),r.a.createElement("div",{className:"recipe"},r.a.createElement("div",{className:"recipe-header"},r.a.createElement("h2",{className:"recipe-name"},r.a.createElement("strong",null,n.getRecipe.name)),r.a.createElement("h5",null,r.a.createElement("strong",null,n.getRecipe.category)),r.a.createElement("p",null,"Created by ",r.a.createElement("strong",null,n.getRecipe.username)),r.a.createElement("p",null,"Created date ",r.a.createElement("strong",null,n.getRecipe.createdDate)),r.a.createElement("p",null,n.getRecipe.likes," ",r.a.createElement("span",{role:"img","aria-label":"heart"},"\u2665"))),r.a.createElement("blockquote",{className:"recipe-description"},n.getRecipe.description),r.a.createElement("h3",{className:"recipe-instructions__title"},"Instructions"),r.a.createElement("div",{className:"recipe-instructions",dangerouslySetInnerHTML:{__html:n.getRecipe.instructions}}),r.a.createElement(Ce,{_id:t})))})}),Re=function(e){var t=e.session;return r.a.createElement("div",{className:"App"},r.a.createElement("h3",null,"User Info"),r.a.createElement("p",null,"Username: ",t.getCurrentUser.username),r.a.createElement("p",null,"E-mail: ",t.getCurrentUser.email),r.a.createElement("p",null,"Join Date: ",function(e){var t=new Date(e).toLocaleDateString("en-US"),n=new Date(e).toLocaleTimeString("en-US");return"".concat(t," at ").concat(n)}(t.getCurrentUser.joinDate)),r.a.createElement("ul",null,r.a.createElement("h3",null,t.getCurrentUser.username,"'s Favorites"),t.getCurrentUser.favorites.map(function(e){return r.a.createElement("li",{key:e._id},r.a.createElement(G.a,{to:"/recipes/".concat(e._id)},r.a.createElement("p",null,e.name))," ")}),!t.getCurrentUser.favorites.length&&r.a.createElement("p",null,r.a.createElement("strong",null,"You have no favorites currently. Go add some!"))))},we=function(e){function t(){var e,n;Object(m.a)(this,t);for(var a=arguments.length,r=new Array(a),c=0;c1&&void 0!==arguments[1]?arguments[1]:{};return r.a.createElement(r.a.Fragment,null,r.a.createElement("button",{className:"button-primary",onClick:function(){return e.loadRecipe(n)}},"Update"),r.a.createElement("button",{className:"delete-button",onClick:function(){return e.handleDelete(t)}},a.loading?"Deleting...":"Delete"))}))}))})}}]),t}(r.a.Component),Ue=function(e){var t=e.handleSubmit,n=e.recipe,a=e.handleChange,c=e.handleEditChange,i=e.closeModal;return r.a.createElement(E.c,{mutation:P,variables:{_id:n._id,name:n.name,imageUrl:n.imageUrl,category:n.category,description:n.description,instructions:n.instructions}},function(e){return r.a.createElement("div",{className:"modal modal-open"},r.a.createElement("div",{className:"modal-inner"},r.a.createElement("div",{className:"modal-content"},r.a.createElement("form",{onSubmit:function(n){return t(n,e)},className:"modal-content-inner"},r.a.createElement("h4",null,"Edit Recipe"),r.a.createElement("input",{type:"text",name:"name",placeholder:"Recipe Name",onChange:a,value:n.name}),r.a.createElement("input",{type:"text",name:"imageUrl",placeholder:"Recipe Image",onChange:a,value:n.imageUrl}),r.a.createElement("select",{name:"category",onChange:a,value:n.category},r.a.createElement("option",{value:"Breakfast"},"Breakfast"),r.a.createElement("option",{value:"Lunch"},"Lunch"),r.a.createElement("option",{value:"Dinner"},"Dinner"),r.a.createElement("option",{value:"Snack"},"Snack")),r.a.createElement("input",{type:"text",name:"description",placeholder:"Add description",onChange:a,value:n.description}),r.a.createElement(be.a,{name:"instructions",content:n.instructions,events:{change:c}}),r.a.createElement("hr",null),r.a.createElement("div",{className:"modal-buttons"},r.a.createElement("button",{type:"submit",className:"button-primary"},"Update"),r.a.createElement("button",{onClick:i},"Cencel"))))))})},_e=we,$e=ye(function(e){return e&&e.data.getCurrentUser})(function(e){var t=e.session;return r.a.createElement("div",{className:"App"},r.a.createElement(Re,{session:t}),r.a.createElement(_e,{username:t.getCurrentUser.username}))}),Ne=n(108),Ae=Object(ie.a)(function(e){var t=e.history;return r.a.createElement(E.a,null,function(e){return r.a.createElement("button",{onClick:function(){return function(e,t){localStorage.removeItem("token"),e.resetStore(),t.push("/")}(e,t)}},"Signout")})}),De=function(e){var t=e.session;return r.a.createElement(a.Fragment,null,r.a.createElement("ul",null,r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/",exact:!0},"Home")),r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/search"},"Search")),r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/recipe/add"},"Add Recipe")),r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/profile"},"Profile")),r.a.createElement("li",null,r.a.createElement(Ae,null))),r.a.createElement("h4",null,"Welcome, ",r.a.createElement("strong",null,t.getCurrentUser.username)))},xe=function(){return r.a.createElement("ul",null,r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/",exact:!0},"Home")),r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/search"},"Search")),r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/signin"},"Signin")),r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/signup"},"Signup")))},qe=function(e){var t=e.session;return r.a.createElement("nav",null,t&&t.getCurrentUser?r.a.createElement(De,{session:t}):r.a.createElement(xe,null))},Ie=new b.a({uri:"http://localhost:4444/graphql",fetchOptions:{credentials:"include"},request:function(e){var t=localStorage.getItem("token");e.setContext({headers:{authorization:t}})},onError:function(e){e.networkError&&localStorage.setItem("token","")}}),Le=he(function(e){var t=e.refetch,n=e.session;return r.a.createElement(l.a,null,r.a.createElement(a.Fragment,null,r.a.createElement(qe,{session:n}),r.a.createElement(u.a,null,r.a.createElement(o.a,{path:"/",exact:!0,component:ee}),r.a.createElement(o.a,{path:"/search",component:ge}),r.a.createElement(o.a,{path:"/profile",render:function(){return r.a.createElement($e,{session:n})}}),r.a.createElement(o.a,{path:"/recipe/add",render:function(){return r.a.createElement(ke,{session:n})}}),r.a.createElement(o.a,{path:"/recipes/:_id",component:Se}),r.a.createElement(o.a,{path:"/signin",render:function(){return r.a.createElement(se,{refetch:t})}}),r.a.createElement(o.a,{path:"/signup",render:function(){return r.a.createElement(de,{refetch:t})}}),r.a.createElement(s.a,{to:"/"}))))});i.a.render(r.a.createElement(E.b,{client:Ie},r.a.createElement(Le,null)),document.getElementById("root"))},56:function(e,t,n){e.exports=n(106)},61:function(e,t,n){},62:function(e,t,n){}},[[56,1,2]]]);
2 | //# sourceMappingURL=main.ef6f36c7.chunk.js.map
--------------------------------------------------------------------------------
/public/static/js/main.ef6f36c7.chunk.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["queries/fragments.js","queries/index.js","components/Recipe/RecipeItem.js","components/Spinner.js","components/App.js","components/Error.js","components/Auth/Signin.js","components/Auth/Signup.js","components/withSession.js","components/Recipe/SearchItem.js","components/Recipe/Search.js","components/withAuth.js","components/Recipe/AddRecipe.js","components/Recipe/LikeRecipe.js","components/Recipe/RecipePage.js","components/Profile/UserInfo.js","components/Profile/UserRecipes.js","components/Profile/Profile.js","components/Auth/Signout.js","components/Navbar.js","index.js"],"names":["recipeFragments","recipe","gql","_templateObject","minRecipe","_templateObject2","like","_templateObject3","GET_ALL_RECIPES","queries_templateObject","GET_RECIPE","queries_templateObject2","SEARCH_RECIPES","queries_templateObject3","ADD_RECIPE","_templateObject4","LIKE_RECIPE","_templateObject5","UNLIKE_RECIPE","_templateObject6","DELETE_USER_RECIPE","_templateObject7","UPDATE_USER_RECIPE","_templateObject8","GET_CURRENT_USER","_templateObject9","GET_USER_RECIPES","_templateObject10","SIGNIN_USER","_templateObject11","SIGNUP_USER","_templateObject12","RecipeItem","posed","li","shown","opacity","hidden","Recipe_RecipeItem","_ref","_id","name","imageUrl","category","react_default","a","createElement","style","background","concat","className","Link","to","Spinner","react_spinners","color","size","margin","RecipeList","ul","x","staggerChildren","App","state","on","slideIn","_this","setState","setTimeout","this","_this2","react_apollo_esm","query","data","loading","error","components_Spinner","pose","getAllRecipes","map","Object","assign","key","React","Component","Error","message","initialState","username","password","Signin","clearState","objectSpread","handleChange","event","_event$target","target","value","defineProperty","handleSubmit","signinUser","preventDefault","then","_ref2","asyncToGenerator","regenerator_default","mark","_callee","wrap","_context","prev","next","localStorage","setItem","token","props","refetch","history","push","stop","_x","apply","arguments","validateForm","_this$state","_this$state2","mutation","variables","_ref3","onSubmit","type","placeholder","onChange","disabled","components_Error","withRouter","email","passwordConfirmation","Signup","signupUser","withSession","session","SearchItem","likes","Search","searchRecipes","client","persist","searchTerm","sent","Recipe_SearchItem","withAuth","conditionFunc","Redirect","description","instructions","AddRecipe","handleEditChange","newContent","editor","getData","addRecipe","updateCache","cache","readQuery","writeQuery","toConsumableArray","getCurrentUser","refetchQueries","update","htmlFor","lib_default","content","events","change","liked","componentDidMount","console","log","_this$props$session$g","favorites","prevLiked","findIndex","favorite","handleClick","likeRecipe","unlikeRecipe","prevState","handleLike","_ref4","_callee2","_context2","_x2","updateLike","_ref5","getRecipe","updateUnlike","_ref6","onClick","match","params","createdDate","role","aria-label","dangerouslySetInnerHTML","__html","Recipe_LikeRecipe","UserInfo","date","newDate","Date","toLocaleDateString","newTime","toLocaleTimeString","formatDate","joinDate","length","UserRecipes","modal","handleDelete","deleteUserRecipe","window","confirm","updateUserRecipe","closeModal","loadRecipe","UserRecipes_EditRecipeModal","getUserRecipes","border","marginBottom","filter","attrs","undefined","Fragment","EditRecipeModal","Profile_UserInfo","Profile_UserRecipes","removeItem","resetStore","handleSignout","NavbarAuth","react","NavLink","exact","Auth_Signout","NavbarUnAuth","Navbar","Navbar_NavbarAuth","Navbar_NavbarUnAuth","ApolloClient","uri","fetchOptions","credentials","request","operation","getItem","setContext","headers","authorization","onError","networkError","RootWithSession","BrowserRouter","components_Navbar","Switch","Route","path","component","render","components_Profile_Profile","Recipe_AddRecipe","RecipePage","Auth_Signin","Auth_Signup","ReactDOM","document","getElementById"],"mappings":"k0BAEO,IAAMA,EAAkB,CAC7BC,OAAQC,YAAFC,KAaNC,UAAWF,YAAFG,KAQTC,KAAMJ,YAAFK,2zFCpBC,IAAMC,EAAkBN,YAAHO,IAMxBT,EAAgBI,WAEPM,EAAaR,YAAHS,IAMnBX,EAAgBC,QAEPW,EAAiBV,YAAHW,KAWdC,EAAaZ,YAAHa,IAoBnBf,EAAgBI,WAEPY,EAAcd,YAAHe,IAMpBjB,EAAgBM,MAEPY,EAAgBhB,YAAHiB,IAMtBnB,EAAgBM,MAEPc,EAAqBlB,YAAHmB,KAOlBC,EAAqBpB,YAAHqB,IAoB3BvB,EAAgBC,QAIPuB,EAAmBtB,YAAHuB,KAahBC,EAAmBxB,YAAHyB,IAMzB3B,EAAgBC,QAIP2B,EAAc1B,YAAH2B,KAQXC,EAAc5B,YAAH6B,aC/HlBC,EAAaC,IAAMC,GAAG,CAC1BC,MAAO,CAAEC,QAAS,GAClBC,OAAQ,CAAED,QAAS,KAGNE,EAAA,SAAAC,GAAA,IAAGC,EAAHD,EAAGC,IAAKC,EAARF,EAAQE,KAAMC,EAAdH,EAAcG,SAAUC,EAAxBJ,EAAwBI,SAAxB,OACbC,EAAAC,EAAAC,cAACd,EAAD,CACEe,MAAO,CAAEC,WAAU,OAAAC,OAASP,EAAT,sCACnBQ,UAAU,QAEVN,EAAAC,EAAAC,cAAA,QAAMI,UAAWP,GAAWA,GAC5BC,EAAAC,EAAAC,cAAA,OAAKI,UAAU,aACbN,EAAAC,EAAAC,cAACK,EAAA,EAAD,CAAMC,GAAE,YAAAH,OAAcT,IACpBI,EAAAC,EAAAC,cAAA,UAAKL,eCREY,EANC,kBACdT,EAAAC,EAAAC,cAAA,OAAKI,UAAU,WACbN,EAAAC,EAAAC,cAACQ,EAAA,YAAD,CAAaC,MAAO,UAAWC,KAAM,GAAIC,OAAQ,UCI/CC,EAAazB,IAAM0B,GAAG,CAC1BxB,MAAO,CACLyB,EAAG,KACHC,gBAAiB,KAEnBxB,OAAQ,CACNuB,EAAG,WA0CQE,8MArCbC,MAAQ,CACNC,IAAI,KAONC,QAAU,WACRC,EAAKC,SAAS,CAAEH,IAAKE,EAAKH,MAAMC,yFAJhCI,WAAWC,KAAKJ,QAAS,sCAOlB,IAAAK,EAAAD,KACP,OACEzB,EAAAC,EAAAC,cAAA,OAAKI,UAAU,OACbN,EAAAC,EAAAC,cAAA,MAAII,UAAU,cAAd,oBACmBN,EAAAC,EAAAC,cAAA,uBAEnBF,EAAAC,EAAAC,cAACyB,EAAA,EAAD,CAAOC,MAAOhE,GACX,SAAA+B,GAA8B,IAA3BkC,EAA2BlC,EAA3BkC,KAAMC,EAAqBnC,EAArBmC,QAASC,EAAYpC,EAAZoC,MACjB,GAAID,EAAS,OAAO9B,EAAAC,EAAAC,cAAC8B,EAAD,MACpB,GAAID,EAAO,OAAO/B,EAAAC,EAAAC,cAAA,OAAKI,UAAU,OAAf,SAFW,IAGrBc,EAAOM,EAAKP,MAAZC,GACR,OACEpB,EAAAC,EAAAC,cAACY,EAAD,CAAYmB,KAAMb,EAAK,QAAU,SAAUd,UAAU,SAClDuB,EAAKK,cAAcC,IAAI,SAAA9E,GAAM,OAC5B2C,EAAAC,EAAAC,cAACR,EAAD0C,OAAAC,OAAA,CAAYC,IAAKjF,EAAOuC,KAASvC,iBA3BjCkF,IAAMC,oECfTC,GAFD,SAAA9C,GAAA,IAAGoC,EAAHpC,EAAGoC,MAAH,OAAe/B,EAAAC,EAAAC,cAAA,SAAI6B,EAAMW,UCKjCC,GAAe,CACnBC,SAAU,GACVC,SAAU,IAGNC,8MACJ3B,sBAAawB,MAEbI,WAAa,WACXzB,EAAKC,SAALa,OAAAY,GAAA,EAAAZ,CAAA,GAAmBO,QAGrBM,aAAe,SAAAC,GAAS,IAAAC,EACED,EAAME,OAAtBvD,EADcsD,EACdtD,KAAMwD,EADQF,EACRE,MACd/B,EAAKC,SAALa,OAAAkB,GAAA,EAAAlB,CAAA,GACGvC,EAAOwD,OAIZE,aAAe,SAACL,EAAOM,GACrBN,EAAMO,iBACND,IAAaE,KAAb,eAAAC,EAAAvB,OAAAwB,GAAA,EAAAxB,CAAAyB,GAAA5D,EAAA6D,KAAkB,SAAAC,EAAApE,GAAA,IAAAkC,EAAA,OAAAgC,GAAA5D,EAAA+D,KAAA,SAAAC,GAAA,cAAAA,EAAAC,KAAAD,EAAAE,MAAA,cAAStC,EAATlC,EAASkC,KACzBuC,aAAaC,QAAQ,QAASxC,EAAK2B,WAAWc,OAD9BL,EAAAE,KAAA,EAEV7C,EAAKiD,MAAMC,UAFD,OAGhBlD,EAAKyB,aACLzB,EAAKiD,MAAME,QAAQC,KAAK,KAJR,wBAAAT,EAAAU,SAAAZ,MAAlB,gBAAAa,GAAA,OAAAjB,EAAAkB,MAAApD,KAAAqD,YAAA,OAQFC,aAAe,WAAM,IAAAC,EACY1D,EAAKH,MAA5ByB,EADWoC,EACXpC,SAAUC,EADCmC,EACDnC,SAElB,OADmBD,IAAaC,2EAIzB,IAAAnB,EAAAD,KAAAwD,EACwBxD,KAAKN,MAA5ByB,EADDqC,EACCrC,SAAUC,EADXoC,EACWpC,SAElB,OACE7C,EAAAC,EAAAC,cAAA,OAAKI,UAAU,OACbN,EAAAC,EAAAC,cAAA,MAAII,UAAU,OAAd,UACAN,EAAAC,EAAAC,cAACyB,EAAA,EAAD,CAAUuD,SAAUlG,EAAamG,UAAW,CAAEvC,WAAUC,aACrD,SAACW,EAAD4B,GAA0CA,EAA3BvD,KAA2B,IAArBC,EAAqBsD,EAArBtD,QAASC,EAAYqD,EAAZrD,MAC7B,OACE/B,EAAAC,EAAAC,cAAA,QACEI,UAAU,OACV+E,SAAU,SAAAnC,GAAK,OAAIxB,EAAK6B,aAAaL,EAAOM,KAE5CxD,EAAAC,EAAAC,cAAA,SACEoF,KAAK,OACLzF,KAAK,WACL0F,YAAY,WACZlC,MAAOT,EACP4C,SAAU9D,EAAKuB,eAEjBjD,EAAAC,EAAAC,cAAA,SACEoF,KAAK,WACLzF,KAAK,WACL0F,YAAY,WACZlC,MAAOR,EACP2C,SAAU9D,EAAKuB,eAEjBjD,EAAAC,EAAAC,cAAA,UACEoF,KAAK,SACLG,SAAU3D,GAAWJ,EAAKqD,eAC1BzE,UAAU,kBAHZ,UAOCyB,GAAS/B,EAAAC,EAAAC,cAACwF,GAAD,CAAO3D,MAAOA,eAhEnBQ,IAAMC,WA0EZmD,gBAAW7C,IC/EpBH,GAAe,CACnBC,SAAU,GACVgD,MAAO,GACP/C,SAAU,GACVgD,qBAAsB,IAGlBC,8MACJ3E,sBAAawB,MAEbI,WAAa,WACXzB,EAAKC,SAALa,OAAAY,GAAA,EAAAZ,CAAA,GAAmBO,QAGrBM,aAAe,SAAAC,GAAS,IAAAC,EACED,EAAME,OAAtBvD,EADcsD,EACdtD,KAAMwD,EADQF,EACRE,MACd/B,EAAKC,SAALa,OAAAkB,GAAA,EAAAlB,CAAA,GACGvC,EAAOwD,OAIZE,aAAe,SAACL,EAAO6C,GACrB7C,EAAMO,iBACNsC,IAAarC,KAAb,eAAAC,EAAAvB,OAAAwB,GAAA,EAAAxB,CAAAyB,GAAA5D,EAAA6D,KAAkB,SAAAC,EAAApE,GAAA,IAAAkC,EAAA,OAAAgC,GAAA5D,EAAA+D,KAAA,SAAAC,GAAA,cAAAA,EAAAC,KAAAD,EAAAE,MAAA,cAAStC,EAATlC,EAASkC,KACzBuC,aAAaC,QAAQ,QAASxC,EAAKkE,WAAWzB,OAD9BL,EAAAE,KAAA,EAEV7C,EAAKiD,MAAMC,UAFD,OAGhBlD,EAAKyB,aACLzB,EAAKiD,MAAME,QAAQC,KAAK,KAJR,wBAAAT,EAAAU,SAAAZ,MAAlB,gBAAAa,GAAA,OAAAjB,EAAAkB,MAAApD,KAAAqD,YAAA,OAQFC,aAAe,WAAM,IAAAC,EACyC1D,EAAKH,MAAzDyB,EADWoC,EACXpC,SAAUgD,EADCZ,EACDY,MAAO/C,EADNmC,EACMnC,SAAUgD,EADhBb,EACgBa,qBAGnC,OADGjD,IAAagD,IAAU/C,GAAYA,IAAagD,2EAI5C,IAAAnE,EAAAD,KAAAwD,EACqDxD,KAAKN,MAAzDyB,EADDqC,EACCrC,SAAUgD,EADXX,EACWW,MAAO/C,EADlBoC,EACkBpC,SAAUgD,EAD5BZ,EAC4BY,qBAEnC,OACE7F,EAAAC,EAAAC,cAAA,OAAKI,UAAU,OACbN,EAAAC,EAAAC,cAAA,MAAII,UAAU,OAAd,UACAN,EAAAC,EAAAC,cAACyB,EAAA,EAAD,CACEuD,SAAUhG,EACViG,UAAW,CAAEvC,WAAUgD,QAAO/C,aAE7B,SAACkD,EAADX,GAA0CA,EAA3BvD,KAA2B,IAArBC,EAAqBsD,EAArBtD,QAASC,EAAYqD,EAAZrD,MAC7B,OACE/B,EAAAC,EAAAC,cAAA,QACEI,UAAU,OACV+E,SAAU,SAAAnC,GAAK,OAAIxB,EAAK6B,aAAaL,EAAO6C,KAE5C/F,EAAAC,EAAAC,cAAA,SACEoF,KAAK,OACLzF,KAAK,WACL0F,YAAY,WACZlC,MAAOT,EACP4C,SAAU9D,EAAKuB,eAEjBjD,EAAAC,EAAAC,cAAA,SACEoF,KAAK,QACLzF,KAAK,QACL0F,YAAY,SACZlC,MAAOuC,EACPJ,SAAU9D,EAAKuB,eAEjBjD,EAAAC,EAAAC,cAAA,SACEoF,KAAK,WACLzF,KAAK,WACL0F,YAAY,WACZlC,MAAOR,EACP2C,SAAU9D,EAAKuB,eAEjBjD,EAAAC,EAAAC,cAAA,SACEoF,KAAK,WACLzF,KAAK,uBACL0F,YAAY,mBACZlC,MAAOwC,EACPL,SAAU9D,EAAKuB,eAEjBjD,EAAAC,EAAAC,cAAA,UACEoF,KAAK,SACLG,SAAU3D,GAAWJ,EAAKqD,eAC1BzE,UAAU,kBAHZ,UAOCyB,GAAS/B,EAAAC,EAAAC,cAACwF,GAAD,CAAO3D,MAAOA,eAlFnBQ,IAAMC,WA4FZmD,gBAAWG,IC7FXE,GATK,SAAAxD,GAAS,OAAI,SAAA+B,GAAK,OACpCvE,EAAAC,EAAAC,cAACyB,EAAA,EAAD,CAAOC,MAAOhD,GACX,SAAAe,GAAgC,IAA7BkC,EAA6BlC,EAA7BkC,KAAMC,EAAuBnC,EAAvBmC,QAAS0C,EAAc7E,EAAd6E,QACjB,OAAI1C,EAAgB,KACb9B,EAAAC,EAAAC,cAACsC,EAADJ,OAAAC,OAAA,GAAekC,EAAf,CAAsBC,QAASA,EAASyB,QAASpE,SCI/CqE,GATI,SAAAvG,GAAA,IAAGC,EAAHD,EAAGC,IAAKC,EAARF,EAAQE,KAAMsG,EAAdxG,EAAcwG,MAAd,OACjBnG,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAACK,EAAA,EAAD,CAAMC,GAAE,YAAAH,OAAcT,IACpBI,EAAAC,EAAAC,cAAA,UAAKL,IAEPG,EAAAC,EAAAC,cAAA,mBAAWiG,KCyCAC,8MA3CbjF,MAAQ,CACNkF,cAAe,MAGjBpD,aAAe,SAAAtD,GAAuB,IAApB0G,EAAoB1G,EAApB0G,cAChB/E,EAAKC,SAAS,CACZ8E,2FAIK,IAAA3E,EAAAD,KACC4E,EAAkB5E,KAAKN,MAAvBkF,cACR,OACErG,EAAAC,EAAAC,cAACyB,EAAA,EAAD,KACG,SAAA2E,GAAM,OACLtG,EAAAC,EAAAC,cAAA,OAAKI,UAAU,OACbN,EAAAC,EAAAC,cAAA,oBACAF,EAAAC,EAAAC,cAAA,SACEoF,KAAK,SACLhF,UAAU,SACVT,KAAK,SACL0F,YAAY,qBACZC,SAAQ,eAAA7B,EAAAvB,OAAAwB,GAAA,EAAAxB,CAAAyB,GAAA5D,EAAA6D,KAAE,SAAAC,EAAMb,GAAN,IAAAkC,EAAAvD,EAAA,OAAAgC,GAAA5D,EAAA+D,KAAA,SAAAC,GAAA,cAAAA,EAAAC,KAAAD,EAAAE,MAAA,cACRjB,EAAMqD,UADEtC,EAAAE,KAAA,EAEemC,EAAO1E,MAAM,CAClCA,MAAO5D,EACPmH,UAAW,CAAEqB,WAAYtD,EAAME,OAAOC,SAJhC,OAAA+B,EAAAnB,EAAAwC,KAEA5E,EAFAuD,EAEAvD,KAIRH,EAAKuB,aAAapB,GANV,wBAAAoC,EAAAU,SAAAZ,MAAF,gBAAAa,GAAA,OAAAjB,EAAAkB,MAAApD,KAAAqD,YAAA,KASV9E,EAAAC,EAAAC,cAAA,UACGmG,EAAclE,IAAI,SAAA9E,GAAM,OACvB2C,EAAAC,EAAAC,cAACwG,GAADtE,OAAAC,OAAA,CAAYC,IAAKjF,EAAOuC,KAASvC,iBAlC5BkF,IAAMC,wCCaZmE,GAbE,SAAAC,GAAa,OAAI,SAAApE,GAAS,OAAI,SAAA+B,GAAK,OAClDvE,EAAAC,EAAAC,cAACyB,EAAA,EAAD,CAAOC,MAAOhD,GACX,SAACiD,EAAMC,EAASC,GACf,OAAID,EAAgB,KACb8E,EAAc/E,GACnB7B,EAAAC,EAAAC,cAACsC,EAAc+B,GAEfvE,EAAAC,EAAAC,cAAC2G,EAAA,EAAD,CAAUrG,GAAG,WCGfmC,GAAe,CACnB9C,KAAM,GACNC,SAAU,GACVC,SAAU,YACV+G,YAAa,GACbC,aAAc,GACdnE,SAAU,IAGNoE,8MACJ7F,sBAAawB,MAEbI,WAAa,WACXzB,EAAKC,SAALa,OAAAY,GAAA,EAAAZ,CAAA,GAAmBO,QAGrBoC,aAAe,WAAM,IAAAC,EAQf1D,EAAKH,MANPtB,EAFiBmF,EAEjBnF,KACAC,EAHiBkF,EAGjBlF,SACAC,EAJiBiF,EAIjBjF,SACA+G,EALiB9B,EAKjB8B,YACAC,EANiB/B,EAMjB+B,aACAnE,EAPiBoC,EAOjBpC,SASF,OANG/C,IACAC,IACAC,IACA+G,IACAC,IACAnE,KAILK,aAAe,SAAAC,GAAS,IAAAC,EACED,EAAME,OAAtBvD,EADcsD,EACdtD,KAAMwD,EADQF,EACRE,MACd/B,EAAKC,SAALa,OAAAkB,GAAA,EAAAlB,CAAA,GACGvC,EAAOwD,OAIZ4D,iBAAmB,SAAA/D,GACjB,IAAMgE,EAAahE,EAAMiE,OAAOC,UAChC9F,EAAKC,SAAS,CAAEwF,aAAcG,OAGhC3D,aAAe,SAACL,EAAOmE,GACrBnE,EAAMO,iBACN4D,IAAY3D,KAAK,SAAA/D,GAAcA,EAAXkC,KAClBP,EAAKyB,aACLzB,EAAKiD,MAAME,QAAQC,KAAK,UAI5B4C,YAAc,SAACC,EAAD5D,GAAoC,IAAlB0D,EAAkB1D,EAA1B9B,KAAQwF,UACtBnF,EAAkBqF,EAAMC,UAAU,CAAE5F,MAAOhE,IAA3CsE,cACRqF,EAAME,WAAW,CACf7F,MAAOhE,EACPiE,KAAM,CACJK,cAAa,CAAGmF,GAAHhH,OAAA+B,OAAAsF,GAAA,EAAAtF,CAAiBF,2FAMlCT,KAAKF,SAAS,CACZqB,SAAUnB,KAAK8C,MAAM0B,QAAQ0B,eAAe/E,4CAIvC,IAAAlB,EAAAD,KAAAwD,EAQHxD,KAAKN,MANPtB,EAFKoF,EAELpF,KACAC,EAHKmF,EAGLnF,SACAC,EAJKkF,EAILlF,SACA+G,EALK7B,EAKL6B,YACAC,EANK9B,EAML8B,aACAnE,EAPKqC,EAOLrC,SAGF,OACE5C,EAAAC,EAAAC,cAACyB,EAAA,EAAD,CACEuD,SAAUhH,EACViH,UAAW,CACTtF,OACAC,WACAC,WACA+G,cACAC,eACAnE,YAEFgF,eAAgB,iBAAM,CACpB,CAAEhG,MAAO9C,EAAkBqG,UAAW,CAAEvC,aACxC,CAAEhB,MAAOhD,KAEXiJ,OAAQpG,KAAK6F,aAEZ,SAACD,EAADjC,GAAyCA,EAA3BvD,KAA2B,IAArBC,EAAqBsD,EAArBtD,QAASC,EAAYqD,EAAZrD,MAC5B,OAAID,EAAgB9B,EAAAC,EAAAC,cAAC8B,EAAD,MAElBhC,EAAAC,EAAAC,cAAA,OAAKI,UAAU,OACbN,EAAAC,EAAAC,cAAA,MAAII,UAAU,OAAd,cACAN,EAAAC,EAAAC,cAAA,QACEI,UAAU,OACV+E,SAAU,SAAAnC,GAAK,OAAIxB,EAAK6B,aAAaL,EAAOmE,KAE5CrH,EAAAC,EAAAC,cAAA,SACEoF,KAAK,OACLzF,KAAK,OACL0F,YAAY,cACZC,SAAU9D,EAAKuB,aACfI,MAAOxD,IAETG,EAAAC,EAAAC,cAAA,SACEoF,KAAK,OACLzF,KAAK,WACL0F,YAAY,eACZC,SAAU9D,EAAKuB,aACfI,MAAOvD,IAETE,EAAAC,EAAAC,cAAA,UACEL,KAAK,WACL2F,SAAU9D,EAAKuB,aACfI,MAAOtD,GAEPC,EAAAC,EAAAC,cAAA,UAAQmD,MAAM,aAAd,aACArD,EAAAC,EAAAC,cAAA,UAAQmD,MAAM,SAAd,SACArD,EAAAC,EAAAC,cAAA,UAAQmD,MAAM,UAAd,UACArD,EAAAC,EAAAC,cAAA,UAAQmD,MAAM,SAAd,UAEFrD,EAAAC,EAAAC,cAAA,SACEoF,KAAK,OACLzF,KAAK,cACL0F,YAAY,kBACZC,SAAU9D,EAAKuB,aACfI,MAAOyD,IAET9G,EAAAC,EAAAC,cAAA,SAAO4H,QAAQ,gBAAf,oBACA9H,EAAAC,EAAAC,cAAC6H,GAAA9H,EAAD,CACEJ,KAAK,eACLmI,QAASjB,EACTkB,OAAQ,CAAEC,OAAQxG,EAAKuF,oBAQzBjH,EAAAC,EAAAC,cAAA,UACEuF,SAAU3D,GAAWJ,EAAKqD,eAC1BO,KAAK,SACLhF,UAAU,kBAHZ,UAOCyB,GAAS/B,EAAAC,EAAAC,cAACwF,GAAD,CAAO3D,MAAOA,eApJhBQ,IAAMC,WA8JfmE,MAAS,SAAAV,GAAO,OAAIA,GAAWA,EAAQpE,KAAK8F,gBAA5ChB,CACbhB,aAAWqB,KC7EEhB,iNApGb7E,MAAQ,CACNgH,OAAO,EACPvF,SAAU,MAGZwF,kBAAoB,WAElB,GADAC,QAAQC,IAAIhH,EAAKiD,OACbjD,EAAKiD,MAAM0B,QAAQ0B,eAAgB,KAAAY,EACLjH,EAAKiD,MAAM0B,QAAQ0B,eAA3C/E,EAD6B2F,EAC7B3F,SAAU4F,EADmBD,EACnBC,UACV5I,EAAQ0B,EAAKiD,MAAb3E,IACF6I,EACJD,EAAUE,UAAU,SAAAC,GAAQ,OAAIA,EAAS/I,MAAQA,KAAQ,EAC3D0B,EAAKC,SAAS,CAAE4G,MAAOM,EAAW7F,iBAItCgG,YAAc,SAACC,EAAYC,GACzBxH,EAAKC,SACH,SAAAwH,GAAS,MAAK,CACZZ,OAAQY,EAAUZ,QAEpB,kBAAM7G,EAAK0H,WAAWH,EAAYC,QAItCE,WAAa,SAACH,EAAYC,GACpBxH,EAAKH,MAAMgH,MACbU,IAAanF,KAAb,eAAAC,EAAAvB,OAAAwB,GAAA,EAAAxB,CAAAyB,GAAA5D,EAAA6D,KAAkB,SAAAC,EAAApE,GAAA,OAAAkE,GAAA5D,EAAA+D,KAAA,SAAAC,GAAA,cAAAA,EAAAC,KAAAD,EAAAE,MAAA,cAAAxE,EAASkC,KAAToC,EAAAE,KAAA,EACV7C,EAAKiD,MAAMC,UADD,wBAAAP,EAAAU,SAAAZ,MAAlB,gBAAAa,GAAA,OAAAjB,EAAAkB,MAAApD,KAAAqD,YAAA,IAIAgE,IAAepF,KAAf,eAAAuF,EAAA7G,OAAAwB,GAAA,EAAAxB,CAAAyB,GAAA5D,EAAA6D,KAAoB,SAAAoF,EAAA9D,GAAA,OAAAvB,GAAA5D,EAAA+D,KAAA,SAAAmF,GAAA,cAAAA,EAAAjF,KAAAiF,EAAAhF,MAAA,cAAAiB,EAASvD,KAATsH,EAAAhF,KAAA,EACZ7C,EAAKiD,MAAMC,UADC,wBAAA2E,EAAAxE,SAAAuE,MAApB,gBAAAE,GAAA,OAAAH,EAAApE,MAAApD,KAAAqD,YAAA,OAMJuE,WAAa,SAAC9B,EAAD+B,GAAqC,IAAnBT,EAAmBS,EAA3BzH,KAAQgH,WACrBjJ,EAAQ0B,EAAKiD,MAAb3E,IACA2J,EAAchC,EAAMC,UAAU,CACpC5F,MAAO9D,EACPqH,UAAW,CAAEvF,SAFP2J,UAIRhC,EAAME,WAAW,CACf7F,MAAO9D,EACPqH,UAAW,CAAEvF,OACbiC,KAAM,CACJ0H,UAAUnH,OAAAY,GAAA,EAAAZ,CAAA,GAAMmH,EAAP,CAAkBpD,MAAO0C,EAAW1C,MAAQ,UAK3DqD,aAAe,SAACjC,EAADkC,GAAuC,IAArBX,EAAqBW,EAA7B5H,KAAQiH,aACvBlJ,EAAQ0B,EAAKiD,MAAb3E,IACA2J,EAAchC,EAAMC,UAAU,CACpC5F,MAAO9D,EACPqH,UAAW,CAAEvF,SAFP2J,UAIRhC,EAAME,WAAW,CACf7F,MAAO9D,EACPqH,UAAW,CAAEvF,OACbiC,KAAM,CACJ0H,UAAUnH,OAAAY,GAAA,EAAAZ,CAAA,GAAMmH,EAAP,CAAkBpD,MAAO2C,EAAa3C,MAAQ,gFAKpD,IAAAzE,EAAAD,KAAAuD,EACqBvD,KAAKN,MAAzByB,EADDoC,EACCpC,SAAUuF,EADXnD,EACWmD,MACVvI,EAAQ6B,KAAK8C,MAAb3E,IAER,OACEI,EAAAC,EAAAC,cAACyB,EAAA,EAAD,CACEuD,SAAU5G,EACV6G,UAAW,CAAEvF,MAAKgD,YAClBiF,OAAQpG,KAAK+H,cAEZ,SAAAV,GAAY,OACX9I,EAAAC,EAAAC,cAACyB,EAAA,EAAD,CACEuD,SAAU9G,EACV+G,UAAW,CAAEvF,MAAKgD,YAClBiF,OAAQnG,EAAK2H,YAEZ,SAAAR,GAAU,OACTjG,GACE5C,EAAAC,EAAAC,cAAA,UACEI,UAAU,cACVoJ,QAAS,kBAAMhI,EAAKkH,YAAYC,EAAYC,KAE3CX,EAAQ,SAAW,mBA1Fb5F,IAAMC,YC2DhBmD,gBAzDI,SAAAhG,GAAe,IACxBC,EADwBD,EAAZgK,MACEC,OAAdhK,IACR,OACEI,EAAAC,EAAAC,cAACyB,EAAA,EAAD,CAAOC,MAAO9D,EAAYqH,UAAW,CAAEvF,QACpC,SAAA+D,GAA8B,IAA3B9B,EAA2B8B,EAA3B9B,KAAMC,EAAqB6B,EAArB7B,QAASC,EAAY4B,EAAZ5B,MACjB,OAAID,EAAgB9B,EAAAC,EAAAC,cAAC8B,EAAD,MAChBD,EAAc/B,EAAAC,EAAAC,cAAA,OAAKI,UAAU,OAAf,SAEhBN,EAAAC,EAAAC,cAAA,OAAKI,UAAU,OACbN,EAAAC,EAAAC,cAAA,OACEC,MAAO,CACLC,WAAU,OAAAC,OACRwB,EAAK0H,UAAUzJ,SADP,sCAIZQ,UAAU,iBAEZN,EAAAC,EAAAC,cAAA,OAAKI,UAAU,UACbN,EAAAC,EAAAC,cAAA,OAAKI,UAAU,iBACbN,EAAAC,EAAAC,cAAA,MAAII,UAAU,eACZN,EAAAC,EAAAC,cAAA,cAAS2B,EAAK0H,UAAU1J,OAE1BG,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAAA,cAAS2B,EAAK0H,UAAUxJ,WAE1BC,EAAAC,EAAAC,cAAA,uBACaF,EAAAC,EAAAC,cAAA,cAAS2B,EAAK0H,UAAU3G,WAErC5C,EAAAC,EAAAC,cAAA,yBACeF,EAAAC,EAAAC,cAAA,cAAS2B,EAAK0H,UAAUM,cAEvC7J,EAAAC,EAAAC,cAAA,SACG2B,EAAK0H,UAAUpD,MAAO,IACvBnG,EAAAC,EAAAC,cAAA,QAAM4J,KAAK,MAAMC,aAAW,SAA5B,YAKJ/J,EAAAC,EAAAC,cAAA,cAAYI,UAAU,sBACnBuB,EAAK0H,UAAUzC,aAElB9G,EAAAC,EAAAC,cAAA,MAAII,UAAU,8BAAd,gBACAN,EAAAC,EAAAC,cAAA,OACEI,UAAU,sBACV0J,wBAAyB,CACvBC,OAAQpI,EAAK0H,UAAUxC,gBAG3B/G,EAAAC,EAAAC,cAACgK,GAAD,CAAYtK,IAAKA,UCtBhBuK,GAxBE,SAAAxK,GAAA,IAAGsG,EAAHtG,EAAGsG,QAAH,OACfjG,EAAAC,EAAAC,cAAA,OAAKI,UAAU,OACbN,EAAAC,EAAAC,cAAA,uBACAF,EAAAC,EAAAC,cAAA,sBAAc+F,EAAQ0B,eAAe/E,UACrC5C,EAAAC,EAAAC,cAAA,oBAAY+F,EAAQ0B,eAAe/B,OACnC5F,EAAAC,EAAAC,cAAA,uBAXe,SAAAkK,GACjB,IAAMC,EAAU,IAAIC,KAAKF,GAAMG,mBAAmB,SAC5CC,EAAU,IAAIF,KAAKF,GAAMK,mBAAmB,SAClD,SAAApK,OAAUgK,EAAV,QAAAhK,OAAwBmK,GAQPE,CAAWzE,EAAQ0B,eAAegD,WACjD3K,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAAA,UAAK+F,EAAQ0B,eAAe/E,SAA5B,gBACCqD,EAAQ0B,eAAea,UAAUrG,IAAI,SAAAwG,GAAQ,OAC5C3I,EAAAC,EAAAC,cAAA,MAAIoC,IAAKqG,EAAS/I,KAChBI,EAAAC,EAAAC,cAACK,EAAA,EAAD,CAAMC,GAAE,YAAAH,OAAcsI,EAAS/I,MAC7BI,EAAAC,EAAAC,cAAA,SAAIyI,EAAS9I,OACP,QAGVoG,EAAQ0B,eAAea,UAAUoC,QACjC5K,EAAAC,EAAAC,cAAA,SACEF,EAAAC,EAAAC,cAAA,mECbJ2K,8MACJ1J,MAAQ,CACNvB,IAAK,GACLC,KAAM,GACNC,SAAU,GACVC,SAAU,YACV+G,YAAa,GACbC,aAAc,GACd+D,OAAO,KAGT7H,aAAe,SAAAC,GAAS,IAAAC,EACED,EAAME,OAAtBvD,EADcsD,EACdtD,KAAMwD,EADQF,EACRE,MACd/B,EAAKC,SAALa,OAAAkB,GAAA,EAAAlB,CAAA,GACGvC,EAAOwD,OAIZ4D,iBAAmB,SAAA/D,GACjB,IAAMgE,EAAahE,EAAMiE,OAAOC,UAChC9F,EAAKC,SAAS,CAAEwF,aAAcG,OAGhC6D,aAAe,SAAAC,GACSC,OAAOC,QAC3B,iDAGAF,IAAmBtH,KAAK,SAAA/D,GAAcA,EAAXkC,UAM/B0B,aAAe,SAACL,EAAOiI,GACrBjI,EAAMO,iBACN0H,IAAmBzH,KAAK,SAAAC,GAAc,IAAX9B,EAAW8B,EAAX9B,KACzBwG,QAAQC,IAAIzG,GACZP,EAAK8J,kBAITC,WAAa,SAAAhO,GACXiE,EAAKC,SAALa,OAAAY,GAAA,EAAAZ,CAAA,GAAmB/E,EAAnB,CAA2ByN,OAAO,QAGpCM,WAAa,WACX9J,EAAKC,SAAS,CAAEuJ,OAAO,6EAGhB,IAAApJ,EAAAD,KACCmB,EAAanB,KAAK8C,MAAlB3B,SACAkI,EAAUrJ,KAAKN,MAAf2J,MACR,OACE9K,EAAAC,EAAAC,cAACyB,EAAA,EAAD,CAAOC,MAAO9C,EAAkBqG,UAAW,CAAEvC,aAC1C,SAAAwC,GAA8B,IAA3BvD,EAA2BuD,EAA3BvD,KAAMC,EAAqBsD,EAArBtD,QAASC,EAAYqD,EAAZrD,MACjB,OAAID,EAAgB9B,EAAAC,EAAAC,cAAC8B,EAAD,MAChBD,EAAc/B,EAAAC,EAAAC,cAAA,OAAKI,UAAU,OAAf,SAEhBN,EAAAC,EAAAC,cAAA,UACG4K,GACC9K,EAAAC,EAAAC,cAACoL,GAAD,CACEjO,OAAQqE,EAAKP,MACbiK,WAAY1J,EAAK0J,WACjBnI,aAAcvB,EAAKuB,aACnBgE,iBAAkBvF,EAAKuF,iBACvB1D,aAAc7B,EAAK6B,eAGvBvD,EAAAC,EAAAC,cAAA,2BACE2B,EAAK0J,eAAeX,QACpB5K,EAAAC,EAAAC,cAAA,SACEF,EAAAC,EAAAC,cAAA,sDAGH2B,EAAK0J,eAAepJ,IAAI,SAAA9E,GAAM,OAC7B2C,EAAAC,EAAAC,cAAA,MAAIoC,IAAKjF,EAAOuC,IAAKO,MAAO,CAAEqL,OAAQ,oBACpCxL,EAAAC,EAAAC,cAACK,EAAA,EAAD,CAAMC,GAAE,YAAAH,OAAchD,EAAOuC,MAC3BI,EAAAC,EAAAC,cAAA,SAAI7C,EAAOwC,OAEbG,EAAAC,EAAAC,cAAA,KAAGC,MAAO,CAAEsL,aAAc,MAA1B,UAAyCpO,EAAO8I,OAChDnG,EAAAC,EAAAC,cAACyB,EAAA,EAAD,CACEuD,SAAU1G,EACV2G,UAAW,CAAEvF,IAAKvC,EAAOuC,KACzBgI,eAAgB,iBAAM,CACpB,CAAEhG,MAAOhE,GACT,CAAEgE,MAAOhD,KAEXiJ,OAAQ,SAACN,EAAD0B,GAA2C,IAAzB+B,EAAyB/B,EAAjCpH,KAAQmJ,iBAChBO,EAAmBhE,EAAMC,UAAU,CACzC5F,MAAO9C,EACPqG,UAAW,CAAEvC,cAFP2I,eAIRhE,EAAME,WAAW,CACf7F,MAAO9C,EACPqG,UAAW,CAAEvC,YACbf,KAAM,CACJ0J,eAAgBA,EAAeG,OAC7B,SAAArO,GAAM,OAAIA,EAAOuC,MAAQoL,EAAiBpL,WAMjD,SAACoL,GAAD,IAAmBW,EAAnB7G,UAAA8F,OAAA,QAAAgB,IAAA9G,UAAA,GAAAA,UAAA,GAA2B,GAA3B,OACC9E,EAAAC,EAAAC,cAACF,EAAAC,EAAM4L,SAAP,KACE7L,EAAAC,EAAAC,cAAA,UACEI,UAAU,iBACVoJ,QAAS,kBAAMhI,EAAK2J,WAAWhO,KAFjC,UAMA2C,EAAAC,EAAAC,cAAA,UACEI,UAAU,gBACVoJ,QAAS,kBAAMhI,EAAKqJ,aAAaC,KAEhCW,EAAM7J,QAAU,cAAgB,0BApHjCS,IAAMC,WAmI1BsJ,GAAkB,SAAAxC,GAAA,IACtB/F,EADsB+F,EACtB/F,aACAlG,EAFsBiM,EAEtBjM,OACA4F,EAHsBqG,EAGtBrG,aACAgE,EAJsBqC,EAItBrC,iBACAmE,EALsB9B,EAKtB8B,WALsB,OAOtBpL,EAAAC,EAAAC,cAACyB,EAAA,EAAD,CACEuD,SAAUxG,EACVyG,UAAW,CACTvF,IAAKvC,EAAOuC,IACZC,KAAMxC,EAAOwC,KACbC,SAAUzC,EAAOyC,SACjBC,SAAU1C,EAAO0C,SACjB+G,YAAazJ,EAAOyJ,YACpBC,aAAc1J,EAAO0J,eAGtB,SAAAoE,GAAgB,OACfnL,EAAAC,EAAAC,cAAA,OAAKI,UAAU,oBACbN,EAAAC,EAAAC,cAAA,OAAKI,UAAU,eACbN,EAAAC,EAAAC,cAAA,OAAKI,UAAU,iBACbN,EAAAC,EAAAC,cAAA,QACEmF,SAAU,SAAAnC,GAAK,OAAIK,EAAaL,EAAOiI,IACvC7K,UAAU,uBAEVN,EAAAC,EAAAC,cAAA,yBACAF,EAAAC,EAAAC,cAAA,SACEoF,KAAK,OACLzF,KAAK,OACL0F,YAAY,cACZC,SAAUvC,EACVI,MAAOhG,EAAOwC,OAEhBG,EAAAC,EAAAC,cAAA,SACEoF,KAAK,OACLzF,KAAK,WACL0F,YAAY,eACZC,SAAUvC,EACVI,MAAOhG,EAAOyC,WAEhBE,EAAAC,EAAAC,cAAA,UACEL,KAAK,WACL2F,SAAUvC,EACVI,MAAOhG,EAAO0C,UAEdC,EAAAC,EAAAC,cAAA,UAAQmD,MAAM,aAAd,aACArD,EAAAC,EAAAC,cAAA,UAAQmD,MAAM,SAAd,SACArD,EAAAC,EAAAC,cAAA,UAAQmD,MAAM,UAAd,UACArD,EAAAC,EAAAC,cAAA,UAAQmD,MAAM,SAAd,UAEFrD,EAAAC,EAAAC,cAAA,SACEoF,KAAK,OACLzF,KAAK,cACL0F,YAAY,kBACZC,SAAUvC,EACVI,MAAOhG,EAAOyJ,cAEhB9G,EAAAC,EAAAC,cAAC6H,GAAA9H,EAAD,CACEJ,KAAK,eACLmI,QAAS3K,EAAO0J,aAChBkB,OAAQ,CAAEC,OAAQjB,KAEpBjH,EAAAC,EAAAC,cAAA,WACAF,EAAAC,EAAAC,cAAA,OAAKI,UAAU,iBACbN,EAAAC,EAAAC,cAAA,UAAQoF,KAAK,SAAShF,UAAU,kBAAhC,UAGAN,EAAAC,EAAAC,cAAA,UAAQwJ,QAAS0B,GAAjB,kBAUDP,MClNAlE,MAAS,SAAAV,GAAO,OAAIA,GAAWA,EAAQpE,KAAK8F,gBAA5ChB,CAPC,SAAAhH,GAAA,IAAGsG,EAAHtG,EAAGsG,QAAH,OACdjG,EAAAC,EAAAC,cAAA,OAAKI,UAAU,OACbN,EAAAC,EAAAC,cAAC6L,GAAD,CAAU9F,QAASA,IACnBjG,EAAAC,EAAAC,cAAC8L,GAAD,CAAapJ,SAAUqD,EAAQ0B,eAAe/E,wBCYnC+C,gBAVC,SAAAhG,GAAA,IAAG8E,EAAH9E,EAAG8E,QAAH,OACdzE,EAAAC,EAAAC,cAACyB,EAAA,EAAD,KACG,SAAA2E,GACC,OACEtG,EAAAC,EAAAC,cAAA,UAAQwJ,QAAS,kBAVH,SAACpD,EAAQ7B,GAC7BL,aAAa6H,WAAW,SACxB3F,EAAO4F,aACPzH,EAAQC,KAAK,KAOgByH,CAAc7F,EAAQ7B,KAA7C,eCAF2H,GAAa,SAAAzI,GAAA,IAAGsC,EAAHtC,EAAGsC,QAAH,OACjBjG,EAAAC,EAAAC,cAACmM,EAAA,SAAD,KACErM,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAACoM,GAAA,EAAD,CAAS9L,GAAG,IAAI+L,OAAK,GAArB,SAIFvM,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAACoM,GAAA,EAAD,CAAS9L,GAAG,WAAZ,WAEFR,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAACoM,GAAA,EAAD,CAAS9L,GAAG,eAAZ,eAEFR,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAACoM,GAAA,EAAD,CAAS9L,GAAG,YAAZ,YAEFR,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAACsM,GAAD,QAGJxM,EAAAC,EAAAC,cAAA,sBACWF,EAAAC,EAAAC,cAAA,cAAS+F,EAAQ0B,eAAe/E,aAKzC6J,GAAe,kBACnBzM,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAACoM,GAAA,EAAD,CAAS9L,GAAG,IAAI+L,OAAK,GAArB,SAIFvM,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAACoM,GAAA,EAAD,CAAS9L,GAAG,WAAZ,WAEFR,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAACoM,GAAA,EAAD,CAAS9L,GAAG,WAAZ,WAEFR,EAAAC,EAAAC,cAAA,UACEF,EAAAC,EAAAC,cAACoM,GAAA,EAAD,CAAS9L,GAAG,WAAZ,aAKSkM,GAxDA,SAAA/M,GAAA,IAAGsG,EAAHtG,EAAGsG,QAAH,OACbjG,EAAAC,EAAAC,cAAA,WACG+F,GAAWA,EAAQ0B,eAClB3H,EAAAC,EAAAC,cAACyM,GAAD,CAAY1G,QAASA,IAErBjG,EAAAC,EAAAC,cAAC0M,GAAD,QCcAtG,GAAS,IAAIuG,IAAa,CAC9BC,IAAK,gCAELC,aAAc,CACZC,YAAa,WAEfC,QAAS,SAAAC,GACP,IAAM5I,EAAQF,aAAa+I,QAAQ,SACnCD,EAAUE,WAAW,CACnBC,QAAS,CACPC,cAAehJ,MAIrBiJ,QAAS,SAAA5N,GAAsBA,EAAnB6N,cAERpJ,aAAaC,QAAQ,QAAS,OA0B9BoJ,GAAkBzH,GArBX,SAAArC,GAAA,IAAGa,EAAHb,EAAGa,QAASyB,EAAZtC,EAAYsC,QAAZ,OACXjG,EAAAC,EAAAC,cAACwN,EAAA,EAAD,KACE1N,EAAAC,EAAAC,cAACmM,EAAA,SAAD,KACErM,EAAAC,EAAAC,cAACyN,GAAD,CAAQ1H,QAASA,IACjBjG,EAAAC,EAAAC,cAAC0N,EAAA,EAAD,KACE5N,EAAAC,EAAAC,cAAC2N,EAAA,EAAD,CAAOC,KAAK,IAAIvB,OAAK,EAACwB,UAAW7M,KACjClB,EAAAC,EAAAC,cAAC2N,EAAA,EAAD,CAAOC,KAAK,UAAUC,UAAW3H,KACjCpG,EAAAC,EAAAC,cAAC2N,EAAA,EAAD,CAAOC,KAAK,WAAWE,OAAQ,kBAAMhO,EAAAC,EAAAC,cAAC+N,GAAD,CAAShI,QAASA,OACvDjG,EAAAC,EAAAC,cAAC2N,EAAA,EAAD,CACEC,KAAK,cACLE,OAAQ,kBAAMhO,EAAAC,EAAAC,cAACgO,GAAD,CAAWjI,QAASA,OAEpCjG,EAAAC,EAAAC,cAAC2N,EAAA,EAAD,CAAOC,KAAK,gBAAgBC,UAAWI,KACvCnO,EAAAC,EAAAC,cAAC2N,EAAA,EAAD,CAAOC,KAAK,UAAUE,OAAQ,kBAAMhO,EAAAC,EAAAC,cAACkO,GAAD,CAAQ5J,QAASA,OACrDxE,EAAAC,EAAAC,cAAC2N,EAAA,EAAD,CAAOC,KAAK,UAAUE,OAAQ,kBAAMhO,EAAAC,EAAAC,cAACmO,GAAD,CAAQ7J,QAASA,OACrDxE,EAAAC,EAAAC,cAAC2G,EAAA,EAAD,CAAUrG,GAAG,WAQrB8N,IAASN,OACPhO,EAAAC,EAAAC,cAACyB,EAAA,EAAD,CAAgB2E,OAAQA,IACtBtG,EAAAC,EAAAC,cAACuN,GAAD,OAEFc,SAASC,eAAe","file":"static/js/main.ef6f36c7.chunk.js","sourcesContent":["import { gql } from \"apollo-boost\";\r\n\r\nexport const recipeFragments = {\r\n recipe: gql`\r\n fragment CompleteRecipe on Recipe {\r\n _id\r\n name\r\n imageUrl\r\n category\r\n description\r\n instructions\r\n createdDate\r\n likes\r\n username\r\n }\r\n `,\r\n minRecipe: gql`\r\n fragment MinimalRecipe on Recipe {\r\n _id\r\n name\r\n imageUrl\r\n category\r\n }\r\n `,\r\n like: gql`\r\n fragment LikeRecipe on Recipe {\r\n _id\r\n likes\r\n }\r\n `\r\n};\r\n","import { gql } from \"apollo-boost\";\r\nimport { recipeFragments } from \"./fragments\";\r\n\r\n// Recipes Queries\r\nexport const GET_ALL_RECIPES = gql`\r\n query {\r\n getAllRecipes {\r\n ...MinimalRecipe\r\n }\r\n }\r\n ${recipeFragments.minRecipe}\r\n`;\r\nexport const GET_RECIPE = gql`\r\n query($_id: ID!) {\r\n getRecipe(_id: $_id) {\r\n ...CompleteRecipe\r\n }\r\n }\r\n ${recipeFragments.recipe}\r\n`;\r\nexport const SEARCH_RECIPES = gql`\r\n query($searchTerm: String) {\r\n searchRecipes(searchTerm: $searchTerm) {\r\n _id\r\n name\r\n likes\r\n }\r\n }\r\n`;\r\n\r\n// Recipes Mutations\r\nexport const ADD_RECIPE = gql`\r\n mutation(\r\n $name: String!\r\n $imageUrl: String!\r\n $category: String!\r\n $description: String!\r\n $instructions: String!\r\n $username: String\r\n ) {\r\n addRecipe(\r\n name: $name\r\n imageUrl: $imageUrl\r\n category: $category\r\n description: $description\r\n instructions: $instructions\r\n username: $username\r\n ) {\r\n ...MinimalRecipe\r\n }\r\n }\r\n ${recipeFragments.minRecipe}\r\n`;\r\nexport const LIKE_RECIPE = gql`\r\n mutation($_id: ID!, $username: String!) {\r\n likeRecipe(_id: $_id, username: $username) {\r\n ...LikeRecipe\r\n }\r\n }\r\n ${recipeFragments.like}\r\n`;\r\nexport const UNLIKE_RECIPE = gql`\r\n mutation($_id: ID!, $username: String!) {\r\n unlikeRecipe(_id: $_id, username: $username) {\r\n ...LikeRecipe\r\n }\r\n }\r\n ${recipeFragments.like}\r\n`;\r\nexport const DELETE_USER_RECIPE = gql`\r\n mutation($_id: ID!) {\r\n deleteUserRecipe(_id: $_id) {\r\n _id\r\n }\r\n }\r\n`;\r\nexport const UPDATE_USER_RECIPE = gql`\r\n mutation(\r\n $_id: ID!\r\n $name: String!\r\n $imageUrl: String!\r\n $category: String!\r\n $description: String!\r\n $instructions: String!\r\n ) {\r\n updateUserRecipe(\r\n _id: $_id\r\n name: $name\r\n imageUrl: $imageUrl\r\n category: $category\r\n description: $description\r\n instructions: $instructions\r\n ) {\r\n ...CompleteRecipe\r\n }\r\n }\r\n ${recipeFragments.recipe}\r\n`;\r\n\r\n// User Queries\r\nexport const GET_CURRENT_USER = gql`\r\n query {\r\n getCurrentUser {\r\n username\r\n joinDate\r\n email\r\n favorites {\r\n _id\r\n name\r\n }\r\n }\r\n }\r\n`;\r\nexport const GET_USER_RECIPES = gql`\r\n query($username: String!) {\r\n getUserRecipes(username: $username) {\r\n ...CompleteRecipe\r\n }\r\n }\r\n ${recipeFragments.recipe}\r\n`;\r\n\r\n// User Mutations\r\nexport const SIGNIN_USER = gql`\r\n mutation($username: String!, $password: String!) {\r\n signinUser(username: $username, password: $password) {\r\n token\r\n }\r\n }\r\n`;\r\n\r\nexport const SIGNUP_USER = gql`\r\n mutation($username: String!, $email: String!, $password: String!) {\r\n signupUser(username: $username, email: $email, password: $password) {\r\n token\r\n }\r\n }\r\n`;\r\n","import React from \"react\";\r\nimport posed from \"react-pose\";\r\nimport { Link } from \"react-router-dom\";\r\n\r\nconst RecipeItem = posed.li({\r\n shown: { opacity: 1 },\r\n hidden: { opacity: 0 }\r\n});\r\n\r\nexport default ({ _id, name, imageUrl, category }) => (\r\n \r\n {category}\r\n \r\n \r\n
{name}
\r\n \r\n \r\n \r\n);\r\n","import React from \"react\";\r\nimport { PulseLoader } from \"react-spinners\";\r\n\r\nconst Spinner = () => (\r\n \r\n);\r\n\r\nexport default Spinner;\r\n","import React from \"react\";\nimport posed from \"react-pose\";\nimport \"./App.css\";\n\nimport { Query } from \"react-apollo\";\nimport { GET_ALL_RECIPES } from \"../queries\";\nimport RecipeItem from \"./Recipe/RecipeItem\";\nimport Spinner from \"./Spinner\";\n\nconst RecipeList = posed.ul({\n shown: {\n x: \"0%\",\n staggerChildren: 100\n },\n hidden: {\n x: \"-100%\"\n }\n});\n\nclass App extends React.Component {\n state = {\n on: false\n };\n\n componentDidMount() {\n setTimeout(this.slideIn, 200);\n }\n\n slideIn = () => {\n this.setState({ on: !this.state.on });\n };\n\n render() {\n return (\n \n
\n Find Recipes You Love\n
\n
\n {({ data, loading, error }) => {\n if (loading) return ;\n if (error) return Error
;\n const { on } = this.state;\n return (\n \n {data.getAllRecipes.map(recipe => (\n \n ))}\n \n );\n }}\n \n
\n );\n }\n}\n\nexport default App;\n","import React from \"react\";\r\n\r\nconst Error = ({ error }) => {error.message}
;\r\n\r\nexport default Error;\r\n","import React from \"react\";\r\nimport { withRouter } from \"react-router-dom\";\r\n\r\nimport { Mutation } from \"react-apollo\";\r\nimport { SIGNIN_USER } from \"../../queries\";\r\nimport Error from \"../Error\";\r\n\r\nconst initialState = {\r\n username: \"\",\r\n password: \"\"\r\n};\r\n\r\nclass Signin extends React.Component {\r\n state = { ...initialState };\r\n\r\n clearState = () => {\r\n this.setState({ ...initialState });\r\n };\r\n\r\n handleChange = event => {\r\n const { name, value } = event.target;\r\n this.setState({\r\n [name]: value\r\n });\r\n };\r\n\r\n handleSubmit = (event, signinUser) => {\r\n event.preventDefault();\r\n signinUser().then(async ({ data }) => {\r\n localStorage.setItem(\"token\", data.signinUser.token);\r\n await this.props.refetch();\r\n this.clearState();\r\n this.props.history.push(\"/\");\r\n });\r\n };\r\n\r\n validateForm = () => {\r\n const { username, password } = this.state;\r\n const isInvalid = !username || !password;\r\n return isInvalid;\r\n };\r\n\r\n render() {\r\n const { username, password } = this.state;\r\n\r\n return (\r\n \r\n
Signin
\r\n \r\n {(signinUser, { data, loading, error }) => {\r\n return (\r\n \r\n );\r\n }}\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nexport default withRouter(Signin);\r\n","import React from \"react\";\r\nimport { withRouter } from \"react-router-dom\";\r\n\r\nimport { Mutation } from \"react-apollo\";\r\nimport { SIGNUP_USER } from \"../../queries\";\r\nimport Error from \"../Error\";\r\n\r\nconst initialState = {\r\n username: \"\",\r\n email: \"\",\r\n password: \"\",\r\n passwordConfirmation: \"\"\r\n};\r\n\r\nclass Signup extends React.Component {\r\n state = { ...initialState };\r\n\r\n clearState = () => {\r\n this.setState({ ...initialState });\r\n };\r\n\r\n handleChange = event => {\r\n const { name, value } = event.target;\r\n this.setState({\r\n [name]: value\r\n });\r\n };\r\n\r\n handleSubmit = (event, signupUser) => {\r\n event.preventDefault();\r\n signupUser().then(async ({ data }) => {\r\n localStorage.setItem(\"token\", data.signupUser.token);\r\n await this.props.refetch();\r\n this.clearState();\r\n this.props.history.push(\"/\");\r\n });\r\n };\r\n\r\n validateForm = () => {\r\n const { username, email, password, passwordConfirmation } = this.state;\r\n const isInvalid =\r\n !username || !email || !password || password !== passwordConfirmation;\r\n return isInvalid;\r\n };\r\n\r\n render() {\r\n const { username, email, password, passwordConfirmation } = this.state;\r\n\r\n return (\r\n \r\n
Signup
\r\n \r\n {(signupUser, { data, loading, error }) => {\r\n return (\r\n \r\n );\r\n }}\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nexport default withRouter(Signup);\r\n","import React from \"react\";\r\nimport { Query } from \"react-apollo\";\r\nimport { GET_CURRENT_USER } from \"../queries\";\r\n\r\nconst withSession = Component => props => (\r\n \r\n {({ data, loading, refetch }) => {\r\n if (loading) return null;\r\n return ;\r\n }}\r\n \r\n);\r\n\r\nexport default withSession;\r\n","import React from \"react\";\r\nimport { Link } from \"react-router-dom\";\r\n\r\nconst SearchItem = ({ _id, name, likes }) => (\r\n \r\n \r\n {name}
\r\n \r\n Likes: {likes}
\r\n \r\n);\r\n\r\nexport default SearchItem;\r\n","import React from \"react\";\r\nimport { ApolloConsumer } from \"react-apollo\";\r\nimport { SEARCH_RECIPES } from \"../../queries\";\r\nimport SearchItem from \"./SearchItem\";\r\n\r\nclass Search extends React.Component {\r\n state = {\r\n searchRecipes: []\r\n };\r\n\r\n handleChange = ({ searchRecipes }) => {\r\n this.setState({\r\n searchRecipes\r\n });\r\n };\r\n\r\n render() {\r\n const { searchRecipes } = this.state;\r\n return (\r\n \r\n {client => (\r\n \r\n
Search
\r\n
{\r\n event.persist();\r\n const { data } = await client.query({\r\n query: SEARCH_RECIPES,\r\n variables: { searchTerm: event.target.value }\r\n });\r\n this.handleChange(data);\r\n }}\r\n />\r\n
\r\n {searchRecipes.map(recipe => (\r\n \r\n ))}\r\n
\r\n
\r\n )}\r\n \r\n );\r\n }\r\n}\r\n\r\nexport default Search;\r\n","import React from \"react\";\r\nimport { Query } from \"react-apollo\";\r\nimport { Redirect } from \"react-router-dom\";\r\nimport { GET_CURRENT_USER } from \"../queries\";\r\n\r\nconst withAuth = conditionFunc => Component => props => (\r\n \r\n {(data, loading, error) => {\r\n if (loading) return null;\r\n return conditionFunc(data) ? (\r\n \r\n ) : (\r\n \r\n );\r\n }}\r\n \r\n);\r\n\r\nexport default withAuth;\r\n","import React from \"react\";\r\nimport CKEditor from \"react-ckeditor-component\";\r\nimport { withRouter } from \"react-router-dom\";\r\n\r\nimport { Mutation } from \"react-apollo\";\r\nimport {\r\n ADD_RECIPE,\r\n GET_ALL_RECIPES,\r\n GET_USER_RECIPES,\r\n GET_CURRENT_USER\r\n} from \"../../queries\";\r\nimport Error from \"../Error\";\r\nimport withAuth from \"../withAuth\";\r\nimport Spinner from \"../Spinner\";\r\n\r\nconst initialState = {\r\n name: \"\",\r\n imageUrl: \"\",\r\n category: \"Breakfast\",\r\n description: \"\",\r\n instructions: \"\",\r\n username: \"\"\r\n};\r\n\r\nclass AddRecipe extends React.Component {\r\n state = { ...initialState };\r\n\r\n clearState = () => {\r\n this.setState({ ...initialState });\r\n };\r\n\r\n validateForm = () => {\r\n const {\r\n name,\r\n imageUrl,\r\n category,\r\n description,\r\n instructions,\r\n username\r\n } = this.state;\r\n const isInvalid =\r\n !name ||\r\n !imageUrl ||\r\n !category ||\r\n !description ||\r\n !instructions ||\r\n !username;\r\n return isInvalid;\r\n };\r\n\r\n handleChange = event => {\r\n const { name, value } = event.target;\r\n this.setState({\r\n [name]: value\r\n });\r\n };\r\n\r\n handleEditChange = event => {\r\n const newContent = event.editor.getData();\r\n this.setState({ instructions: newContent });\r\n };\r\n\r\n handleSubmit = (event, addRecipe) => {\r\n event.preventDefault();\r\n addRecipe().then(({ data }) => {\r\n this.clearState();\r\n this.props.history.push(\"/\");\r\n });\r\n };\r\n\r\n updateCache = (cache, { data: { addRecipe } }) => {\r\n const { getAllRecipes } = cache.readQuery({ query: GET_ALL_RECIPES });\r\n cache.writeQuery({\r\n query: GET_ALL_RECIPES,\r\n data: {\r\n getAllRecipes: [addRecipe, ...getAllRecipes]\r\n }\r\n });\r\n };\r\n\r\n componentDidMount() {\r\n this.setState({\r\n username: this.props.session.getCurrentUser.username\r\n });\r\n }\r\n\r\n render() {\r\n const {\r\n name,\r\n imageUrl,\r\n category,\r\n description,\r\n instructions,\r\n username\r\n } = this.state;\r\n\r\n return (\r\n [\r\n { query: GET_USER_RECIPES, variables: { username } },\r\n { query: GET_CURRENT_USER }\r\n ]}\r\n update={this.updateCache}\r\n >\r\n {(addRecipe, { data, loading, error }) => {\r\n if (loading) return ;\r\n return (\r\n \r\n
Add Recipe
\r\n \r\n \r\n );\r\n }}\r\n \r\n );\r\n }\r\n}\r\n\r\nexport default withAuth(session => session && session.data.getCurrentUser)(\r\n withRouter(AddRecipe)\r\n);\r\n","import React from \"react\";\r\nimport { Mutation } from \"react-apollo\";\r\nimport { UNLIKE_RECIPE, LIKE_RECIPE, GET_RECIPE } from \"../../queries\";\r\nimport withSession from \"../withSession\";\r\n\r\nclass LikeRecipe extends React.Component {\r\n state = {\r\n liked: false,\r\n username: \"\"\r\n };\r\n\r\n componentDidMount = () => {\r\n console.log(this.props);\r\n if (this.props.session.getCurrentUser) {\r\n const { username, favorites } = this.props.session.getCurrentUser;\r\n const { _id } = this.props;\r\n const prevLiked =\r\n favorites.findIndex(favorite => favorite._id === _id) > -1;\r\n this.setState({ liked: prevLiked, username });\r\n }\r\n };\r\n\r\n handleClick = (likeRecipe, unlikeRecipe) => {\r\n this.setState(\r\n prevState => ({\r\n liked: !prevState.liked\r\n }),\r\n () => this.handleLike(likeRecipe, unlikeRecipe)\r\n );\r\n };\r\n\r\n handleLike = (likeRecipe, unlikeRecipe) => {\r\n if (this.state.liked) {\r\n likeRecipe().then(async ({ data }) => {\r\n await this.props.refetch();\r\n });\r\n } else {\r\n unlikeRecipe().then(async ({ data }) => {\r\n await this.props.refetch();\r\n });\r\n }\r\n };\r\n\r\n updateLike = (cache, { data: { likeRecipe } }) => {\r\n const { _id } = this.props;\r\n const { getRecipe } = cache.readQuery({\r\n query: GET_RECIPE,\r\n variables: { _id }\r\n });\r\n cache.writeQuery({\r\n query: GET_RECIPE,\r\n variables: { _id },\r\n data: {\r\n getRecipe: { ...getRecipe, likes: likeRecipe.likes + 1 }\r\n }\r\n });\r\n };\r\n\r\n updateUnlike = (cache, { data: { unlikeRecipe } }) => {\r\n const { _id } = this.props;\r\n const { getRecipe } = cache.readQuery({\r\n query: GET_RECIPE,\r\n variables: { _id }\r\n });\r\n cache.writeQuery({\r\n query: GET_RECIPE,\r\n variables: { _id },\r\n data: {\r\n getRecipe: { ...getRecipe, likes: unlikeRecipe.likes - 1 }\r\n }\r\n });\r\n };\r\n\r\n render() {\r\n const { username, liked } = this.state;\r\n const { _id } = this.props;\r\n\r\n return (\r\n \r\n {unlikeRecipe => (\r\n \r\n {likeRecipe =>\r\n username && (\r\n \r\n )\r\n }\r\n \r\n )}\r\n \r\n );\r\n }\r\n}\r\n\r\nexport default withSession(LikeRecipe);\r\n","import React from \"react\";\r\nimport { withRouter } from \"react-router-dom\";\r\nimport { Query } from \"react-apollo\";\r\nimport { GET_RECIPE } from \"../../queries\";\r\nimport LikeRecipe from \"./LikeRecipe\";\r\nimport Spinner from \"../Spinner\";\r\n\r\nconst RecipePage = ({ match }) => {\r\n const { _id } = match.params;\r\n return (\r\n \r\n {({ data, loading, error }) => {\r\n if (loading) return ;\r\n if (error) return Error
;\r\n return (\r\n \r\n
\r\n
\r\n
\r\n
\r\n {data.getRecipe.name}\r\n
\r\n
\r\n {data.getRecipe.category}\r\n
\r\n
\r\n Created by {data.getRecipe.username}\r\n
\r\n
\r\n Created date {data.getRecipe.createdDate}\r\n
\r\n
\r\n {data.getRecipe.likes}{\" \"}\r\n \r\n ♥\r\n \r\n
\r\n
\r\n
\r\n {data.getRecipe.description}\r\n
\r\n
Instructions
\r\n
\r\n
\r\n
\r\n
\r\n );\r\n }}\r\n \r\n );\r\n};\r\n\r\nexport default withRouter(RecipePage);\r\n","import React from \"react\";\r\nimport { Link } from \"react-router-dom\";\r\n\r\nconst formatDate = date => {\r\n const newDate = new Date(date).toLocaleDateString(\"en-US\");\r\n const newTime = new Date(date).toLocaleTimeString(\"en-US\");\r\n return `${newDate} at ${newTime}`;\r\n};\r\n\r\nconst UserInfo = ({ session }) => (\r\n \r\n
User Info
\r\n
Username: {session.getCurrentUser.username}
\r\n
E-mail: {session.getCurrentUser.email}
\r\n
Join Date: {formatDate(session.getCurrentUser.joinDate)}
\r\n
\r\n
\r\n);\r\n\r\nexport default UserInfo;\r\n","import React from \"react\";\r\nimport { Query, Mutation } from \"react-apollo\";\r\nimport { Link } from \"react-router-dom\";\r\nimport CKEditor from \"react-ckeditor-component\";\r\nimport {\r\n GET_USER_RECIPES,\r\n UPDATE_USER_RECIPE,\r\n DELETE_USER_RECIPE,\r\n GET_ALL_RECIPES,\r\n GET_CURRENT_USER\r\n} from \"../../queries\";\r\nimport Spinner from \"../Spinner\";\r\n\r\nclass UserRecipes extends React.Component {\r\n state = {\r\n _id: \"\",\r\n name: \"\",\r\n imageUrl: \"\",\r\n category: \"Breakfast\",\r\n description: \"\",\r\n instructions: \"\",\r\n modal: false\r\n };\r\n\r\n handleChange = event => {\r\n const { name, value } = event.target;\r\n this.setState({\r\n [name]: value\r\n });\r\n };\r\n\r\n handleEditChange = event => {\r\n const newContent = event.editor.getData();\r\n this.setState({ instructions: newContent });\r\n };\r\n\r\n handleDelete = deleteUserRecipe => {\r\n const confirmDelete = window.confirm(\r\n \"Are you sure you want to delete this recipe?\"\r\n );\r\n if (confirmDelete) {\r\n deleteUserRecipe().then(({ data }) => {\r\n //\r\n });\r\n }\r\n };\r\n\r\n handleSubmit = (event, updateUserRecipe) => {\r\n event.preventDefault();\r\n updateUserRecipe().then(({ data }) => {\r\n console.log(data);\r\n this.closeModal();\r\n });\r\n };\r\n\r\n loadRecipe = recipe => {\r\n this.setState({ ...recipe, modal: true });\r\n };\r\n\r\n closeModal = () => {\r\n this.setState({ modal: false });\r\n };\r\n\r\n render() {\r\n const { username } = this.props;\r\n const { modal } = this.state;\r\n return (\r\n \r\n {({ data, loading, error }) => {\r\n if (loading) return ;\r\n if (error) return Error
;\r\n return (\r\n \r\n );\r\n }}\r\n \r\n );\r\n }\r\n}\r\n\r\nconst EditRecipeModal = ({\r\n handleSubmit,\r\n recipe,\r\n handleChange,\r\n handleEditChange,\r\n closeModal\r\n}) => (\r\n \r\n {updateUserRecipe => (\r\n \r\n )}\r\n \r\n);\r\n\r\nexport default UserRecipes;\r\n","import React from \"react\";\r\nimport UserInfo from \"./UserInfo\";\r\nimport UserRecipes from \"./UserRecipes\";\r\nimport withAuth from \"../withAuth\";\r\n\r\nconst Profile = ({ session }) => (\r\n \r\n \r\n \r\n
\r\n);\r\n\r\nexport default withAuth(session => session && session.data.getCurrentUser)(\r\n Profile\r\n);\r\n","import React from \"react\";\r\nimport { withRouter } from \"react-router-dom\";\r\nimport { ApolloConsumer } from \"react-apollo\";\r\n\r\nconst handleSignout = (client, history) => {\r\n localStorage.removeItem(\"token\");\r\n client.resetStore();\r\n history.push(\"/\");\r\n};\r\n\r\nconst Signout = ({ history }) => (\r\n \r\n {client => {\r\n return (\r\n \r\n );\r\n }}\r\n \r\n);\r\n\r\nexport default withRouter(Signout);\r\n","import React, { Fragment } from \"react\";\r\nimport { NavLink } from \"react-router-dom\";\r\nimport Signout from \"../components/Auth/Signout\";\r\n\r\nconst Navbar = ({ session }) => (\r\n \r\n);\r\n\r\nconst NavbarAuth = ({ session }) => (\r\n \r\n \r\n - \r\n \r\n Home\r\n \r\n
\r\n - \r\n Search\r\n
\r\n - \r\n Add Recipe\r\n
\r\n - \r\n Profile\r\n
\r\n - \r\n \r\n
\r\n
\r\n \r\n Welcome, {session.getCurrentUser.username}\r\n
\r\n \r\n);\r\n\r\nconst NavbarUnAuth = () => (\r\n \r\n - \r\n \r\n Home\r\n \r\n
\r\n - \r\n Search\r\n
\r\n - \r\n Signin\r\n
\r\n - \r\n Signup\r\n
\r\n
\r\n);\r\n\r\nexport default Navbar;\r\n","import React, { Fragment } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport {\n BrowserRouter as Router,\n Route,\n Switch,\n Redirect\n} from \"react-router-dom\";\n\nimport \"./index.css\";\nimport App from \"./components/App\";\nimport Signin from \"./components/Auth/Signin\";\nimport Signup from \"./components/Auth/Signup\";\nimport withSession from \"./components/withSession\";\nimport Search from \"./components/Recipe/Search\";\nimport AddRecipe from \"./components/Recipe/AddRecipe\";\nimport RecipePage from \"./components/Recipe/RecipePage\";\nimport Profile from \"./components/Profile/Profile\";\nimport Navbar from \"./components/Navbar\";\n\nimport ApolloClient from \"apollo-boost\";\nimport { ApolloProvider } from \"react-apollo\";\n\nconst client = new ApolloClient({\n uri: \"http://localhost:4444/graphql\",\n //uri: \"https://react-apollo-recipes-hide.herokuapp.com/graphql\",\n fetchOptions: {\n credentials: \"include\"\n },\n request: operation => {\n const token = localStorage.getItem(\"token\");\n operation.setContext({\n headers: {\n authorization: token\n }\n });\n },\n onError: ({ networkError }) => {\n if (networkError) {\n localStorage.setItem(\"token\", \"\");\n }\n }\n});\n\nconst Root = ({ refetch, session }) => (\n \n \n \n \n \n \n } />\n }\n />\n \n } />\n } />\n \n \n \n \n);\n\nconst RootWithSession = withSession(Root);\n\nReactDOM.render(\n \n \n ,\n document.getElementById(\"root\")\n);\n"],"sourceRoot":""}
--------------------------------------------------------------------------------
/public/static/js/runtime~main.a8a9905a.js:
--------------------------------------------------------------------------------
1 | !function(e){function r(r){for(var n,f,i=r[0],l=r[1],a=r[2],c=0,s=[];c