From 291a00346a5263564043c603e2e7248d1e477fc2 Mon Sep 17 00:00:00 2001 From: Jess Mear Date: Wed, 8 Mar 2017 07:20:05 -0700 Subject: [PATCH 1/8] functionality largely implemented, missing termcontainer component --- README.md | 56 ++++++++++++++++++- data/db.json | 118 ++++++++++++++++++++++++++++++++++----- public/avatars/pam.png | Bin 0 -> 5361 bytes public/avatars/penny.png | Bin 0 -> 5667 bytes public/index.html | 2 +- src/AddDefinition.js | 63 ++++++++++++++++++--- src/AddTerm.js | 38 +++++++++++-- src/App.js | 44 +++++++++++++-- src/Definition.js | 30 +++++++++- src/Dictionary.js | 37 ++++++------ src/Layout.js | 7 ++- src/Login.js | 7 ++- src/Navigation.js | 12 +++- src/Term.js | 31 ++++++++-- src/TermContainer.js | 35 ++++++++++-- src/{ => css}/App.css | 0 src/{ => css}/index.css | 34 +++++++++++ src/index.js | 2 +- src/{ => svg}/logo.svg | 0 19 files changed, 445 insertions(+), 71 deletions(-) create mode 100644 public/avatars/pam.png create mode 100644 public/avatars/penny.png rename src/{ => css}/App.css (100%) rename src/{ => css}/index.css (58%) rename src/{ => svg}/logo.svg (100%) diff --git a/README.md b/README.md index f3c2491..d9bb2ae 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # Dev Dictionary +# After Installation QuickStart +npm run json-server // starts API server +PORT=4500 npm start // starts front-end server + + + ## TL;DR If you are considering taking on this challenge, you'll be writing some code to fetch data and feeding it to pre-built components. @@ -30,7 +36,7 @@ Expected time: 2-8 hours This spins up a simple API server, using [json-server](https://github.com/typicode/json-server). It serves the data from `data/db.json`. It runs on port 4501, but you can change that in `package.json`. -1. Familiarize yourself with URLs for fetching data from json-server. Read their doc. It's simple. E.g. fetching terms would use `http://localhost:4501/terms`. To embed definitions, use `http://localhost:4501/terms?_expand=definitions`. +1. Familiarize yourself with URLs for fetching data from json-server. Read their doc. It's simple. E.g. fetching terms would use `http://localhost:4501/terms`. To embed definitions, use `http://localhost:4501/terms?_embed=definitions`. 1. Start the frontend dev server. $ PORT=4500 npm start @@ -77,6 +83,9 @@ The point of the project is for us to have a well known app idea at the start, s Implement edit and delete for terms and definitions. +Add Giphy to definitions: +'http://api.giphy.com/v1/gifs/search?q=' + searchPhrase + '&rating=g&api_key=dc6zaTOxFJmzC' + # Need more control? This project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app), which doesn't allow configuration by design. But you can provide configuration by first "ejecting" from create-react-app. Search Google for "create-react-app eject". @@ -92,4 +101,47 @@ The idea for the site came from Jess in Eric McKay's Learn Web Development meetu I like the light-hearted definitions too. Here are a few responses to "What does full stack mean to you?" from @samrocksc on azwebdevs slack #random on 2017-01-12: - Full stack means not having to get your changes past the Java team (Joe Fleming) - Full stack means your cheapass boss won't pay a proper devops person and makes you do that part too (Luis Montes) -- Full stack means adding an extra line to your resume after reading a hello world tutorial on Express. (Nick Klepinger) \ No newline at end of file +- Full stack means adding an extra line to your resume after reading a hello world tutorial on Express. (Nick Klepinger) + +# Sample API Calls + +NOTE: are in plain text, no quotes + +All terms: +http://localhost:4501/terms + +All definitions: +http://localhost:4501/definitions + +All users: +http://localhost:4501/users + + +All terms and definitions: +http://localhost:4501/terms?_embed=definitions + +All users and definitions: +http://localhost:4501/users?_embed=definitions + +All users and terms: +http://localhost:4501/users?_embed=terms + + +Seerch for a specific term: +http://localhost:4501/terms?q= + +Search for a specific term and get all matching and their definitions: +http://localhost:4501/terms?q=&_embed=definitions + +Search for a specific definition: +http://localhost:4501/definitions?q= + +Search for a specific user: +http://localhost:4501/users?q= + +Search for a specific user and get all matching and their definitions: +http://localhost:4501/users?q=&_embed=definitions + +Search for a specific user and get all matching and their terms: +http://localhost:4501/users?q=&_embed=terms + diff --git a/data/db.json b/data/db.json index 1346f8b..a156940 100644 --- a/data/db.json +++ b/data/db.json @@ -1,17 +1,105 @@ { - "terms": [ - { "id": 1, "name": "Full stack", "userId": 1 }, - { "id": 2, "name": "Design pattern", "userId": 2 } - ], - "definitions": [ - { "id": 1, "content": "Able to wear a stack of responsibility hats", "termId": 1, "userId": 1 }, - { "id": 2, "content": "Fully able to do the part of the job you like, as well as the stack of crud you don't", "termId": 1, "userId": 2 }, - { "id": 3, "content": "3rd definition", "termId": 2, "userId": 1 }, - { "id": 4, "content": "4th definition", "termId": 2, "userId": 2 } - ], - "users": [ - { "id": 1, "name": "Alice", "avatarUrl": "alice.png" }, - { "id": 2, "name": "Dilbert", "avatarUrl": "dilbert.png" }, - { "id": 3, "name": "Wally", "avatarUrl": "wally.png" } - ] + "terms": [ + { + "id": 1, + "name": "Full stack", + "userId": 1 + }, + { + "id": 2, + "name": "Design pattern", + "userId": 2 + }, + { + "id": 3, + "name": "Smoke test", + "userId": 4 + }, + { + "id": 4, + "name": "Unit test", + "userId": 4 + }, + { + "name": "Tech debt", + "userId": 4, + "id": 5 + }, + { + "name": "Waterfall", + "userId": 4, + "id": 6 + }, + { + "name": "UX", + "userId": 3, + "id": 7 + } + ], + "definitions": [ + { + "id": 1, + "content": "Able to wear a stack of responsibility hats", + "termId": 1, + "userId": 1 + }, + { + "id": 2, + "content": "Fully able to do the part of the job you like, as well as the stack of crud you don't", + "termId": 1, + "userId": 2 + }, + { + "id": 3, + "content": "3rd definition", + "termId": 2, + "userId": 4 + }, + { + "id": 4, + "content": "4th definition", + "termId": 2, + "userId": 2 + }, + { + "id": 5, + "content": "A quick manual test done immediately after pushing a change to the live site to check for any obvious problems. Often followed up with formal QA.", + "termId": 3, + "userId": 4 + }, + { + "id": 6, + "content": "Testing set up to check for proper output throughout an application to catch accidental errors as soon as they are introduced.", + "termId": 4, + "userId": 4 + }, + { + "id": 7, + "content": "That thing everyone says we should do that we never have time to get around doing even though it would probably save us time in the long run. See also 'tech debt'.", + "termId": 4, + "userId": 4 + } + ], + "users": [ + { + "id": 1, + "name": "Alice", + "avatarUrl": "alice.png" + }, + { + "id": 2, + "name": "Dilbert", + "avatarUrl": "dilbert.png" + }, + { + "id": 3, + "name": "Wally", + "avatarUrl": "wally.png" + }, + { + "id": 4, + "name": "Penny", + "avatarUrl": "penny.png" + } + ] } \ No newline at end of file diff --git a/public/avatars/pam.png b/public/avatars/pam.png new file mode 100644 index 0000000000000000000000000000000000000000..f2011a9cc4acddd088c368e77d9b51477a76c54f GIT binary patch literal 5361 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 - +