Giter Club home page Giter Club logo

full-circle's Introduction

NO LONGER USED: replaced with Airtable form.

See https://turing.edu/financing/diversity-scholarship-application


Build Status Code Climate security

Full Circle: Turing's Diversity Scholarship Application

This application assists in streamlining and automating the application process for Turing's Diversity Scholarship Program.

Dependencies

  • Ruby 2.4.1
  • Rails 5.1.3
  • React 2.2.1

Setup

If you don't have ruby 2.4.1 or greater first install this using your Ruby version manager of choice (we use rbenv at Turing)

Now: git clone https://github.com/turingschool/full-circle.git

Run bundle install.

Create OAuth App in Census (https://login-staging.turing.edu) Redirect url http://localhost:3000/auth/census/callback

Install figaro: $ bundle exec figaro install and then add to the created application.yml file your Census OAuth credentials:

CENSUS_CLIENT_ID:
CENSUS_CLIENT_SECRET:

You should also set your role in Census to full-circle-admin

Create and migrate the DB

  • rake db:create db:migrate

Optional seed the db

  • rake db:seed

Finally, run the test suite: $ rspec

To install client side dependencies:

  • yarn

Finally, to run the application locally:

  • rails s

Deployment

Full Circle is hosted on Heroku. Green builds of the master branch will deploy to staging automatically via CircleCI. Migrations are run as part of the Heroku release process. Migrations on Heroku should not need to be run manually (rake db:migrate) except in emergencies or extreme circumstances.

Production deploys are done by approving the workflow in the Circle UI. Manual git push's to Heroku should not happen except in extreme circumstances.

How the App Works

This section describes how the app works and it's structure. Here is where you can find what code does what and where to find it.

Basic Structure

Full Circle is really 3 single page apps in one. Each user has their own dashboard: Student, Reviewer, and Admin. When a user first logs in via the homepage portal they will be redirected to the dashboard that corresponds to their role (found in controller/concerns/authorize.rb).

Roles are determined by the user's role within Census. Admin full-circle-admin Reviewer full-circle-reviewer

  • A student will be rerouted to student/dashboard, and will not be able to visit the reviewer or admin dashboard.
  • A reviewer will be rerouted to reviewer/dashboard and will not be able to visit the admin dashboard, but can visit the student dashboard.
  • An admin will be rerouted to admin/dashboard, and can navigate to all other dashboards.

Once a user has entered a dashboard we are no longer in Rails but in React. All React components will be found in the app/assets/javascript/components folder. Each dashboard lives in their corresponding folder with shared components living in the shared folder.

User Authentication

See user testing for additional Spec information on Auth/Auth.

Files that include OAuth flow:

  • config/initializers/omniauth.rb
  • app/models/concerns/oauth_user.rb
  • app/controllers/concerns/authorize.rb
  • app/controllers/session_controller.rb

OAuth happens right now via the omniauth gem with the Census provider (found in the omniauth.rb config file).

When a user clicks on the login button on the homepage this initiates the Census callback loop. When a user is Authorized they are rerouted through the session_controller. When a session is created a user is then rerouted based on their role (found in authorize.rb)

A user in the Full Circle database will maintain state with the OAuth provider. If they change their name on Github, it will also change in Full Circle. When a user logs in, all information is updated in this way from the provider. This information can be found in oauth_params in oauth_user.rb. When a change is needed for the User model's attributes, these can be updated here and should not effect anything else.

User Authorization

Files that include Authorization

  • controller/concerns/authorize.rb
  • app/controllers/api_controller.rb
  • app/controllers/application_controller.rb
  • app/models/jw_token.rb

Because this is a Rails-React app user Authorization happens in two places in two ways:

  1. When a user logs in via the homepage and a new session is created the user is authorized before rerouting to the correct dashboard. All users are defaulted to a student. Rerouting and user checks can be found in authorize.rb.

  2. Prior to a user entering a dashboard the user_id is converted to a JWT token (found in application_controller.rb) and stored in the client as 'user_id'. This is then used for all calls to the API side of the app. The user token is sent in a header as Authorization: Bearer <token>. On the api side this comes in as request.env['HTTP_AUTHORIZATION'] (found in api_controller.rb). Once the token is decoded and parsed the user is then pulled from the database and scoping of the role can be achieved by calling user.?.

React Components

This section covers React Components, their organization, shared use, and architecture.

All React Components are found in the app/assets/javascript/components

React is integrated with rails using the Rails-React gem. This gem deals with React by pulling it into the asset-pipeline. This means that you don't ever need to import React into files, export components out of files, or care very much about folder structure at all. Make a React Component and it will be automatically available anywhere. This has draw-backs. Mainly that incorporating webpack based packages are pain and I've avoided using them. This means that I've been forces to only use packages that are asset-pipeline friendly and can be loaded via a gam.

Organization

All components can be found in app/assets/javascript/components. This file is loaded via component.js in app/assets/javascript, which is subsequently loaded via application.js.

You might have noticed the 'ping' folder which includes ping.js.jsx holding some generic methods for making API requests. You can include any file in the javascrips folder and application.js will load it allowing you access to those methods on a global scope. By adding the jsx we can seamlessly use these methods in our React components.

Components are organized into five main sub folders, Homepage, Admin, Reviewer, Student, and shared. Sections of each page are then put into subfolders in an attempt to makes their use more obvious. Hopefully that's true.

To make sure components never collide with one another all student components are started with Student, admin components Admin, and reviewer components Reviewer. This gets a little verbose, but helps to scope components.

handleAction Pattern

One of the tricky aspects of React is dealing with state changes among deeply nested components. For larger applications Redux can be used, but since this application isn't that big an alternative has been created instead.

Most "base" components of the page has one very simple method called 'handleAction'. This function takes an object that contains a key/value structure to match that of React's setState().

This makes changing state relatively painless. Assuming that you'll be handling all state changes from this base Component, you can handle any state change with it by sending it up the component chain and calling it at any point.

To use it you must send the method the key/value you want to change the state of, which requires a little bind weirdness. When you do finally call it will look like this: this.props.handleAction.bind(this, {key: value}). On action this call the handleAction method and initiate a state change.

handleChange Pattern

Changing state based on Javascrip's event needs to be handles a little differently than just making key: value since we also need access to the event itself.

Typically this is used when you want to capture a change in a text field, or the event.target.value.

To do this you'll need to rely on React's onClick prop, and then understand, again, the weirdness of bind.

React's onClick is much like Javascrip's thing.on('click', function()). The callback function is what you make onClick equal to. To make a universal onChange function you'll need to build the key: value pair by sending the key and then just using the event in the function.

handleChange(key, event) {
  this.setState( {[key]: event.target.value} )
}

To call the function: onClick={this.props.handleChange.bind(this, 'key')}. You don't need to send the event since onChange automatically sends that at the end of the params sent to the receiving function. This is captured as event in the handleChange function.

Shared components

Components that can be used anywhere are stored in the Shared folder. Most of these rely on the "handleAction" pattern.

Name: ClickBtn
Description: Creates a clickable button that will execute a function.
Props:

  • onClick: (Function) What will be executed on button click.
  • Text: (String) Text that will be displayed in button body.
  • readOnly: (String) Classnames. 'true' class will hide button.
  • disabled: (Boolean) Defaults to false. true will disable the button as clickable.

Name: LinkBtn
Description: Creates a clickable button that will reroute to a link.
Props:

  • Url: (String) Full Url of redirect on button Click.
  • Text: (String) Text that will be displayed in button body.
  • readOnly: (Boolean) Defaults to false. True will disable button.

Name: StaticTextField
Description: Creates a formatted static text row.
Props:

  • label: (String) Row label.
  • text: (String) Text of row.
  • width: (String) Width of row. Must include %, px, vw, etc.. ('100%')

Name: SelectableTextField
Description: Creates a formatted text selectable row.
Props:

  • texts: (Array) The texts that will be displayed in the row. Must be held in an array, even if just one text.
  • width: (String) Width of row. Must include %, px, vw, etc.. ('100%')
  • returnKey: (String) The key that will match a state change.
  • returnValue: (String, Array, Object) The thing that will be replaced in the state change.
  • handleAction: (Function) The function that will executed when row is selected.

Name: DropDownMenu
Description: Creates a drop down menu from a list of objects.
Props:

  • list: (Array) All of the objects that will be selectable from the drop down menu.
  • header: (Object) The initial object that will be displayed in the header of the drop down menu.
  • label: (String) The attribute of the object that will be displayed in the drop down rows.
  • handleAction: (Function) The function that will handle the selection of a row. When a row is selected the drop down menu will build an object { item: selectedObject } that can be used to change state.

Stylesheets

Everything is scss and Flexbox is the main layout tool used. Flexbox everywhere!

Because I hate Bootstrap, I rolled all my own Stylesheets. Sorry if this kills you a little.

Stylesheets are organized in folders and should be more or less easy to locate. For the most part styles in each folder should make sense why they are there. Other times it won't make sense. At the very least, fussy searching for a style class should be easy and the class should not be much of a mystery.

Shared React Components have their own Mixin, found in the stylesheets/components folder. When you add a shared Component in React you will also need to @include the corresponding style in it's parent.

I tried to make each .scss file as small as possible. I have also repeated styles when they could have been shared in a single file. This is mostly to reduce the chance of breaking styles elsewhere. When you change a style you should have a pretty good idea of what it's actually going to change, and not change for that matter.

Because scss allows us to nest classes I have "scoped" each page to keep things from messing with other things. All admin classes are wrapped in .admin, reviewer in .reviewer, and student in .student. Seems a little redundant, but it makes you stress less about adding and changing styles.

Testing

This section covers some of what is in the testing suite that may not be obvious. Testing React in a Rails environment isn't awesome and requires a few extra hurdles to jump through.

The testing environment uses RSpec and Capybara with Poltergeist to handle Phantomjs. It's slow, but easy to write and easy to test and does not require any additional setup on your end.

As of now Phantomjs does not support Javascript ES6. This means that unless you want to go down some very dark roads testing React Components is not possible. When support of ES6 is supported, Feature testing should be really easy and integrate very nicely with Capybara.

All testing configs for middle-wear will be found in rails_helper.rb. This includes Shoulda-Matchers, Capybara/Poltergeist, and Omniauth

Unit testing covers most Ruby written code, and is fairly straight forward. Feature testing covers some higher level functionality on the user's end.

User authentication and authorization

features/homepage/user_can_log_in_spec.rb

Omniauth mocks a user's credentials and fakes a callback authentication with a provider. What Omniauth returns is found in the rails_helper.rb under Omniauth.config. If a different provider is used you may need to update these to match what the provider actually returns.

full-circle's People

Contributors

mraaronolsen avatar victoriavasys avatar kat3kasper avatar dependabot[bot] avatar srt32 avatar dependabot-support avatar tannerwelsh avatar dependabot-preview[bot] avatar christielynam avatar

Stargazers

 avatar

Watchers

Jeff Casimir avatar Steve Kinney avatar James Cloos avatar Will Mitchell avatar Cory Westerfield avatar Alex Robinson avatar Andrew Carmer avatar  avatar Taylor Moore avatar Mike Limberg avatar Robbie avatar Pamela Lovett avatar Leta Keane avatar  avatar

full-circle's Issues

Guidelines Component

Fix "Got It" button (overlaps border when accessed via the "Read Guidelines" button)

When a student logs in ->

  • Full circle will talk to enroll to confirm enrolled status.
  • If they are not eligible they will see the message ‘Sorry you are not eligible’
  • If they are eligible they are redirected to ‘/student/application’

Augment login page

Add a welcome message "Turing School of Software & Design Diversity​ ​Scholarship​ Application Site"

Subtext: "Please login to complete your application process"

Add a GitHub logo to the login button

Admin clicks on any application

  • They will be shown the essay and all total scores for that application.
  • Each criteria will be averaged across all reviews.
  • A list of each review with criteria scores will be shown to the side.
  • Admins will have access to Name and Email of student.
  • An admin can not edit any scores submitted by a reviewer.

If the application period is ->

  • closed ‘/student/application’ will show a message that applications are not being accepted.
  • open ‘/student/application’ will be shows the application form.

When a reviewer clicks on an open cohort ->

  • They will be shown a list of all submitted applications for that cohort.
  • Each application in the list will have three states, ‘unreviewed’, ‘reviewing’, and ‘reviewed’
  • ‘Unreviewed applications will be highlighted in grey as not started.
  • ‘Reviewing’ applications will be highlighted in red as incompleted.
  • ‘Reviewed’ applications will be highlighted in green as completed.

Allow admin to be reviewers?

They see different pages...
But admin should be able to assign selves to cohort? Would mean on the reviewers page in admin, both admin & reviewers appear

Admin clicks on ‘New Cohort’ ->

  • They will be shown a form allowing them to create an ‘Open Application Window’.
  • An ‘Open Application Window’ will have a start date and an end date.
  • An ‘Open Application Window’ will have a cohort number.

Admin views a Closed cohort application

  • Will be rendered in black.
  • When an admin views a closed cohort they will be able to see which applications were awarded scholarships.
  • There will be no additional actions available to the admin in closed cohorts except viewing application questions, scores, and student information.

Admin adds a new cohort

• "Add Cohort" should be a button on the dashboard
• Clicking on it should show component similar to "Edit Cohort" 2nd column
• Title
• Start Date
• End Date
• Open Date
• Close Date
• Notify Date

Update time zone

At 5p 12-17-17, the site said "Turing is no longer accepting scholarship applications"

Admin views an Open cohort

  • Cohort will be rendered in green.
  • When an admin views an open cohort they will see a status bar.
  • The status bar will show the application window with start date and end date.
  • Status bar will show how many applications have been awarded.
  • Status bar will show how many completed reviews have been done.

Admin clicks on any cohort

  • All applications will have two states, ‘not awarded’ and ‘awarded’.
  • Awarded applications will be rendered in green.
  • Not Awarded applications will be rendered in black.
  • Applications will be ranked by total score.
  • Each application will have an avg score.

Essay "Page"

Add description "words left" after number
Reformat questions
Essay submitted the first time I saved (but now seems fine) (because applications in draft-state display like finished applications)
Submission is allowed multiple times

Student Application Epic

  • Applications will have two states, ‘draft’ and ‘submitted’.
    When a student clicks ‘Save’ the application will be saved to the database as ‘draft’
  • When there are unsaved changes the ‘Save’ button will be green, and a message at the top of the application will say ‘unsaved changes’
  • When there are no unsaved changes the ‘Save’ button will be unclickable and grayed out.
  • If a student tries to leave the application with unsaved changes they will be prompted to save before leaving the site. Otherwise they can cancel the action and will return to the unsaved application form.
  • When a student clicks ‘Submit’ but has not completed the application they will be shown a message of what needs to be completed and those areas that need to be completed will be highlighted in red.
  • When a student clicks ‘Submit’ and the application is complete they will first be shown a preview of the application and prompted to ‘Submit’ again.

The Admin Dashboard Epic

  • The admin dashboard will show a list of 'Application Cohorts'
  • Closed cohorts are rendered black
  • The open cohort is rendered in green
  • Button to Create New 'Application Cohort'
  • Header with Name, Logged in As Admin
  • An empty box where applications will appear for a cohort
  • An empty box where cohort information will appear

Reviewer Application Epic

  • All applications will default to ‘unreviewed’.
  • When a reviewer scores a criteria it will automatically save.
  • When a reviewer scores at least one criteria the application will change state to ‘reviewing’.
  • When a reviewer clicks ‘Done’ the application will change state to ‘reviewed’.
  • When a reviewer has reviewed all applications they can click submit.
  • When a reviewer submits reviews those scores will be visible to an admin.
  • Once a reviewer submits their reviews they will not be able to change any scores.

Application Reviewer

  • A cohort will have many Reviewers through Application Reviewers.
  • Each Application Reviewer will have two statuses: 'unfinalized', 'finalized'
  • A reviewer will need to click finalize to change the status.
  • Once a status has been changes the admin dashboard will show the additional reviews for that cohort.

When a student tries to submit...

... but has not saved they will be prompted to first save the application.

  • If a user tries to submit when the application is empty they will see an error telling them so.

Open Cohort Epic

  • Cohorts will have two state statuses
  • ‘Closed’, ‘Open’
  • ‘Unfinalized’, ‘Finalized’
  • After a cohort has closed but has not been finalized by an Admin it will be ‘Unfinalized’ and rendered red.
  • When an admin visits an ‘Unconfirmed’ cohort a message will appear telling the admin that action is needed and a ‘Finalize’ button will appear.
  • When an admin clicks on ‘Finalize’
  • Emails will be sent ->
  • Email to send message to applicant: “Hey, congrats, you’ve been accepted. Look for an email from RightSignature”
  • Email to send message to applicant: ‘Hey, sorry, you have not been chosen.’
  • Email to send to admin: “Action item for accepted applicant”.

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.