olinlibrary / futureboard

A digital signage platform for sharing video and other media, supplemented by information about events happening on campus
https://futureboard.olin.build
3 stars 0 forks source link

FUTUREboard

Build Status

FUTUREboard is a digital signage platform for sharing of media – including images, GIFs, and videos — supplemented by information about events happening on campus.

Table of Contents

Status

To Do

Top Priorities

And MORE!

Possible Extensions

Make Your Own

Setup

To install your own version of FUTUREboard: fork this repo, clone it so you have local access, enter the directory (cd FORWARDboard) and then run npm install, which will automatically install the npm modules listed in package.json. This project was deployed with Heroku using a Mongo database hosted by mLab. Our app is set to access the external services using keys stored as environment variables. You'll need to run the following code with each variable replaced with your real key.

export MONGODB_URI="<Get this from mLab instance>";

Optionally set the ADMIN_PASSWORD to something. If you do not set it, then there will be no auth on the admin page.

By default, the app uses the staging instance of ABE. In the future, this will only be accessible with authentication, or from within the Olin LAN. To use a local ABE instance:

  1. Follow the instructions here to run the local ABE server.
  2. Set the ABE_API_URI environment variable to http://localhost:3000.

Once you've set these environment variables, you should be able to run the app locally by executing npm start from the root of the repo directory. (This runs node server.js, as specified in package.json). This will serve the app at http://localhost:8080.

NOTE: You'll need to add these as environment variables to your Heroku instance as well. Depending on your setup, you may want to have a separate database for local vs. production, but for just getting the app running it's not a crime to use the same.

Setting up AWS: We use AWS S3 to store media, and have AWS Lambda functions to resize images and transcode video.

We used aws-lambda-ffmpeg and aws-lambda-image for resizing the media. Install aws-lambda-ffmpeg first, because its installer fails if you try to use existing buckets. You can also install it with temporary buckets and then change the settings in the aws console. Create two buckets, an 'upload' bucket and a 'media' bucket. Users will upload to the 'upload' bucket, triggering a lambda function to process the file and save it to your 'media' bucket. Currently, images are prepended with 'img-' and video is with 'vid-' to differentiate lambda triggers. Create AWS keys for your app and set the following environment variables:

export ACCESS_KEY_ID=your access_key_id
export SECRET_ACCESS_KEY=your secret_access_key

Finally set up the 'media' bucket to publish to an SNS topic on ObjectCreate, and create an HTTPS subscription to url/aws/MediaStatusSNS. You will have to confirm this once you spin up the heroku instance.

Now that you've got these variables set, you need to get the Heroku toolbelt set up. Once logged in through the command line interface, run heroku git:remote -a <YOUR PROJECT NAME>. Now when you've committed changes to Github, you can push to Heroku by running git push heroku master. If everything was done correctly, your app should deploy and you can access it at <YOUR PROJECT NAME>.herokuapp.com.

Development

A tricky part about working with external services on your local server is that you need a publicly accessible URL for them to send packets to, so you need to have some form of staging server or tunneling software like Ngrok (tutorial for using Ngrok with Twilio, it's pretty quick to get started!). The latter is recommended as it makes development more natural (test changes without new deployment) but is less permanent than a staging server managed by Heroku. A combination is ideal but extra work, that's all up to you!

As far as database administration, a pro of using mLab is having an interface for sifting through db records and doing general management rather than through the command line. Currently our app has a db admin interface so this functionality is less necessary.

Database

It is very likely that your local server will be running with a local MongoDB.

To export the online mLab database: navigate to /scripts; then run the bash script importDB.sh with three input arguments listed below.

# To Run:
# sh importDB.sh <db_username> <db_password> <local_db_name>

# Export remote database for local import.
# Get username and password from Heroku mLab instance - environment variables in settings.
mongodump -h ds113063.mlab.com:13063 -d heroku_w45g6cd6 -u $1 -p $2 -o mLabDump;
# You can find your db_password in :
# heroku > settings > Reveal Config Vars -> MONGODB_URI -> Edit
   -> COPY and PASTE the string between ':' and '@'

# Replace database with files exported from remote using `exportRemote.sh`
mongorestore --drop -d $3 mLabDump/heroku_w45g6cd6;

Contributing

To contribute, fork this repo and clone it to your local development environment. When making edits, make sure to base off of the dev branch by first running git checkout dev and ensuring that it's up to date with this repo git pull upstream dev. Once you're up to date, create a new branch off dev with git checkout -b <branch_name> and make any edits you'd like to make.

Run npm run lint to verify your code formatting.

Once you've made the changes you'd like to make, ensure that they are committed to your new branch before switching back to dev to make sure it's fully up to date (another git checkout dev and git pull upstream dev). Once this is done, switch back to your branch (git checkout <branch_name>) and rebase onto dev with git rebase -i dev. This will ensure that any changes that have been made to dev are accounted for in your branch, thus avoiding any merge conflicts when we try to pull those changes into the main repo. To learn more about rebasing, look here. If you've pushed your branch up to your version of the repo before rebasing, you will need to force push your rebased changes to your branch to ensure that the correct history is included for merging.

After all of that, go ahead and open a new pull request onto the upstream version of dev! This pull request should have a title describing the changes at a very high level and a description that gets into more details. These details should include what changes have been made and why. Then request that a contributor on the main repo review your code. Once suggestions have been made, make necessary edits and confirm once again that everything looks good. If yes, your reviewer can go ahead and merge it in!

Operating

First start the mongodb server: sudo service mongod start or mongod. (To restart, sudo service mongod restart.)

Set environment variables for AWS:

export ACCESS_KEY_ID=
export SECRET_ACCESS_KEY=

Once you've set up your own version of the app, run npm start to get it running.

Directory Structure

#f03c15 Backend #c5f015 Frontend #1589F0 Assets #5d646b Deprecated

API

~Strikethrough~ indicates unimplemented functionality.

Note: Flagged bobs are never returned, except on /bobs/flagged.

/api/

HTTP Method Action
GET retrieve this documentation

/api/bobs

HTTP Method Action
GET retrieve a list of all bobs
POST create a new bob object

/api/bobs/active

HTTP Method Action
GET retrieve a list of active bobs (The definition of active is still extremely fluid)

/api/bobs/[bobId]

HTTP Method Action
GET retrieve bob object with id bobId
PUT update the bob object
DELETE delete the bob object (Requires auth)

/api/bobs/[bobId]/votes

HTTP Method Action
GET retrieve number of votes bob with bobId has
POST add one up-vote to the bob

/api/bobs/[bobId]/flags

HTTP Method Action
GET retrieve flag value of bob
POST flag a bob

/api/flavors

HTTP Method Action
GET retrieve all flavors
~POST~ create a new flavor object

/api/flavors/[flavorID : flavorName]

HTTP Method Action
GET retrieve a flavor object by name or id
~PUT~ update the flavor object

/api/tags

HTTP Method Action
GET retrieve all tags
~POST~ create a new tag

/api/tags/[tagID]

HTTP Method Action
GET retrieve a tag by name or id
~PUT~ update the tag

Socket.io

Socket Name Input Method
'add_element' bob object Create a new bob
'update_element' bob object Update the bob with the same bob id
'upvote' { id: bobid, votes: num_votes } Set bob with id bobid to num_votes
'delete' bob id remove bob immediately

Notes on AWS

We tried using AWS to handle media storage and transcoding, but in the future I would warn against this. We had set up two buckets - an upload bucket and a media bucket. Lambda functions were supposed to resize and transcode images and video into the media bucket, and then move the original files into a 'original/' folder in the media bucket. AWS is a big challenge, and we could not demo with this functionality because we ran into an error when adding triggers to the video transcoding lambda. Right now we use the source media on FUTUREboard, which does not work well on mobile and low power computers (like rasp pi). Google cloud allows transparent image resizing with url parameters (docs). Alternatively, you can spin up a worker service on heroku to do all image and video resizing.

Credits

This project is a product of Software of Summer 2017! Thank you to Jeff and Oliver for ongoing mentorship and to the fellow students for feedback and support. Also a big thanks to the participants of the first ever Library Potluck who interacted with the board and gave feedback.

License

This project is licensed under the MIT License, a "short and simple permissive license with conditions only requiring preservation of copyright and license notices."