diff --git a/news-site-v/.gitignore b/news-site-v/.gitignore new file mode 100644 index 0000000..8491b15 --- /dev/null +++ b/news-site-v/.gitignore @@ -0,0 +1,18 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +!public/* + +# dependencies +node_modules +package-lock.json + +# testing +coverage + +# production +build + +# misc +.DS_Store +.env +npm-debug.log diff --git a/news-site-v/README.md b/news-site-v/README.md new file mode 100644 index 0000000..6d1ba7c --- /dev/null +++ b/news-site-v/README.md @@ -0,0 +1,188 @@ +# News Site Part V + +## High Level Objectives +1. Create ability to add an article to the news site +2. Add a `log in` UI (no real functionality yet) + +## Quick Review + +Let's first review a few HTTP methods: +- **GET:** Grabbing data and resources from a server. Remember that you can add filters into the query string. An example: `GET http://localhost:3001/api/articles/?filter={"where": {"section": "opinion"}}` +- **POST:** Creates new records. You will use this today to create a new article +- **PATCH / PUT:** Updating a record that already exists. +- **DELETE:** Deletes a record + +We've become kind of familiar with the `fetch` method for JS. We have been using it for mostly `GET` requests. Here is an example: + +```js +fetch('https://jsonip.com') // makes a request to this URL + .then((response) => response.json()) // after the request is made, you THEN get a Promise as a response. After I receive the Promise, I turn it into a JSON object + .catch((error) => console.log(error)) // in the case that there's an error, CATCH it and console the error +``` + +More popularly, however, we can use `fetch` to create `POST` requests. Here is an example: + +```javascript +const articleObject = { title: 'test', byline: 'byline test', abstract: 'asdf' } + +fetch('http://localhost:3001/api/articles', { + headers: { + 'Content-Type': 'application/json' + }, + method: 'POST', + body: JSON.stringify(articleObject) // whenever you make an API request, you have to stringify your request +}).then((response) => { + return response.json() +}).then((json) => { + console.log(json) +}) +``` + +There are a number of differences between the `GET` and `POST` examples with fetch. The `POST` `fetch` request includes `headers`, `method`, and `body`. `headers` contains data that the server needs to know what type of data it's about to receive. The `method` tells the server what kind of request is being made. Finally, the `body` contains the contents (i.e., `body`) of the request you are making. + +## Initial Setup + +If you'd like to use your own code from `news-site-IV`, you can copy and paste the entire `src` directory from the `news-site-IV` repo and replace the starter `src` code in this repo. + +**After copying over your source directory, run `npm run update-tests`.** This command will update a few unit tests in your `src/` directory. + +Once you've performed the steps above, run `npm install ; npm run start` - verify that no errors appear in your browser console or terminal, and that your app functions the same as it did in the last challenge. Also try running `npm run test` - you should see a single failure coming from the `ArticlesAPI.js` module. This is to be expected - the test that's failing is because the functionality the test is attempting to run hasn't been built yet - we'll be doing that next. + +## Testing Fetch +Let's test this `fetch` command in the console: + +```js +const articleObject = { title: 'test', byline: 'byline test', abstract: 'asdf' } + +fetch('http://localhost:3001/api/articles', { + headers: { + 'Content-Type': 'application/json' + }, + method: 'POST', + body: JSON.stringify(articleObject) // whenever you make an API request, you have to stringify your request +}).then((response) => { + return response.json() +}).then((json) => { + console.log(json) +}) +``` + +If you refresh the page and scroll to the bottom, you'll see our new `test` article! What if you have a bad request? Let's try passing an incomplete data set: + +```javascript +const articleObject = { byline: 'byline test', abstract: 'asdf' } + +fetch('http://localhost:3001/api/articles', { + headers: { + 'Content-Type': 'application/json' + }, + method: 'POST', + body: JSON.stringify(articleObject) // whenever you make an API request, you have to stringify your request +}).then((response) => { + return response.json() +}).then((json) => { + console.log(json) +}) +``` + +Check the console for some errors. Part of your job today is to handle these types of issues/errors. + +## Release 0: ArticlesAPI.addArticle() + +To start, let's build a function within `ArticlesAPI.js` that we can use to send article data to the API. + +Up until now, we've only used Fetch to make `GET` requests to our API (this is the default request method `fetch` uses). When reading data from an API (such as reading a list of articles), it's customary to use the GET request method. When writing/submitting data, it's customary to use the POST request method - POST allows data to be sent securely. + +To send a POST request, you will still use `fetch` by passing some additional data that will instruct it to use the POST request method. Posting data to our API would look something like this: + +```javascript +return fetch('http://localhost:3001/api/articles', { + headers: { + 'Content-Type': 'application/json' + }, + method: "POST", + body: JSON.stringify(articleObject) +}) +``` + +Note the second argument passed to `fetch` - an object of options. This object allows you to control specific aspects of the request that's made, such as headers and the request method. + +Headers allow you to pass additional information with a request. Here, we're including a header that says that we are sending JSON. Headers can also include things like authentication tokens, instructions on how to handle cached files, to name a few. + +The `method` key in the options object defines the type of request that should be made. By default, this is set to `GET` - here, we're setting it to `POST`. + +Lastly, the `body` key contains the `POST` payload - the data that will be sent to the API, and then processed and stored in a database. The value of this property should be a JSON-encoded string. + +In `ArticlesAPI.js`, you should define a new function called `addArticle`. This function should accept a single parameter - `articleObject`. This function should perform a Fetch call similar to the one above - you'll want to convert the object that's passed into the function into a JSON string, and set the `body` property of the options object (the second parameter in the Fetch call) to this JSON string. + +A new test has been added to verify this behavior - once all of your unit tests succeed, you may continue to the next section. + + +## Release 1: The Add Article Page +The Add Article Page will be used to display a form that will allow users to submit an article. Let's first begin by creating the route and the page. + +The route that should display the Add Article Page should be `/add-article` - no parameters are necessary. + +Once your page component and route are established, add a link to the Nav component that points to this page. + +Once you've added the "Add An Article" link to your AppNav.js component, verify that clicking the link redirects you to the appropriate route. + +Lastly, let's create the content that `AddArticlePage.js` should render. + +We need to render a `
+ +The event object that's passed into your event handler will contain references to all of the input fields through a property called "elements". Example: + + handleFormSubmit = (event) => { + console.log(event.target.elements[0].value) // This will print out the value contained within the first input field on the form. + } + +Within your `