Here's the situation:
Dashboardly hired a senior full-stack developer to build their grand-parents dashboard application. The dude started building the API, database and front-end in parallel, but got hit by a bus midway through. You are his succession. You have been tasked with completing the missing code to create the MVP for the app, then implementing one by one a set of features to make the app better.
To help you complete your work successfully, Dashboardly has done three things for you:
- Provided a set of mockups of what the application should look like.
- Written document describing all the missing code to make the MVP work, as well as an explanation of each feature they want to build (attached)
- Hired three experienced consultants (mentors) who are really good at giving hints, but cannot type due to having lost their hands in a crocodile fight
Your task is to bring the project forward as much as possible for Friday, which was announced as the official launch date for Dashboardly a year ago.
Apart from this time constraint, your other constraint is money. These consultants are 💰uper expensive, and you are only allowed 15 credits per team. Each credit gives you a 15-minute slot with a mentor and you cannot take more than one slot per hour. A credit is all or nothing: if you use mentor time for only three minutes, you have consumed a credit.
This document outlines what is currently missing to make the MVP 100% functional.
The table structure that supports the MVP is 100% created and available in the API repository.
There is an ExpressJS API for Dashboardly. It is not 100% in compliance with the API contract. More is explained below.
There is a web app for Dashboardly. It is not 100% complete nor in line with the mockups. More is explained below.
Have a look at the queries being made on the database and verify if any indexes still need to be added to make some queries faster.
First, you should read all the existing code and understand what it's doing. You should also execute the code in your development environment and make sure it is working.
Then, you need to implement the following:
-
You need to fill in the code for the
controllers/bookmarks.jsmodule. You can take advantage of the already completed code incontrollers/boards.jsto get a hint on how to do it. You'll also have to implement some accompanying methods in theDashboardlyDataLoadermodule. Make sure to validate the user before modifying/deleting bookmarks!! -
You'll also need to fill in the code for the
POST /boards/:id/bookmarkshandler incontrollers/boards.jsin a similar way. This may also require adding methods inDashboardlyDataLoader. -
Fill in the code for the
GET /boards/:id/bookmarkshandler incontrollers/boards.js. -
Fill in the code for the
GET /auth/mehandler incontrollers/auth.js. -
The API contract says that user objects should have an
avatarUrlfield, but as you can see that field is not part of theuserstable in the database. That's OK. The database and REST representations don't have to match at 100%, and resources don't even have to be tied to any storage. In this case though, theavatarUrlcan be generated from theemailfield using the Gravatar service. To do this you'll need to generate anmd5hash of the email (read the docs!). The best place to make this addition would be in your data loader: before sending out a user object, add anavatarUrlproperty using the Gravatar instructions to generate it.NOTE: Even though this logic could be implemented on the client, we choose to implement it at the level of the API. This way we can change our
avatarUrllogic only once, and all client applications will see the change. -
Add CORS support! Since your client web app will be hosted on a separate subdomain, you'll need CORS. The
express-corsmiddleware can take care of that for you. For now, you can use it without any config, meaning it will allow all domains. This will need to be changed before deploying.
When you are done, make sure to test your API thoroughly using Postman. You should test the following:
- List all boards
- List a single board
- List all the links for a single board
- Signup, as well as receiving proper errors where appropriate
- Login and get a token, as well as receiving proper errors where appropriate, then try it with
/auth/me - Logout, and checking that your previous token was indeed removed from the system
- Using a valid token, create/modify/delete a new board
- Try creating a board without a token and make sure it fails
- Using a valid token, create/modify/delete a new bookmark under a board you own
- Using a valid token, create a new bookmark under a board you don't own and make sure it fails
- Try creating/modifying/deleting a bookmark without a token and make sure it fails
Once all these elements are working through Postman, the next step will be to test how well they integrate with the client application. Since the app was built using the Apiary mock server, there should be a 100% match. One thing you may have to do is add CORS to your API.
First, you should read all the existing code and understand what it's doing. You should also execute the code in your development environment and make sure it is working.
Then, you need to implement the following:
- Styling: try to get as close as possible to the mockups, without using any CSS framework. You may use the grid system that you built in week 4.
- Implement the signup component. You can look at the login component for some inspiration, even though it's not 100% the same.
- Create the signup form in
src/components/pages/SignUp.js - Make an API call to the "Create new user (signup)" endpoint
- On success, use React Router's
browserHistoryto redirect the user to/login - On error, display the errors in the form
- Create the signup form in
- For logged in users, make sure the menu displays their avatar URL from the API. To do this you'll have to call the
/auth/meendpoint and retrieve theavatarUrlof the logged in user. - For logged in users on the home page, make the
+button work. It should open a modal prompting the user to create a new board like in the mockups. On submit, make the appropriate API call. Once the board is created, redirect the user to that board's page with React Router'sbrowserHistory. - Fix
src/components/pages/Board.jsto add a+button if the logged in user owns the current board. Then, implement that+to let the logged in user add a bookmark on their board. It should open a modal like in the mockup, then make the appropriate API call to create the bookmark. On success, you should refresh the list of bookmarks from the server, making sure to keep the component DRY. - Fix the logout functionality in
src/components/modals/Menu.js: instead of being a<Link>to/logout, this should simply be a clickable element that fires the appropriate API call to delete the session, then removes the session token from local storage. - On the home page listing all boards, add an
Editbutton to the boards that are owned by the logged in user. ClickingEditwill open a modal letting the user modify the board's title and description. Submitting should call the appropriatePATCHendpoint on the API, then reload the list of boards. - On a board page that is owned by the logged in user, add an
Editbutton to all the bookmarks. Clicking onEditwill open a modal just like the one for creating a bookmark, letting the user change the url and title of the bookmark. Submitting should call the appropriatePATCHendpoint of the API, then reload the list of links. - In a similar way to (7) and (8), also provide
Deletebuttons to allow the user to delete their own boards as well as bookmarks individually.
You will have to test all this UI by connecting it to the real API you are building rather than the mock data from Apiary. To do this, simply modify the API_URL config in src/config.js and test away.
Allow users to search boards on the homepage by keyword. This could be as simple as doing a LIKE "%keyword%" (slowwwwww) query to your MySQL database, or learning about Elasticsearch and using it thru a SaaS provider. Expose this functionality through your API using the GET /boards endpoint, and accepting a keyword query string parameter.
Allow the creator of a board to mark it as "Unlisted" (both when creating and modifying a board). This means it will not show in search results nor on the home page with all boards, but anyone with the link can visit it.









