{"componentChunkName":"component---src-templates-assignment-template-js","path":"/assignments/assignment02","webpackCompilationHash":"041090671d318979d692","result":{"data":{"markdownRemark":{"htmlAst":{"type":"root","children":[{"type":"element","tagName":"h4","properties":{"id":"goals"},"children":[{"type":"element","tagName":"a","properties":{"href":"#goals","ariaLabel":"goals permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Goals"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Implement basic React components with state and callbacks"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Use a linter and code formatter to write more consistent, more maintainable, higher quality, code"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The goal of this assignment is to learn the basics of creating a single page web application (SPA) with React. In this and the next few assignments, you will be developing a miniature version of Wikipedia named \"Simplepedia\". Implementing Simplepedia will provide hands-on experience developing a full single page web application in preparation for completing your large project. Simplepedia was first developed with Davin Chia in Fall 2016 as an independent study."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"As with previous assignments, you will need to do additional research (online) to successfully complete the assignment."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"prerequisites"},"children":[{"type":"element","tagName":"a","properties":{"href":"#prerequisites","ariaLabel":"prerequisites permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Prerequisites"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"We created the assignment skeleton with "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"create-react-app"}]},{"type":"text","value":" (its structure should become very familiar to us). We have removed some of the unneeded features and added some styling and seed data."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Click the GitHub classroom "},{"type":"element","tagName":"a","properties":{"href":"https://classroom.github.com/a/KI_QMrOh"},"children":[{"type":"text","value":"link"}]},{"type":"text","value":" and then clone repository GitHub classroom creates to your local computer as you did in previous assignments. "}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Update the author information in the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"package.json"}]},{"type":"text","value":" file"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Install the module dependencies with "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"npm install"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"When you install the dependencies you may get warnings like below. These can safely be ignored."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"npm WARN ts-pnp@1.0.0 requires a peer of typescript@* but none is installed. You must install peer dependencies yourself."}]}]}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Once you have the dependencies installed you can start the development server with "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"npm start"}]},{"type":"text","value":". Practice good Git practices by creating a working branch for your features."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"background"},"children":[{"type":"element","tagName":"a","properties":{"href":"#background","ariaLabel":"background permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Background"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"This week, you will be constructing the basic interface for looking at a collection of articles. Here is the goal you are aiming for:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"span","properties":{"className":["gatsby-resp-image-wrapper"],"style":"position: relative; display: block; margin-left: auto; margin-right: auto;  max-width: 650px;"},"children":[{"type":"text","value":"\n      "},{"type":"element","tagName":"a","properties":{"className":["gatsby-resp-image-link"],"href":"/~candrews/classes/cs312-f19/static/42a0ed714bd37abefeed5488b1b73f66/7bd40/assignment02-simplepedia.png","style":"display: block","target":"_blank","rel":["noopener"]},"children":[{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["gatsby-resp-image-background-image"],"style":"padding-bottom: 80.40313549832027%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAAsSAAALEgHS3X78AAABtUlEQVQ4y6VTi26iUBDl//+pGtAW1Phgi00qtCiCVdY32Au+zs4MddMuaWLdm4xzkeHM45zRzuczvjt5nsPu2eg7fTiOI6ay7EvMv99r/KOUgnpXSNMUSZKI8X29XuPx0YFt2+j1egTYx2q1RrLdSszhcCiBalzFcDjEeBxiMpkgpUClMux2O0m03+/lQ7bj8ShVX97xcwlwtVzCMAy02x3J/tNTapnbqtVquL9/gOt61Obmb+A1VqqQAVutlgycve/70tJn0J8cbbFYoNFoYPA8wHQ6RUazOZ1OpSquBtwSY7b9C91uFzkR8N1srgZkUizLQuWugldq98LszS1vNxtiuC16m8/nZAtkH+K9pUrtnQjwX30Ewbgkh1tMhM2CjqKIQAOEUYjbpvdRIbPqui4874X8AN6LR1szlgRRGCIYjRCSZxvRnTvhjni7Civub29TUYe2SxNUqzrMBwumaaJer0PXdVQqVfH8n2HoZDU0m02SWLPwVkPk1ul0YBKpT/2nAjDLVJF5FEhmrozJiePfmM1mWJIKYvJxHMuOM2E8JvYXRfBznuXFDC8LzwG8IZzlf84fdRrNaWVPGuUAAAAASUVORK5CYII='); background-size: cover; display: block;"},"children":[]},{"type":"text","value":"\n  "},{"type":"element","tagName":"img","properties":{"className":["gatsby-resp-image-image"],"alt":"Simplepedia","title":"Simplepedia","src":"/~candrews/classes/cs312-f19/static/42a0ed714bd37abefeed5488b1b73f66/dbb61/assignment02-simplepedia.png","srcSet":["/~candrews/classes/cs312-f19/static/42a0ed714bd37abefeed5488b1b73f66/19bd1/assignment02-simplepedia.png 163w","/~candrews/classes/cs312-f19/static/42a0ed714bd37abefeed5488b1b73f66/d3bcb/assignment02-simplepedia.png 325w","/~candrews/classes/cs312-f19/static/42a0ed714bd37abefeed5488b1b73f66/dbb61/assignment02-simplepedia.png 650w","/~candrews/classes/cs312-f19/static/42a0ed714bd37abefeed5488b1b73f66/7bd40/assignment02-simplepedia.png 893w"],"sizes":["(max-width:","650px)","100vw,","650px"],"loading":"lazy"},"children":[]},{"type":"text","value":"\n  "}]},{"type":"text","value":"\n    "}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Along the top of the page, there is a list of sections. Clicking on one of the sections displays the appropriate list of articles. Clicking on an article title displays the contents of the article at the bottom of the page. All of the articles have a title, some contents, and a modification date."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"As with previous assignments an initial set of (failing) tests are provided as part of the skeleton (run with "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"npm test"}]},{"type":"text","value":"). These tests are intended to help you as you develop your application and to ensure that the grading scripts can successfully test your assignment. Code that passes all of the provided tests is not guaranteed to be correct. However, code that fails one or more these tests does not meet the specification. Testing React applications is a future topic and so you are not expected to write any additional tests for this assignment."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"You will notice that there is already a fair amount of code present in "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"App.js"}]},{"type":"text","value":". In order for this application to be interesting, we need to load in some data. We do this by directly importing "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"seed.json"}]},{"type":"text","value":", which contains our data. The "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"mapFromArticleList"}]},{"type":"text","value":" function transforms a list of articles into an "},{"type":"element","tagName":"a","properties":{"href":"https://immutable-js.github.io/immutable-js/docs/#/Map"},"children":[{"type":"text","value":"Immutable Map"}]},{"type":"text","value":". This is a data structure that works a little bit like a JavaScript object or a Python dictionary, in that it has key value pairs, but the access methods are a little different. An important feature, is that it is "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"immutable"}]},{"type":"text","value":" -- in other words, any changes you make to it result in a new structure. This is a nice feature for an element we are using for application state since all of our state changes in React should be through its explicit mechanisms. In this particular case, the articles have been grouped together into sections based on the first letter of their title, so the keys of the map are the single letter section names and the values are "},{"type":"element","tagName":"a","properties":{"href":"https://immutable-js.github.io/immutable-js/docs/#/List"},"children":[{"type":"text","value":"Immutable Lists"}]},{"type":"text","value":" of the articles themselves (which are not ordered)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The other new feature that you will find in the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"App"}]},{"type":"text","value":" component is an "},{"type":"element","tagName":"a","properties":{"href":"https://reactjs.org/docs/hooks-effect.html"},"children":[{"type":"text","value":"effect hook"}]},{"type":"text","value":". In class we looked at "},{"type":"element","tagName":"a","properties":{"href":"https://reactjs.org/docs/hooks-state.html"},"children":[{"type":"text","value":"state hooks"}]},{"type":"text","value":", which give us access to the component's state. An effect hook allows us to add side effects based on the life cycle of the component. In other words, sometimes we have some code that only should be run occasionally. In this instance, we only want to load the data into the state when the component is created, and not for subsequent renders. This is what the empty array in the last argument of "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"useEffect"}]},{"type":"text","value":" is telling React. That array is the list of state variables to watch for changes. Since the array is empty, it never runs again after the first time. "}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"assignment"},"children":[{"type":"element","tagName":"a","properties":{"href":"#assignment","ariaLabel":"assignment permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Assignment"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"part-1-the-article-browser"},"children":[{"type":"element","tagName":"a","properties":{"href":"#part-1-the-article-browser","ariaLabel":"part 1 the article browser permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Part 1: The article browser"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"With React, the first step is to break the interface down into components:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"span","properties":{"className":["gatsby-resp-image-wrapper"],"style":"position: relative; display: block; margin-left: auto; margin-right: auto;  max-width: 650px;"},"children":[{"type":"text","value":"\n      "},{"type":"element","tagName":"a","properties":{"className":["gatsby-resp-image-link"],"href":"/~candrews/classes/cs312-f19/static/5cb92d51601174d53acaad33238977f8/7bd40/assignment02-simplepedia-components.png","style":"display: block","target":"_blank","rel":["noopener"]},"children":[{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["gatsby-resp-image-background-image"],"style":"padding-bottom: 80.40313549832027%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAAsSAAALEgHS3X78AAACc0lEQVQ4y52Ta1PaQBhG+f9/op32Yzt2rHZqq6MCEkEgXGKCASEkJOFmBEEhIZLTTegonVrb6e6cffbdy7O72U2K0IdgCasY/5nHFeH8DuWiQEMuo8mlhGA2TfqSMfE8fyF0sdHHgFTjUKVeMKnl2lSyLcqZZoKcbVI8abDz7jsf3x7w4c1XPr0/5EK0ldM6shijXVg0ZRdddtDKQqUuqW/5Njv1ITsVl8/KiBNzSdYJSVsBGXuF1I84H7BhCDl3zWnSF5IXcfFGMAbJg3RzSkrVa5QKEtVKifvZhJdTtMVL7eskcu5vSdU1hXMpTzabo9m8ZjK5SzrX6+ivRFGMsIxjMcecCkOloVCpVFEUhWKxiGEY3D88bNaPtia9QlzEYsWG1csqcrmMrusMBgP85VKsvt4yi3gt/Wao6iqaqiHLMsFqtTXwdaM/GtZUcSnFEkdHR3Q6BovFgtVP4+1dvoo40fpphy0NVblEVVVxIZOEMAz5n9Sbi2ej1WS0RkMYavj+UuAzn8+ZzWb/zt0dU3GRnb5D6tT8wtfLA/aVPXYru+zX9yjfyNQmNaqT6pZu6s/6a70S602RVCu8xjIs2t027c41nW4Hx3XoD/oCF9vp4fbdhJ7dwxZ9pmVi9SwsW9AzMQXe2MNDfMOrmcbZSY6cJIkHLnGWPSN9mub4+JhToXFbJp0mk8lQKFw8k88nxE9OOj/nStXxHj1SzaWOa/YxTQtD3LLjuHg3HuPRmOFwxOR2wmg4ZCRif+kT+AGrYJVoHIfiRQRBwDpYcxvFf0pYx/ANWn6Lq/sruo9dxGFxcQRxudE42/Sesp1gb8U2RmTwAyL6qWo7gGXOAAAAAElFTkSuQmCC'); background-size: cover; display: block;"},"children":[]},{"type":"text","value":"\n  "},{"type":"element","tagName":"img","properties":{"className":["gatsby-resp-image-image"],"alt":"Simplepedia","title":"Simplepedia","src":"/~candrews/classes/cs312-f19/static/5cb92d51601174d53acaad33238977f8/dbb61/assignment02-simplepedia-components.png","srcSet":["/~candrews/classes/cs312-f19/static/5cb92d51601174d53acaad33238977f8/19bd1/assignment02-simplepedia-components.png 163w","/~candrews/classes/cs312-f19/static/5cb92d51601174d53acaad33238977f8/d3bcb/assignment02-simplepedia-components.png 325w","/~candrews/classes/cs312-f19/static/5cb92d51601174d53acaad33238977f8/dbb61/assignment02-simplepedia-components.png 650w","/~candrews/classes/cs312-f19/static/5cb92d51601174d53acaad33238977f8/7bd40/assignment02-simplepedia-components.png 893w"],"sizes":["(max-width:","650px)","100vw,","650px"],"loading":"lazy"},"children":[]},{"type":"text","value":"\n  "}]},{"type":"text","value":"\n    "}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"We will break this interface down into two main components: IndexBar (red rectangle) and Article (green rectangle). We will further break down the IndexBar into IndexSections (blue) and IndexTitles (cyan)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":" I recommend reviewing a brief "},{"type":"element","tagName":"a","properties":{"href":"https://facebook.github.io/react/docs/introducing-jsx.html"},"children":[{"type":"text","value":"introduction to JSX"}]},{"type":"text","value":" before starting your assignment."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h4","properties":{"id":"indexbar"},"children":[{"type":"element","tagName":"a","properties":{"href":"#indexbar","ariaLabel":"indexbar permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"IndexBar"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The first component you should create is the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"IndexBar"}]},{"type":"text","value":". Implement the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"IndexBar"}]},{"type":"text","value":" in the provided file "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"src/components/IndexBar.js"}]},{"type":"text","value":". You should pass two props to the IndexBar component. The first, named "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"collection"}]},{"type":"text","value":", should be a reference to the data collection, and the second, named "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"select"}]},{"type":"text","value":", should be a callback to be called when a title is selected. Make sure to use these names (and any others specified in the assignment) to facilitate automated testing."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Internally, you will have two sub-components, though you do not necessarily need to make them actual sub-components. The sections list (the individual letters across the top) should be implemented as an unordered list ("},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"<ul>"}]},{"type":"text","value":"). Wrap this in a "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"<div>"}]},{"type":"text","value":" with the id \"section-list\". The styling is designed to turn your list into the horizontal form seen in the pictures."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"You should add an "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"onClick"}]},{"type":"text","value":" callback to each "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"<li>"}]},{"type":"text","value":" in the list which sets the current section as state for the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"IndexBar"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The second sub-component should be the list of titles found within the current section. This should also be implemented as an unordered list. You should sort the titles like shown in the screenshot (\"unordered\" just means that the list isn't displayed as a numbered list). For these "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"<li>"}]},{"type":"text","value":", make sure to invoke the callback that was passed down with the props when the user clicks on a title. Your code should invoke "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"select()"}]},{"type":"text","value":" with the article associated with the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"<li>"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Finally, when the user clicks a new section, you should invoke the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"select"}]},{"type":"text","value":" callback with a missing (thus "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"undefined"}]},{"type":"text","value":") argument to indicate that the current article should be \"cleared\", i.e. not show."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"When you are done, the HTML must look like:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<div>\n  <div id=\"section-list\">\n    <ul>\n      <li>A</li>\n      <li>B</li>\n    </ul>\n  </div>\n  <div>\n    <ul>\n      <li>Apple</li>\n      <li>Anteater</li>\n      <li>Auton</li>\n    </ul>\n  </div>\n</div>"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Here is one way to transform an array into an HTML list:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"const list = ['daleks', 'cybermen', 'ice warriors', 'autons'];\nconst races = list.map(race => (<li key={race}>{race}</li>));\n\nreturn (<ul>{races}</ul>);"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"which would produce this HTML:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<ul>\n  <li>daleks</li>\n  <li>cybermen</li>\n  <li>ice warriors<?li>\n  <li>autons</li>\n</ul>"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h4","properties":{"id":"article"},"children":[{"type":"element","tagName":"a","properties":{"href":"#article","ariaLabel":"article permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Article"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The next component you should implement is "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Article"}]},{"type":"text","value":" (in the provided file "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"src/components/Article.js"}]},{"type":"text","value":"). The "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Article"}]},{"type":"text","value":" component should take one prop named "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"article"}]},{"type":"text","value":" that is an article record Object. Our articles have three fields: \"title\", \"extract\" (the contents), and \"edited\" (the time the article was last edited)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In your "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Article"}]},{"type":"text","value":" component display the title, text, and date. The entire article should be contained in a "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"<div>"}]},{"type":"text","value":" with the id \"article\". The title should have the id \"article-title\", the text should have the id \"article-text\", and the date should have the id \"article-timestamp\" (there are styles for some of these). To ensure consistent date formatting, render the date in a locale-relevant format with "},{"type":"element","tagName":"a","properties":{"href":"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString"},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Date.toLocaleString"}]}]},{"type":"text","value":". Note that this will not necessarily match the picture -- it will render the date as appropriate for your computer/browser/environment."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h4","properties":{"id":"putting-the-components-together"},"children":[{"type":"element","tagName":"a","properties":{"href":"#putting-the-components-together","ariaLabel":"putting the components together permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Putting the components together"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"src/App.js"}]},{"type":"text","value":" integrate your newly created components. You should add the title (Simplepedia) as a "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"<h1>"}]},{"type":"text","value":" header with the id \"title\" and your two components to the page. You need to make sure that you pass the appropriate callbacks as props so that clicking on a section opens the title list, and clicking on a title opens the related article for viewing. If there is no article to show at the current moment, best practice is to not render the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Article"}]},{"type":"text","value":" component (via "},{"type":"element","tagName":"a","properties":{"href":"https://reactjs.org/docs/conditional-rendering.html"},"children":[{"type":"text","value":"conditional rendering"}]},{"type":"text","value":") as opposed to rendering "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Article"}]},{"type":"text","value":" but having it somehow manage an undefined "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"article"}]},{"type":"text","value":" prop. The latter forces additional complexity into the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Article"}]},{"type":"text","value":" component and in the case of more complex components can trigger unnecessary computation. "}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"finishing-up"},"children":[{"type":"element","tagName":"a","properties":{"href":"#finishing-up","ariaLabel":"finishing up permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Finishing up"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"To earn full points for code organization and style your submission should not have ESLint warnings or errors when run with "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"npm run lint"}]},{"type":"text","value":" (or "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"npx eslint ."}]},{"type":"text","value":"). Remember than you can fix many errors automatically with "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"npm run lint -- --fix"}]},{"type":"text","value":" (although since ESLint can sometimes introduce errors during this process, we suggest committing your code before running \"fix\" so you can rollback any changes). As described in the README, the assignment skeleton includes the Prettier package and associated hooks to automatically reformat your code to a consistent standard when you commit. Thus do not be surprised if your code looks slightly different after a commit."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Submit your assignment by pushing your changes to the GitHub classroom via "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"git push --all origin"}]},{"type":"text","value":" and then submitting your repository to Gradescope as described "},{"type":"element","tagName":"a","properties":{"href":"../../resources/gradescope.html"},"children":[{"type":"text","value":"here"}]},{"type":"text","value":". You can submit (push to GitHub and submit to Gradescope) multiple times. The last submission before the deadline will be the one graded. Portions of your assignment will undergo automated grading. Make sure to follow the specifications exactly, otherwise the tests will fail (even if your code generally works as intended). Use the provided test suite (run with "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"npm test"}]},{"type":"text","value":") to get immediate feedback on whether your code follows the specification (remember that the provided tests are not exhaustive, and an application that passes all of these tests is not guaranteed to be correct). Because of the increased complexity of a React application, Gradescope can take minutes to run all of the tests. Thus you will be more efficient testing locally and only submitting to Gradescope when you are confident your application meets the specification."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"grading"},"children":[{"type":"element","tagName":"a","properties":{"href":"#grading","ariaLabel":"grading permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Grading"}]},{"type":"text","value":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"},{"type":"element","tagName":"table","properties":{},"children":[{"type":"element","tagName":"thead","properties":{},"children":[{"type":"element","tagName":"tr","properties":{},"children":[{"type":"element","tagName":"th","properties":{},"children":[{"type":"text","value":"Points"}]},{"type":"element","tagName":"th","properties":{},"children":[{"type":"text","value":"Criteria"}]}]}]},{"type":"element","tagName":"tbody","properties":{},"children":[{"type":"element","tagName":"tr","properties":{},"children":[{"type":"element","tagName":"td","properties":{},"children":[{"type":"text","value":"5"}]},{"type":"element","tagName":"td","properties":{},"children":[{"type":"text","value":"Code organization, comments, and style"}]}]},{"type":"element","tagName":"tr","properties":{},"children":[{"type":"element","tagName":"td","properties":{},"children":[{"type":"text","value":"5"}]},{"type":"element","tagName":"td","properties":{},"children":[{"type":"text","value":"IndexBar section list display"}]}]},{"type":"element","tagName":"tr","properties":{},"children":[{"type":"element","tagName":"td","properties":{},"children":[{"type":"text","value":"5"}]},{"type":"element","tagName":"td","properties":{},"children":[{"type":"text","value":"IndexBar section list functionality"}]}]},{"type":"element","tagName":"tr","properties":{},"children":[{"type":"element","tagName":"td","properties":{},"children":[{"type":"text","value":"5"}]},{"type":"element","tagName":"td","properties":{},"children":[{"type":"text","value":"IndexBar title list display"}]}]},{"type":"element","tagName":"tr","properties":{},"children":[{"type":"element","tagName":"td","properties":{},"children":[{"type":"text","value":"5"}]},{"type":"element","tagName":"td","properties":{},"children":[{"type":"text","value":"IndexBar title list functionality"}]}]},{"type":"element","tagName":"tr","properties":{},"children":[{"type":"element","tagName":"td","properties":{},"children":[{"type":"text","value":"5"}]},{"type":"element","tagName":"td","properties":{},"children":[{"type":"text","value":"Article display"}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"faq"},"children":[{"type":"element","tagName":"a","properties":{"href":"#faq","ariaLabel":"faq permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"FAQ"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h5","properties":{"id":"do-i-need-to-implement-unit-testing"},"children":[{"type":"element","tagName":"a","properties":{"href":"#do-i-need-to-implement-unit-testing","ariaLabel":"do i need to implement unit testing permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Do I need to implement unit testing?"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"We will learn later in the semester how to unit test React components. For this assignment you are not expected to implement any of your own unit tests. The skeleton includes some unit tests to assist you in your development and to ensure that the grading scripts can automatically test your submission."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h5","properties":{"id":"what-if-the-tests-and-assignment-specification-appear-to-be-in-conflict"},"children":[{"type":"element","tagName":"a","properties":{"href":"#what-if-the-tests-and-assignment-specification-appear-to-be-in-conflict","ariaLabel":"what if the tests and assignment specification appear to be in conflict permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"What if the tests and assignment specification appear to be in conflict?"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Please post to Piazza so that we can resolve any conflict or confusion ASAP."}]}],"data":{"quirksMode":false}},"frontmatter":{"dueDate":"2019-09-30 5p","path":"/assignments/assignment02","title":"CS 312 - Assignment Two","name":"Assignment 2"},"parent":{"__typename":"File","id":"2d485dfd-3885-57d2-95d8-e1e042a75ab7","name":"assignment02","modifiedTime":"Oct 8 2019 13:48"}}},"pageContext":{"isCreatedByStatefulCreatePages":false}}}