GithubHelp home page GithubHelp logo

jc4883 / symposia Goto Github PK

View Code? Open in Web Editor NEW
1.0 2.0 0.0 18.8 MB

A single page web application inspired by Basecamp, featuring todo lists and file storage

Home Page: https://symposia.herokuapp.com/

Ruby 21.01% JavaScript 50.14% CSS 24.31% HTML 3.87% CoffeeScript 0.66%

symposia's Introduction

README

Symposia is a clone of Basecamp, a product managment tool. Symposia does two things: organizes the user's todo's into todo lists, and stores files for viewing and downloading.

Visit the live site here.

Technologies

Symposia uses Ruby on Rails, PostgreSQL, and AWS on the backend, React and Redux on the frontend. Ruby on Rails proved to be the appropriate technology for this project--Ruby on Rails was originally developed by Basecamp for their internal use. In particular, Rail's associations well complemented JBuilder to send to the frontend the necessary data, allowing the user to have a productive time on Symposia.

Features

File Upload

A user is able to save a local file to AWS by choosing a local file and adding a description to it using a form. Here's what it looks like:

In the backend, the formData API was used to encapsulate user data, primarily reading an input of type="file" when the user chooses an image inside of a form. Upon form submission, the following function is called:

  handleSubmit(e) {
    e.preventDefault();
    this.handleCancel();
    let formData = new FormData();
    formData.append('photo_upload[title]', this.state.title);
    formData.append('photo_upload[description]', this.state.description);
    formData.append('photo_upload[project_id]', this.props.projectId);
    
    if (this.state.photoFile) {
      formData.append('photo_upload[photo]', this.state.photoFile);
    }
    this.props.createPhotoUpload(this.props.projectId, formData).then(this.props.parentRender);
  }

Here, the local state of the component is updated to the values given by the user. Then, we append the data to the formData using the keys specified in our Rails model. This way, the appropriate controller in the backend is able to access the data through its params, then correctly save a new upload entry to PostgreSQL. If successful, we return information about what we have saved, including the upload's url extracted using url_for() and an association(!). The upload can be can be viewed if it is an image by placing the photoUrl as the src in an img tag.

One more thing to note about this code snippet: in the handleSubmit() function, at the point that we append this.state.photoFile, the file will already have been uploaded to AWS using readAsDataURL in the FileReader API.

Upon uploading, the user can view the file's show page, where she can download or delete the file from the cloud. This is what it looks like:

One technical achievement was efficiently accessing the title of the upload's project, which is displayed on the top of the upload show page. Through rails, only one trip to the database was required to retrieve both the project's title and the uploaded file information.

In the controller, it is done as follows:

  def show
    @photo_upload = PhotoUpload.find(params[:id])
    if @photo_upload.photo.image?
      @is_image = true
    else
      @is_image = false
    end
    render "api/photo_uploads/show"
  end

Then in jbuilder, we can access the file's project:

  json.set! :project_title, @photo_upload.project.title
  json.set! :uploads do
    json.set! @photo_upload.id do
      json.extract! @photo_upload, :id, :title, :description, :project_id, :created_at
      if @delete != true
        json.photoUrl url_for(@photo_upload.photo)
        json.railsBlobUrl rails_blob_url(@photo_upload.photo, disposition: "attachment")
        json.is_image @is_image
      end
    end
  end

We access the title of the file's project and the file's active storage blob using rails associations in the same request cycle. Therefore, there is no need to retrieve the project information with another ajax request.

Todos

Symposia also allows users to create todo lists, add todos, and view each individual list and todo. Here is what the todo list index page looks like:

In the frontend, one interesting challenge occurred with the todo lists' redux reducer. For context, the todo list slice of state contains an array of only todo id's. On the other hand, the todo slice of state contains the actual information about the todos. This design choice was to ensure that the state contained as little nesting as possible. Here is a code snippet of how I implemented this structure in the todo lists' reducer:

  const todoListsReducer = (state = {}, action) => {
    Object.freeze(state);
    switch (action.type) {
      case RECEIVE_TODO:
        let newState3 = Object.assign({}, state);
        newState3[action.todo.todo_list_id].todos.push({id: action.todo.id})
        return newState3;
      case RECEIVE_TODO_LIST:
        return Object.assign({}, state, {[Object.keys(action.todoList.todoList)[0]]: Object.values(action.todoList.todoList)[0]});
      ...
      default:
        return state;
    }
  }

I allowed the reducer to update both the array of todo id's in the todolists' state and the actual todos in their own state. This is why the todo list reducer catches the RECEIVE_TODO action type case in addition to its own action.type in the code snippet above.

In Conclusion

Thanks for coming! I hope you had fun poking around the code and checking out the live version. I certainly had a blast building it.

To see more of my projects, checkout my portfolio, and make sure to look around my Github as well.

Finally, go to my LinkedIn to learn more about me.

symposia's People

Contributors

jc4883 avatar

Stargazers

Alfred Allegretti avatar

Watchers

James Cloos avatar  avatar

symposia's Issues

Design Docs Review #1

Hey Peter, great start on your design docs, here are my notes so far:

MVP LIST
Auth:

  • Specify which features a user can/can’t use when logged out.

Project Home View:

  • What is included in “see project’s activity?”
  • What is included in “project-specific features”
  • What are the global features?

Schedule:

  • Exporting to google calendars may be a bit optimistic, do some research and see how viable this may be.

SCHEMA
Users:

  • Basecamp uses the user’s real name in a few places, so make sure to include fname and lname in the users table

Projects:

  • Projects definitely need name and description columns. Consider what other columns may be necessary as well. Spend some time on basecamp and see what pieces of data are tied just to a project (as opposed to a to-do or message board)

Tool Bar:

  • Does this need to be it’s own table? Or could it just be stored as a set of boolean columns on the project table?

To-do Lists:

  • To-do lists need name and description columns
  • Each to-do list is going to have a number of to-dos, so you’ll probably want a “todos” table in addition to your “todo_lists” table

Project Home View:

  • You probably don’t need a table for this, all of the information can be stored in the project table itself.

Message Board:

  • Each project only has one message board, so you probably don’t need a message board table. Instead, you’ll need a “message_board_messages” table, with each message storing a project_id

  • Flesh out the following tables with the same logic (which columns are necessary to encapsulate the functionality of that resource).

SAMPLE STATE

  • Make sure to add a session slice of state and a ui slice of state (consider what might need to be under ui. Loading? Will you be using modals? etc).
  • Flesh out the sample state with all the data added after making the above changes to your schema.

Design Docs Review #2

Here are my notes on your backend and frontend routes:

BACKEND ROUTES

  • Flesh out all of your routes with their intended purpose (“POST /api/users - sign up a user”). This will serve as a reminder as you reach your later features.
  • Do all of your routes need to include a :user_id? Think about which ones need a specific user_id and which ones will be fine using the current_user id which is already accessible on the backend.

Projects:

  • Include patch and delete routes for your projects.

FRONTEND ROUTES

  • Fix your formatting here so it’s easier to distinguish between routes and and components. Put components in backticks (`) and make sure all Components are fully in SnakeCase.
  • Spend sometime on Basecamp and flesh out your components with the necessary subcomponents. For example, your schedule should have a Calendar component and a CreateEventForm component. Your ProjectShow should include a ProjectActivity subcomponent. Try to be as detailed and complete as possible as this will be your roadmap when building out your frontend.

Auth MVP review

Awesome work on auth so far, here are my notes:

Splash:

  • Change all references to Basecamp in the text to Symposia

Auth:

  • Your demo login requires two clicks to work. Not 100% sure why this is but may be a need to preventDefault on the submit of the form it’s in. Alternatively, you don’t really need the button to be in a form, it can just be a free-floating button with an onClick which dispatches the demoLogin thunk action.
  • Your splash page should be an AuthRoute meaning that if I’m already logged in I should be sent directly to /projects upon refreshing the root.
  • Clear your error when switching forms (they currently persist if I switch from the signup to the login and vice versa)
  • Your password errors (for login) should appear above the inputs in a yellow box. Check out real basecamp for reference.
  • On your signup form, set your inputs with a flag of required.

Logged in:

  • Create the navBar component and have the logout button in a dropdown (styling this is considered part of Auth).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.