MIT 6.170 final project
JavaScript CSS HTML
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
bin
client
data
docs
server
test
.editorconfig
.gitignore
Procfile
README.md
gulpfile.js
package.json

README.md

Notably

6.170 final project

Created by Vahid Fazel-Rezai, Alexander Luh, Akshay Ravikumar, Kimberli Zhong

URL: notably.xyz

Table of Contents

Features

Notably is a collaborative note-taking app for MIT students!

You can:

  • Search for a class
  • Create sessions for a class (e.g. for a lecture)
  • Take notes with peers in your class

After some discussion, we decided to remove two features listed in our design document: viewing other users' feeds and hiding feeds when users haven't submitted enough snippets. Both these features were what we considered "reach" features, so removing them does not affect the application's main functionality.

Viewing other users' stashes is a privacy concern, and we don't want students to arbitrarily see what snippets other users have saved. Additionally, it adds additional complexity when the user's stash you're viewing changes state (e.g. upon adding, saving, or flagging a snippet). Hiding feeds when users haven't submitted enough snippets would also require slight modifications in the model, but we ultimately deemed it unnecessary in the spirit of openness.

Instructions

All commands should be run in the root folder.

  • To run server: node bin/www
  • To run everything (dev mode): npm run dev (or gulp)
  • To populate database: npm run setup
  • To update packages: npm run update
  • To test: npm test
  • To run mongo shell: mongo notably then e.g. db.courses.find()
  • To run Heroku shell: heroku run bash
  • To enable Imgur posting: get an API key at api.imgur.com and export IMGUR_API_KEY='API KEY'
  • To test API routes: use Postman

API

Snippet

The snippet object looks like this:

{
  "author": (string - username),
  "text": (string - snippet text),
  "timestamp": (string - timestamp),
  "saveCount": (number - number of saves),
  "flagCount": (number - number of flags),
  "savedBy": [(string - usernames)],
  "flaggedBy": [(string - usernames)],
  "sessionId": (string - session id it belongs to)
}

/api/user - GET

  • Get a user's profile information
  • Must be authenticated

params

{
  "username": (string)
}

content

{
  "username": (string),
  "name": (string),
  "stats": {
      "numSubmitted": (int - number of snippets submitted),
      "numSaved": (int - number of snippets saved),
      "numSubscribed": (int - number of courses subscribed to)
  },
  "courses": [{
      "number": (string - course number),
      "name": (string - course name)
  }],
  "recentSessions": [{
    "_id": (string - session id),
    "createdAt": (string - creation timestamp)
    "index": (number - position of session in recentSessions array; 0 is most recent),
    "meta": {
        "title": (string - session title),
        "number": (string - course number),
    }
  }]
}

/api/user/auth - GET

  • Check whether a user is authenticated; checks request's session username and verifies that it's valid

params

{}

content

{
  "username": (string - username)
}

/api/user/create - POST

  • Creates a user

params

{
  "username": (string),
  "password": (string),
  "email": (string),
  "name": (string)
}

content

{
  "username": (string - username of user just created)
}

/api/user/login - POST

  • Authenticates a user

params

{
  "username": (string),
  "password": (string)
}

content

{
  "username": (string - username of user just logged in)
}

/api/user/logout - POST

  • Logs out a user

params

{}

content

{
  "username": (string - username of user just logged in)
}

/api/user/courses - GET

  • Gets all of logged in user's courses
  • Must be authenticated

params

{ }

content

{
  "courses": [{
      "number": (string - course number),
      "name": (string - course name)
  }]
}

/api/user/subscribe - POST

  • Subscribes a user to a course
  • Must be authenticated
  • Returns all of user's courses

params

{
  "course": (string - course number)
}

content

{
  "courses": [{
      "number": (string - course number),
      "name": (string - course name)
  }]
}

/api/user/unsubscribe - POST

  • Unsubscribes a user from a course
  • Must be authenticated
  • Returns all of user's courses

params

{
  "course": (string - course number)
}

content

{
  "courses": [{
      "number": (string - course number),
      "name": (string - course name)
  }]
}

/api/course/all - GET

  • Returns all course numbers and names
  • Must be authenticated

params

{ }

content

{
  "courses": [{
      "number": (string - course number),
      "name": (string - course name)
  }]
}

/api/course - GET

  • Get course info and sessions
  • Must be authenticated

params

{
  "number": (string - course number)
}

content

{
  "_id": (string),
  "meta": {
    "number": (string - course number),
    "name": (string - course name),
    "description": (string - course description),
    "lectureTime": (string - lecture time),
    "location": (string - lecture location)
  },
  "sessions": [{
    "_id": (string - session id),
    "title": (string - session title),
    "createdAt": (string - timestamp)
  }]
}

/api/session - GET

  • Get session info and snippets
  • Must be authenticated

params

{
    "sessionId": (string - session id)
}

content

{
  "_id": (string - session id),
  "createdAt": (string - creation timestamp),
  "meta": {
    "number": (string - course number),
    "title": (string - session title)
  },
  "feed": [(Snippet)],
  "stash": [(Snippet)]
}

/api/session/create - POST

  • Add new session to a course
  • Must be authenticated

params

{
  "number": (string - course number),
  "title": (string - session title)
}

content

{
  "_id": (string - session id),
  "number": (string - course number),
  "title": (string - session title),
  "createdAt": (string - timestamp of creation time)
}

/api/session/image - POST

  • Uploads an image to Imgur and returns the link
  • Must be authenticated

params

{
  "imageData": (string - base64 image data),
}

content

{
  "link": (string - Imgur link to the uploaded image),
}

/api/session/visit - POST

  • Register current user's visit to session
  • Must be authenticated

params

{ }

content

{
  "recentSessions": [{
    "_id": (string - session id),
    "createdAt": (string - creation timestamp)
    "index": (number - position of session in recentSessions array; 0 is most recent),
    "meta": {
        "title": (string - session title),
        "number": (string - course number),
    }
  }]
}

/api/stash - GET

  • Get stash info
  • Must be authenticated

params

{
  "stashId": (string - stash id),
}

content

{
  "_id": (string - session id),
  "createdAt": (string - timestamp),
  "creator": (string - username),
  "sessionTitle": (string - title session stash belongs to),
  "courseNumber": (string - course number associated with stash),
  "session": (string - id of associated session),
  "snippets": [(Snippet)]
}

/api/stash/save - POST

  • Save a snippet to a stash
  • Snippet and stash should have same session ID and should be valid
  • Must be authenticated

params

{
  "snippetId": (string - snippet id),
  "stashId": (string - stash id)
}

content

{
  "_id": (string - session id),
  "createdAt": (string - timestamp),
  "creator": (string - username),
  "sessionTitle": (string - title session stash belongs to),
  "courseNumber": (string - course number associated with stash),
  "session": (string - id of associated session),
  "snippets": [(Snippet)]
}

/api/stash/remove - POST

  • Get snippet info
  • Will send error if snippet not in stash
  • Must be authenticated

params

{
  "snippetId": (string - snippet id),
  "stashId": (string - stash id)
}

content

{
  "_id": (string - session id),
  "createdAt": (string - timestamp),
  "creator": (string - username),
  "sessionTitle": (string - title session stash belongs to),
  "courseNumber": (string - course number associated with stash),
  "session": (string - id of associated session),
  "snippets": [(Snippet)]
}

/api/snippet - GET

  • Get snippet info
  • Must be authenticated

params

{
  "snippetId": (string - snippet id)
}

content

(Snippet)

/api/snippet - POST

  • Add a new user's stash; will return error if user already has a stash
  • Must be authenticated

params

{
  "sessionId": (string - session id),
  "text": (string - snippet text)
}

content

(Snippet)

/api/snippet/flag - POST

  • Flag a snippet
  • Will send error if user tries to flag own snippet or if snippet is already flagged
  • Must be authenticated

params

{
  "snippetId": (string - snippet id)
}

content

(Snippet)

Socket.io Events

"joined session"

  • Fired when a user joins a session
  • Joins a room based on that session Id and username

params

{
"sessionId" : (string - sessionId),
"courseNumber" : (string - course number)
}
  • Response: "session data loaded" event emitted to the course page corresponding to the session
  • Sends an occupancy Object showing the number of active sockets in each session

content

{
"occupancy" : {(string - sessionId) : (integer - occupancy)}
}

"left session"

  • Fired when a user leaves a session
  • Leaves the corresponding session room

params

{
"sessionId" : (string - sessionId),
"courseNumber" : (string - course number)
}

"joined course page"

  • Fired when a user joins a course's home page
  • Joins a room based on the course name and username

params

{
"courseNumber" : (string - course number)
}
  • Response: "session data loaded" event emitted to the course room

params

{
"occupancy" : {(string - sessionId) : (integer - occupancy)}
}

"left course page"

  • Fired when a user leaves a course's home page
  • Leaves the corresponding course room

params

{
"courseNumber" : (string - course number)
}

"new session"

  • Fired when a user creates a new session
  • Creates the session and adds it to the corresponding course

params

{
"session" : (Session),
"courseNumber" : (string - course number)
}
  • Response: "new session" event emitted to the course room

content

{
"session" : (Session)
}

"joined home page"

  • Fired when a user joins a home page
  • Joins a room based on the username

params

{
"username" : (string - username)
}
  • Response: "session data loaded" event sent to the corresponding room

content

{
"occupancy" : {(string - sessionId) : (integer - occupancy)}
}

"left home page"

  • Fired when a user leaves the home page
  • Leaves the corresponding room

params

{
"username" : (string - username)
}

"added snippet"

  • Fired when a user adds a snippet
  • Adds the snippet to the corresponding session's feed

params

{
"content" : (string - snippet content),
"sessionId" : (string - sessionId),
"username" :  (string - username)
}
  • Response: "added snippet" event emitted to every user in the session

content

{
"snippet" : (Snippet)
}
  • On Error: error event emitted only to the sender

content

{
"message" : (string - error message)
}

"saved snippet"

  • Fired when a user saves a snippet
  • Increments the save count of the snippet

params

{
"snippetId" : (string - snippetId),
"sessionId" : (string - sessionId),
"stashId" : (string - stashId),
"username" :  (string - username)
}
  • Response: "saved snippet" event emitted to every user in the session

content

{
"snippetId" : (string - snippetId),
"username" : (string - username)
}
  • On Error: error event emitted only to the sender

content

{
"message" : (string - error message)
}

"removed snippet"

  • Fired when a user removes a snippet
  • Decrements the save count of the snippet

params

{
"snippetId" : (string - snippetId),
"sessionId" : (string - sessionId),
"stashId" : (string - stashId),
"username" :  (string - username)
}
  • Response: "removed snippet" emitted to every user in the session

content

{
"snippetId" : (string - snippetId),
"username" : (string - username)
}
  • On Error: error event emitted only to the sender

content

{
"message" : (string - error message)
}

"flagged snippet"

  • Fired when a user flags a snippet
  • Increments the flag count of the snippet

params

{
"snippetId" : (string - snippetId),
"sessionId" : (string - sessionId),
"username" :  (string - username)
}
  • Response: "flagged snippet" emitted to every user in the session

content

{
"snippetId" : (string - snippetId),
"username" : (string - username)
}
  • On Error: error event emitted only to the sender

content

{
"message" : (string - error message)
}

"disconnect"

  • Fired when a user leaves the website (a standard socket.io call)
  • Updates occupancy for all course and home pages
  • Response: "session data loaded" emitted to the course page corresponding to the session

content

{
"occupancy" : {(string - sessionId) : (integer - occupancy)}
}