Try   HackMD

⬅️ Return to course website

Assignment 1: Nodes

Released: September 13th, 2023

Due: September 27th, 2023 at 11:59 PM ET

Introduction

Having collected all the necessary ingredients by completing the setup assignment, and all the donut know-how in the lab, you are finally ready to make the dough—the most important step of all!

In this assignment, you will be building upon your Lab 1 code to create a complete node file system—a standard way of managing and navigating between hypertext nodes. At the end, you will have built a full-stack application that will allow users to create, read, update, delete, and move hypertext nodes via the frontend. You will be graded on the functionality of your frontend via manual review and your backend via an automatic test suite.

You will make the node file system using the full-stack technologies that you installed in Assignment 0: MongoDB, Express.js, React.js, and Node.js.

This programming assignment contains three parts: the database, the backend, and the frontend. We will start with an overview of the assignment specifications and the general design features of the file system you are creating. Then, we will delve into how to work with each part of the MERN stack to get the whole file system working.

Keep in mind the 30-minute rule: if you can’t get something that appears straightforward to work in 30 minutes, it may not be your problem. Don’t be afraid to send a message in Slack or go to TA hours if something unexpected comes up.

Lab 1 is an important precursor to this assignment!

This assignment builds directly on the work in Lab 1. It's crucial that you go through Lab 1 in its entirety before starting Assignment 1!

Note: Assignment 1 uses the same codebase as Lab 1

Checklist

Database:

  • Create Mongo database

Backend (BackendNodeGateway):

  • createNode [Implemented in Lab 1]
  • getNodeById
  • deleteAll
  • deleteNode
  • moveNode
  • addChild
  • removeChild

Frontend (NodeView):

  • createNode [Implemented in Lab 1]
  • content [Implemented in Lab 1]
  • title
  • breadcrumb [What is a breadcrumb?]
  • delete
  • move

Deployment:

  • Deploy the backend to Render
  • Deploy the frontend to Vercel

Demo

Note: The demo may take up to 30 seconds to load due to the free backend we used for hosting. Additionally, you might notice some strange behavior if there are multiple students interacting with the demo at the same time.

You can find a demo of the MyHypermedia application here.

Syntax Guides

You'll be working with several languages and libraries in this assignment. Here are some syntax guides to serve as a reference:

Database

In the first lab, we provided you with a URI for a database that the TAs had made for the class to share. But now that you are working on you own hypertext system, it's time to create your own database!

Step 1: Creating a MongoDB account

Create/log into your MongoDB account here.

Step 2: Creating a free shared cluster

Create a new organization and project if necessary, then proceed to create a new database deployment.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Select the M0 free shared option.

Step 3: Configuring a new cluster

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Ensure that the following options are selected:

  1. Cloud Provider & Region: AWS, N. Virginia (us-east-1)
  2. Cluster Name: cs1951v (technically, this field can be named whatever you want)

Click Create.

Step 4: Creating a database user and configuring access

After clicking Create, you should see a page like this:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

For the section: How would you like to authenticate your connection?:

  1. Select Username and Password.
  2. Create a Database User: create a username and password that you will remember. This username and password is what will be used in your MongoDB URI to connect to this new cluster.
  3. Click Create User.

Scroll down to the next section which should look like this:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

For the section: Where would you like to connect from?

  1. Add a connection IP address: select My Local Environment and enter in 0.0.0.0 IP address as your whitelist.
  2. Click Add Entry.

Now Click Finish and Close.

Step 5: Getting the connection string

You should now be redirected to the overview page of your new database deployment!

  1. Click the Connect button beside the cluster name.
  2. Under Connect to your application choose the Drivers option.
  3. copy the connection string (you can ignore all other steps on this page).

Step 6: Adding the URI to your .env file

Navigate to the .env file you made in Lab 1: cd server/.env. Update the URI with the new URI we just copied from Step 5.

Remember to:

  1. replace <password> in the URI with the password you created in Step 4.
  2. in between the last slash and the question mark, add the name of your database: cs1951v-database.
  3. add quotation marks "" around your new URI

This is an example of what the line should look like in your .env:

DB_URI="mongodb+srv://username:password@cs1951v.39y6kas.mongodb.net/cs1951v-database?retryWrites=true&w=majority"

Great! You successfully connected your backend to your own MongoDB cluster!

Step 7: Testing your database connection

TODO:

  1. Start your server using cd server and npm install (or npm i) and npm run dev
  2. Start your React service using cd client and npm install (or npm i) and npm run dev
  3. Go to http://localhost:3000/ and create a node.
  4. Check your cs1951v-database dashboard (nodes collection) - you should see a new entry. If you don't see any new entries in your nodes collection, please reach out to the TAs via Slack or in Hours!

Note: We could send a POST request at /node/create via Postman to simulate our frontend actions here.

Awesome! Now that we have verified that our database is properly connected, let's move onto the backend portion of this assignment.

Backend

BackendNodeGateway.ts:

In this assignment you will be tasked with writing methods in BackendNodeGateway.ts to reach full functionality of our node file system.

You will need to implement the following methods:

createNode (already implemented in lab) - One of the core functionalities that we are expecting you to have is the ability to create nodes. This method should create a node in the database.

getNodeById - We want to retrieve nodes from the database. The findNodeById function allows users to retrieve a node given the ID.

getNodesById - We want to retrieve all nodes from the database that have an ID that is in the input list of ID's.

deleteAll - This method should delete all documents in the MongoDB nodes collection. This method won't be needed much for production use but rather use for testing.

deleteNode - Now that we can create and retrieve nodes, we want to allow users to delete nodes. This method should allow users to delete a node and its children from the database given a particular nodeId.

moveNode - In order to have a fully functioning file system, we must be able to move nodes around. You need to implement a function which takes in two nodeIds, nodeToMove's nodeId and newParent's nodeId. The function should then verify if the move is valid and move the node in a way such that nodeToMove becomes a child of newParent.

addChild - This method takes in a childId and parentId and update's a parent's filePath.children array with a new child nodeId. This is mainly used as a helper method for other functions.

removeChild - This method takes in a childId and parentId and remove's childId from the parent's filePath.children array. This is mainly used as a helper method for other functions.

Helper Methods:

NodeCollectionConnection.ts & BackendNodeGateway.ts

The methods in NodeCollectionConnection.ts and BackendNodeGateway.ts that we have already implemented for you should help you implement the methods above. For more practice with MongoDB queries, you can also use Mongo playground.

server/src/types

We also recommend looking at server/src/types as this folder includes important information on how we have set up the schema of INode, IServiceResponse, etc. These files also include type-checking functions such as isINode() which will be very helpful for error-checking in this assignment.

Custom helper methods:

Of course, you can write as many of your own helper functions and are not required to use the ones we provide. As long as you pass our tests, we have a pretty liberal stance on what you can and cannot do!

Note: Because next assignment's stencil code will use the same server/src/types defined in Assignment 1, it would be wise to NOT add custom code to server/src/types just yet.

Testing

To test that your backend functions work as intended, you can run the test suite by running npm test (or npm run test) from the server folder.

Frontend

For the frontend portion of this assignment, you will be building a React component (NodeView.tsx) that renders a node's data in a user-friendly UI. We will start with just image and text nodes, and will add more types of nodes as the course progresses.

Your create node modal functionality should be working from the lab. One thing to note is that when creating an image node, the "Choose file" browse option will not work until after you deploy your site (Imgur doesn't work on localhost). Once you deploy, Imgur uploading should work automatically. In the meantime, you should paste an image url into the textbox.

This a chance to exercise your design skills and creativity: your NodeView can look however you want it to! However, there are some functional requirements that your NodeView must fulfill.

Use Cmd + Shift + F and search for "TODO" to find all the places you need to edit code! Or, use the "Todo Tree" extension's panel in VSCode to see a tree view of all the TODOs.

Requirements for your NodeView:

  • It should clearly display the title of the node

  • It should clearly display the content of the node

    • i.e. the image for an image node, and the text for a text node
  • It should include a "breadcrumb"

    • A breadcrumb is a UI element that shows the user where they currently are in a hierarchical structure, like a website or file system
    • For instance:
      • Coursework > Fall 2021 > CS1951v > Assignment 1
    • See NodeBreadcrumb.tsx to see which data you will have access to as props

    Note: Clicking on a part of the breadcrumb does NOT need to take the user to that node like in the demo.

  • It should include a delete button that deletes the node when clicked

    • We have provided a stub for onDeleteButtonClick in MainView.tsx, which we call an event handler since it handles the user clicking on the delete button
    • You will then want to pass this event handler to the onClick field of a <button /> (We provide a simple <Button /> React component that you should feel free to edit)
    • Here's an example of this pattern:
      ​​​​​​​​/** 
      ​​​​​​​​ * This React component renders a button that logs "Hello,  world!"
      ​​​​​​​​ * to the console when clicked
      ​​​​​​​​ */
      ​​​​​​​​function HelloWorldButton() {
      ​​​​​​​​    const handleClick = () => {
      ​​​​​​​​        console.log('Hello, world!');
      ​​​​​​​​    }
      
      ​​​​​​​​    return (
      ​​​​​​​​        <button onClick={handleClick}>
      ​​​​​​​​            Click me to log Hello, world!
      ​​​​​​​​        </button>
      ​​​​​​​​    )
      ​​​​​​​​}
      
  • It should include a move button that opens the MoveNodeModal when clicked, allowing a user to move a node to a different parent node.

    • Use the onMoveButtonClick prop that is passed in to open the moveNodeModal!

The specification on this document is very broad! The TODOs in the code provide more detail. In general, when implementing a React component, think about how you can go from the input (props) to the output (what you want to render).

Design

In addition the functionality of your NodeView, it is important that it is well-designed. This will be true for the rest of the assignments in this course, and any software you build after the course concludes.

What does "well-designed" mean? In short, a potential user should feel that the interface is intuitive, clear, and enjoyable to use. For instance, buttons should do what they seem like they do, and important information should be presented prominently.

Essentially, we want to see that you have given significant thought to the usability and styling of your UI. Feel free to check out The Basic Principles of User Interface Design or other online resources, or ping in the #assignments channel if you have questions!

Check out the globalCssVariables.scss file, where you can change some of the global colors that are used throughout the system. Feel free to change this as much as you would like to!

Debugging

We highly recommend having your webpage running in your browser as you're working on the frontend, and incrementally checking that each feature you add appears and works as intended. Below we have some debugging options you may consider using.

Print Statements

console.log('Insert message') is a Javascript function that prints a message to the web console. To open the web console, double click/right click on the webpage, click "Inspect Element", and go to the console tab.

VSCode Debugger (Frontend)

You can debug with breakpoints directly in VSCode!

Debuggers for Chrome and Edge are built in, and you can find an extension in the store for Firefox.

Select the Run and Debug tab on the left side of the editor. The first time you setup debugging for your repository, you will need to create a launch.json file. On the dropdown list that opens, select Web App (Chrome) or whichever other browser you prefer to debug with.

To start debugging, go to the "Run and Debug" sidebar (Shortcut: Ctrl + Shift + D) and click the play button beside Launch chrome against localhost.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

This will open localhost:3000 in Chrome, where you have access to all of the Chrome debugging tools as well.

Now, the useful part of using the VSCode debugger, adding breakpoints to your code! Let us say that we are in ImageContent.tsx and we are having issues accessing the anchors that we should render on our node. We want to know what startAnchor is and what anchor is in the following snippet of code for displayImageAnchors.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Spot the 🔴 next to line 106. What that means is that we have set a breakpoint at that line in our code. You can add new breakpoints by click next to the line number. Now when we run our code in the debugger and go to an image, your web app will freeze at that point.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

You can see that it has frozen at line 108. The menu at the top of the following screenshot (next to the ImageContent.tsx tab) can be used to Continue, Step to next line, Stop, Restart, etc. When we are frozen at a breakpoint we can open the Debug Terminal and get really valuable insights as to what the variables are.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

VSCode Debugger (Backend)

You can also debug backend Node.js applications in VSCode. To do this, you will create a "JavaScript Debug Terminal", and you will run your backend from this debug terminal instead of your traditional terminal.

There are two methods for launching a JavaScript Debug Terminal:

  • On the terminal bar at the bottom of the editor, click the arrow beside the + icon to add a new terminal. In the dropdown, select "JavaScript Debug Terminal".
  • Press Control + Shfit + P (or Command + Shift + P) to open the command palette, and select "Debug: JavaScript Debug Terminal".

Then you can run npm run dev from this debug terminal, and you will be able to add breakpoints to your backend code in the same way as shown above.

Deployment

Once you have finished implementing all the steps of this assignment, follow the instructions linked here to deploy your project!

Conceptual Questions

These questions are required for students taking the course as graduate-level or capstone. For non-capstone 1000-level students, you can complete these questions for a maximum of 15 extra credit points (5 per question).

These questions are supposed to help you make good design decisions and get you to consider how we will be expanding this assignment to build a hypertext application over the course of the semester.

Answer these questions in the repositories README.md file

  1. Suppose that in addition to storing nodes in a file system you want to store nodes on an unbounded 2D-canvas (similar to what you’ve seen in Dash demos during class). Explain how this feature would be implemented across each component of the MERN stack. Specifically:
    a. Write a MongoDB database schema that could support this. Justify your design.
    b. Identify at least one potential npm React library that you could use to avoid building the entire 2D canvas UI component from scratch.

  2. Imagine you want to implement an authentication and authorization workflow to protect access to certain nodes. Specifically each node should specify access level for every user and group, with access levels being: read, write, annotate, and admin. Assume for each user session that you have secure access to an accurate user-identifier and an array of group-identifiers that that user belongs to. Explain in 3-5 sentences how you would add support to the BackendNodeGateway so that it returns the node only if the current user has proper access to the requested node.

  3. Finally, imagine you want to persist user trails. Specifically, you want to track the path that a user takes through the hypertext corpus. In this case, since each node has a unique url, each path can be represented as an array (of linked list) of urls. Explain in 3-5 sentences how you might add support for storing and then effectively accessing old trails. In your response, you may choose to focus on the frontend (around how you would make trails into a compelling user experience) or on the backend (around how you would make this data persistent as well as how you would query it).

Handin

Please ensure that all the sections in the README.md are filled out.

You'll be submitting all your assignments for CSCI1951V through Gradescope, and you'll receive all your grades and feedback through Gradescope too. Once you have successfully created a Gradescope account using your Brown email address you can enroll in our Gradescope course by clicking the "Gradescope" tab on Canvas. You should submit your project to the Assignment 1: Nodes assignment in Gradescope by linking your GitHub repository as follows:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Grading

For students taking this course as a capstone or graduate level course, the assignment is out of 125 points. For students not taking this course as a capstone or graduate level course, the assignment is out of 110 points.

Linting - 5 Pts (autograded)

Task Grade
No ESLint or Prettier warnings 5 Pts

Run npm run lint on the server/ and client/ directories to run the linter locally and fix any issues before you submit!

Backend - 45 Pts (autograded)

Task Grade
Implement src/nodes/BackendNodeGateway.ts 45 Pts

Run npm test on the server/ directroy to run the test suite locally and fix any issues before you submit!

Frontend - 50 Pts (TA will grade)

Task Grade
Clearly display the title and content of the node 10 Pts
Includes a breadcrumb 10 Pts
Includes a delete button that deletes the node 10 Pts
Includes a move button that opens the moveNodeModal 10 Pts
Design: usability and style 10 Pts

Deployment - 10 Pts (TA will grade)

Task Grade
Backend deployed successfully 5 Pts
Frontend deployed successfully 5 Pts

Conceptual Questions - 15 Pts (TA will grade)

Task Grade
Question 1 5 Pts
Question 2 5 Pts
Question 3 5 Pts