From 849f3dbc4973243abfa1ebca2d6187344b71ca85 Mon Sep 17 00:00:00 2001 From: Brandon Green Date: Fri, 20 Mar 2020 18:21:23 -0500 Subject: [PATCH 1/3] questions answered and packages installed --- client/src/App.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/App.js b/client/src/App.js index 0f6ab595c..6dec6bd02 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -3,7 +3,7 @@ import { BrowserRouter as Router, Route } from "react-router-dom"; import Login from "./components/Login"; import "./styles.scss"; - +//Brandon's function App() { return ( From 64bb749216b410ffdf4ebfdbd4d44f86fce9b17b Mon Sep 17 00:00:00 2001 From: Brandon Green Date: Fri, 20 Mar 2020 19:09:02 -0500 Subject: [PATCH 2/3] Built out login, axios request, axiosWauth, privateRoute --- client/src/components/Login.js | 51 ++++++++++++++++++++++++-- client/src/components/PrivateRoute.js | 23 ++++++++++++ client/src/components/axiosWithAuth.js | 15 ++++++++ 3 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 client/src/components/PrivateRoute.js create mode 100644 client/src/components/axiosWithAuth.js diff --git a/client/src/components/Login.js b/client/src/components/Login.js index cfca99638..c2ac16404 100644 --- a/client/src/components/Login.js +++ b/client/src/components/Login.js @@ -1,14 +1,59 @@ -import React from "react"; +import React, { useState } from "react"; +import axiosWithAuth from './axiosWithAuth'; -const Login = () => { + +// Stage 1 - Authentication +// Build a login form to authenticate your users. + + +const Login = (props) => { // make a post request to retrieve a token from the api // when you have handled the token, navigate to the BubblePage route + + const [login, setLogin] = useState({ username: "", password: "" }); + + const handleLogin = event => { + setLogin({ ...login, [event.target.name]: event.target.value }); + }; + + //Step 1a: Construct an AXIOS request to retrieve a token from the server. You'll use this token to interact with the API + //Step 1b: Save the token to localStorage + const handleSubmit = event => { + event.preventDefault(); + axiosWithAuth() + .post("/api/login", login) + .then(response => { + localStorage.setItem("token", response.data.payload); + props.history.push("/bubbles") + }) + .catch(error => console.log(error.response)); + }; + + return ( <>

Welcome to the Bubble App!

-

Build a login page here

+
+ + + +
); }; + + + + export default Login; diff --git a/client/src/components/PrivateRoute.js b/client/src/components/PrivateRoute.js new file mode 100644 index 000000000..8b07a02bc --- /dev/null +++ b/client/src/components/PrivateRoute.js @@ -0,0 +1,23 @@ +import React from "react"; +import { Route, Redirect } from "react-router-dom"; + + +//Step 1d: Build a `PrivateRoute` component and use it to protect a route that renders the `BubblesPage` component + + +const PrivateRoute = ({ component: Component, ...rest }) => { + return ( + { + if (localStorage.getItem("token")) { + return ; + } else { + return ; + } + }} + /> + ); +}; + +export default PrivateRoute; \ No newline at end of file diff --git a/client/src/components/axiosWithAuth.js b/client/src/components/axiosWithAuth.js new file mode 100644 index 000000000..5e673ced6 --- /dev/null +++ b/client/src/components/axiosWithAuth.js @@ -0,0 +1,15 @@ +import axios from 'axios'; + +//Step 1c: Build a `axiosWithAuth` module to create an instance of axios with the authentication header + +export const axiosWithAuth = () => { + const token = localStorage.getItem("token") + return axios.create({ + baseURL: "http://localhost:5000", + headers: { + Authorization: token + } + }); +}; + +export default axiosWithAuth; \ No newline at end of file From 66ef724a3456677ad1fac8dbccf2603a2a22e863 Mon Sep 17 00:00:00 2001 From: Brandon Green Date: Fri, 20 Mar 2020 20:43:54 -0500 Subject: [PATCH 3/3] get request, saveEdit, deleteColor --- ANSWERS.md | 21 +++++++++++++++ README.md | 30 ++++++++++----------- client/src/App.js | 17 ++++++------ client/src/components/BubblePage.js | 20 +++++++++++++- client/src/components/Bubbles.js | 3 +++ client/src/components/ColorList.js | 41 ++++++++++++++++++++++++----- client/src/components/Login.js | 6 ++++- client/src/index.js | 2 +- 8 files changed, 108 insertions(+), 32 deletions(-) create mode 100644 ANSWERS.md diff --git a/ANSWERS.md b/ANSWERS.md new file mode 100644 index 000000000..f236075c1 --- /dev/null +++ b/ANSWERS.md @@ -0,0 +1,21 @@ +[ ] Explain what a token is used for. + + A token is used to authenticate a user to ensure they are who they claim to be. This allows the user access to otherwise restricted areas of the site. + + +- [ ] What steps can you take in your web apps to keep your data secure? + + You can set up protected routes so certain pages can't be accessed w/o tokens. Store api keys securely. + + +- [ ] Describe how web servers work. + + A web server holds data for websites and communicates with the client through HTTP. When a user inputs a domain name into the browser, the client sends a request to the server to display a webpage. The server then gets the request and delvers the webpage to the client. + + +- [ ] Which HTTP methods can be mapped to the CRUD acronym that we use when interfacing with APIs/Servers. + +Create: (Post)Request- add new data +Read: (Get)Request- retrieve data +Update: (Put)Request- update data +Delete: (Delete)Request- delete data \ No newline at end of file diff --git a/README.md b/README.md index 039d8f2be..056e96198 100644 --- a/README.md +++ b/README.md @@ -36,24 +36,24 @@ Demonstrate your understanding of this Sprint's concepts by answering the follow Follow these steps to set up and work on your project: -- [ ] Create a forked copy of this project. -- [ ] Add PM as collaborator on Github. -- [ ] Clone your OWN version of Repo (Not Lambda's by mistake!). -- [ ] Create a new Branch on the clone: git checkout -b ``. -- [ ] Implement the project on this Branch, committing changes regularly. -- [ ] Push commits: git push origin ``. -- [ ] **RUN** `npm install` at the root to retrieve all the dependencies for the node server. You will not need to create any react apps here nor will you need to install any other dependencies. You should have all you need in this repo. -- [ ] **LOOK** at all the files you've been given for this project. One important file to note is `server.js`. This file contains an **API** that you are going to be interfacing with. Below is documentation on how to interact with the **API**. -- [ ] **RUN** `npm start` to get your API up and running on `http://localhost:5000`. This is the **URL** you're going to need to use within your React app in order to make AJAX requests for data. -- [ ] **LOOK** at your `client` directory and notice it's just a plain ol' React App that we've built using `create-react-app`. -- [ ] **cd** into `client` and run `npm install` to retrieve the client side dependencies. -- [ ] **RUN** `npm start` to fire up your React application. +- [x] Create a forked copy of this project. +- [x] Add PM as collaborator on Github. +- [x] Clone your OWN version of Repo (Not Lambda's by mistake!). +- [x] Create a new Branch on the clone: git checkout -b ``. +- [x] Implement the project on this Branch, committing changes regularly. +- [x] Push commits: git push origin ``. +- [x] **RUN** `npm install` at the root to retrieve all the dependencies for the node server. You will not need to create any react apps here nor will you need to install any other dependencies. You should have all you need in this repo. +- [x] **LOOK** at all the files you've been given for this project. One important file to note is `server.js`. This file contains an **API** that you are going to be interfacing with. Below is documentation on how to interact with the **API**. +- [x] **RUN** `npm start` to get your API up and running on `http://localhost:5000`. This is the **URL** you're going to need to use within your React app in order to make AJAX requests for data. +- [x] **LOOK** at your `client` directory and notice it's just a plain ol' React App that we've built using `create-react-app`. +- [x] **cd** into `client` and run `npm install` to retrieve the client side dependencies. +- [x] **RUN** `npm start` to fire up your React application. Follow these steps for completing your project: -- [ ] Submit a Pull-Request to merge Branch into master (student's Repo). -- [ ] Add your Project Manager as a Reviewer on the Pull-request -- [ ] PM then will count the HW as done by merging the branch back into master. +- [x] Submit a Pull-Request to merge Branch into master (student's Repo). +- [x] Add your Project Manager as a Reviewer on the Pull-request +- [x] PM then will count the HW as done by merging the branch back into master. ## Minimum Viable Product diff --git a/client/src/App.js b/client/src/App.js index 6dec6bd02..8a2925742 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,18 +1,19 @@ -import React, { useState } from "react"; -import { BrowserRouter as Router, Route } from "react-router-dom"; +import React from "react"; +import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; +import PrivateRoute from "./components/PrivateRoute"; +import BubblePage from "./components/BubblePage"; import Login from "./components/Login"; import "./styles.scss"; -//Brandon's + function App() { return (
- - {/* - Build a PrivateRoute component that will - display BubblePage when you're authenticated - */} + + + +
); diff --git a/client/src/components/BubblePage.js b/client/src/components/BubblePage.js index c615c430e..2c38b7ae1 100644 --- a/client/src/components/BubblePage.js +++ b/client/src/components/BubblePage.js @@ -1,14 +1,32 @@ import React, { useState, useEffect } from "react"; -import axios from "axios"; +import axiosWithAuth from "./axiosWithAuth"; import Bubbles from "./Bubbles"; import ColorList from "./ColorList"; + +//Stage 2 - Consuming the API + +//Step 2a: When `BubblePages` renders, make a GET request to fetch the color data for your bubbles. + + const BubblePage = () => { const [colorList, setColorList] = useState([]); // fetch your colors data from the server when the component mounts // set that data to the colorList state property + useEffect(() => { + axiosWithAuth() + .get(`http://localhost:5000/api/colors`) + .then(response => { + // console.log(res) + setColorList(response.data) + }) + .catch(err => console.log(err)); + + }, []) + + return ( <> diff --git a/client/src/components/Bubbles.js b/client/src/components/Bubbles.js index 066cfc4c6..ef5ee626b 100755 --- a/client/src/components/Bubbles.js +++ b/client/src/components/Bubbles.js @@ -2,6 +2,9 @@ import React, { useState, useEffect } from "react"; import { Pack } from "@potion/layout"; import { Svg, Circle } from "@potion/element"; +//Step 2c: Watch and enjoy as your app responds to updates in the data. Check out `Bubbles.js` to see how this is built. + + const Bubbles = ({ colors }) => { const [bubbleData, setBubbleData] = useState([]); useEffect(() => { diff --git a/client/src/components/ColorList.js b/client/src/components/ColorList.js index e09ffafcd..67066164e 100755 --- a/client/src/components/ColorList.js +++ b/client/src/components/ColorList.js @@ -1,11 +1,15 @@ import React, { useState } from "react"; -import axios from "axios"; +import axiosWithAuth from "./axiosWithAuth"; const initialColor = { color: "", code: { hex: "" } }; +//Step 2b: In `ColorList.js`, complete the `saveEdit` and `deleteColor` +//functions to make AJAX requests to the API to edit/delete data + + const ColorList = ({ colors, updateColors }) => { console.log(colors); const [editing, setEditing] = useState(false); @@ -16,17 +20,41 @@ const ColorList = ({ colors, updateColors }) => { setColorToEdit(color); }; + //PUT request const saveEdit = e => { e.preventDefault(); + //console.log(colorToEdit) // Make a put request to save your updated color // think about where will you get the id from... // where is is saved right now? + axiosWithAuth() + .put(`http://localhost:5000/api/colors/${colorToEdit.id}`, colorToEdit) + .then(updateColorList()) + .catch(error => console.log(error.response)); + + }; + + //GET request + const updateColorList = () => { + axiosWithAuth() + .get("http://localhost:5000/api/colors") + .then(response => { + updateColors(response.data); + }); }; + + //DELETE request const deleteColor = color => { // make a delete request to delete this color + // console.log(color) + axiosWithAuth() + .delete(`http://localhost:5000/api/colors/${color.id}`) + .then(updateColorList()) + .catch(err => console.log(err.response)); }; + return (

colors

@@ -35,11 +63,11 @@ const ColorList = ({ colors, updateColors }) => {
  • editColor(color)}> { - e.stopPropagation(); - deleteColor(color) - } - }> - x + e.stopPropagation(); + deleteColor(color) + } + }> + x {" "} {color.color} @@ -86,4 +114,5 @@ const ColorList = ({ colors, updateColors }) => { ); }; + export default ColorList; diff --git a/client/src/components/Login.js b/client/src/components/Login.js index c2ac16404..3b9349365 100644 --- a/client/src/components/Login.js +++ b/client/src/components/Login.js @@ -18,6 +18,8 @@ const Login = (props) => { //Step 1a: Construct an AXIOS request to retrieve a token from the server. You'll use this token to interact with the API //Step 1b: Save the token to localStorage + + //POST request const handleSubmit = event => { event.preventDefault(); axiosWithAuth() @@ -33,16 +35,18 @@ const Login = (props) => { return ( <>

    Welcome to the Bubble App!

    -
    + diff --git a/client/src/index.js b/client/src/index.js index f283ca544..cd3cdc7b2 100755 --- a/client/src/index.js +++ b/client/src/index.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React from "react"; import ReactDOM from "react-dom"; import App from "./App";