From 0563710efd219cf7295db59687efa50e68b0f965 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Tue, 27 Sep 2016 21:59:48 -0700
Subject: [PATCH 01/25] Baseline and Wave 1 requirements satisfied
---
.gitignore | 46 ++---
.ruby-version | 2 +-
Gemfile | 47 +++++
Gemfile.lock | 163 ++++++++++++++++++
README.rdoc | 28 +++
Rakefile | 6 +
app/assets/images/.keep | 0
app/assets/javascripts/application.js | 16 ++
app/assets/javascripts/tasks.coffee | 3 +
app/assets/stylesheets/application.css | 15 ++
app/assets/stylesheets/tasks.scss | 3 +
app/controllers/application_controller.rb | 5 +
app/controllers/concerns/.keep | 0
app/controllers/tasks_controller.rb | 37 ++++
app/helpers/application_helper.rb | 2 +
app/helpers/tasks_helper.rb | 2 +
app/mailers/.keep | 0
app/models/.keep | 0
app/models/concerns/.keep | 0
app/views/layouts/application.html.erb | 14 ++
app/views/tasks/index.html.erb | 8 +
app/views/tasks/show.html.erb | 20 +++
bin/bundle | 3 +
bin/rails | 9 +
bin/rake | 9 +
bin/setup | 29 ++++
bin/spring | 15 ++
config.ru | 4 +
config/application.rb | 26 +++
config/boot.rb | 3 +
config/database.yml | 25 +++
config/environment.rb | 5 +
config/environments/development.rb | 41 +++++
config/environments/production.rb | 79 +++++++++
config/environments/test.rb | 42 +++++
config/initializers/assets.rb | 11 ++
config/initializers/backtrace_silencers.rb | 7 +
config/initializers/cookies_serializer.rb | 3 +
.../initializers/filter_parameter_logging.rb | 4 +
config/initializers/inflections.rb | 16 ++
config/initializers/mime_types.rb | 4 +
config/initializers/session_store.rb | 3 +
config/initializers/wrap_parameters.rb | 14 ++
config/locales/en.yml | 23 +++
config/routes.rb | 59 +++++++
config/secrets.yml | 22 +++
db/seeds.rb | 7 +
lib/assets/.keep | 0
lib/tasks/.keep | 0
log/.keep | 0
public/404.html | 67 +++++++
public/422.html | 67 +++++++
public/500.html | 66 +++++++
public/favicon.ico | 0
public/robots.txt | 5 +
test/controllers/.keep | 0
test/controllers/tasks_controller_test.rb | 7 +
test/fixtures/.keep | 0
test/helpers/.keep | 0
test/integration/.keep | 0
test/mailers/.keep | 0
test/models/.keep | 0
test/test_helper.rb | 10 ++
vendor/assets/javascripts/.keep | 0
vendor/assets/stylesheets/.keep | 0
65 files changed, 1069 insertions(+), 33 deletions(-)
create mode 100644 Gemfile
create mode 100644 Gemfile.lock
create mode 100644 README.rdoc
create mode 100644 Rakefile
create mode 100644 app/assets/images/.keep
create mode 100644 app/assets/javascripts/application.js
create mode 100644 app/assets/javascripts/tasks.coffee
create mode 100644 app/assets/stylesheets/application.css
create mode 100644 app/assets/stylesheets/tasks.scss
create mode 100644 app/controllers/application_controller.rb
create mode 100644 app/controllers/concerns/.keep
create mode 100644 app/controllers/tasks_controller.rb
create mode 100644 app/helpers/application_helper.rb
create mode 100644 app/helpers/tasks_helper.rb
create mode 100644 app/mailers/.keep
create mode 100644 app/models/.keep
create mode 100644 app/models/concerns/.keep
create mode 100644 app/views/layouts/application.html.erb
create mode 100644 app/views/tasks/index.html.erb
create mode 100644 app/views/tasks/show.html.erb
create mode 100755 bin/bundle
create mode 100755 bin/rails
create mode 100755 bin/rake
create mode 100755 bin/setup
create mode 100755 bin/spring
create mode 100644 config.ru
create mode 100644 config/application.rb
create mode 100644 config/boot.rb
create mode 100644 config/database.yml
create mode 100644 config/environment.rb
create mode 100644 config/environments/development.rb
create mode 100644 config/environments/production.rb
create mode 100644 config/environments/test.rb
create mode 100644 config/initializers/assets.rb
create mode 100644 config/initializers/backtrace_silencers.rb
create mode 100644 config/initializers/cookies_serializer.rb
create mode 100644 config/initializers/filter_parameter_logging.rb
create mode 100644 config/initializers/inflections.rb
create mode 100644 config/initializers/mime_types.rb
create mode 100644 config/initializers/session_store.rb
create mode 100644 config/initializers/wrap_parameters.rb
create mode 100644 config/locales/en.yml
create mode 100644 config/routes.rb
create mode 100644 config/secrets.yml
create mode 100644 db/seeds.rb
create mode 100644 lib/assets/.keep
create mode 100644 lib/tasks/.keep
create mode 100644 log/.keep
create mode 100644 public/404.html
create mode 100644 public/422.html
create mode 100644 public/500.html
create mode 100644 public/favicon.ico
create mode 100644 public/robots.txt
create mode 100644 test/controllers/.keep
create mode 100644 test/controllers/tasks_controller_test.rb
create mode 100644 test/fixtures/.keep
create mode 100644 test/helpers/.keep
create mode 100644 test/integration/.keep
create mode 100644 test/mailers/.keep
create mode 100644 test/models/.keep
create mode 100644 test/test_helper.rb
create mode 100644 vendor/assets/javascripts/.keep
create mode 100644 vendor/assets/stylesheets/.keep
diff --git a/.gitignore b/.gitignore
index 28f484983..050c9d95c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,35 +1,17 @@
-*.gem
-*.rbc
-/.config
-/coverage/
-/InstalledFiles
-/pkg/
-/spec/reports/
-/test/tmp/
-/test/version_tmp/
-/tmp/
+# See https://help.github.com/articles/ignoring-files for more about ignoring files.
+#
+# If you find yourself ignoring temporary files generated by your text editor
+# or operating system, you probably want to add a global ignore instead:
+# git config --global core.excludesfile '~/.gitignore_global'
-## Specific to RubyMotion:
-.dat*
-.repl_history
-build/
+# Ignore bundler config.
+/.bundle
-## Documentation cache and generated files:
-/.yardoc/
-/_yardoc/
-/doc/
-/rdoc/
+# Ignore the default SQLite database.
+/db/*.sqlite3
+/db/*.sqlite3-journal
-## Environment normalisation:
-/.bundle/
-/vendor/bundle
-/lib/bundler/man/
-
-# for a library or gem, you might want to ignore these files since the code is
-# intended to run in multiple environments; otherwise, check them in:
-# Gemfile.lock
-# .ruby-version
-# .ruby-gemset
-
-# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
-.rvmrc
+# Ignore all logfiles and tempfiles.
+/log/*
+!/log/.keep
+/tmp
diff --git a/.ruby-version b/.ruby-version
index 276cbf9e2..2bf1c1ccf 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.3.0
+2.3.1
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 000000000..e87fad5fc
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,47 @@
+source 'https://rubygems.org'
+
+
+# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
+gem 'rails', '4.2.7'
+# Use sqlite3 as the database for Active Record
+gem 'sqlite3'
+# Use SCSS for stylesheets
+gem 'sass-rails', '~> 5.0'
+# Use Uglifier as compressor for JavaScript assets
+gem 'uglifier', '>= 1.3.0'
+# Use CoffeeScript for .coffee assets and views
+gem 'coffee-rails', '~> 4.1.0'
+# See https://github.com/rails/execjs#readme for more supported runtimes
+# gem 'therubyracer', platforms: :ruby
+
+# Use jquery as the JavaScript library
+gem 'jquery-rails'
+# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
+gem 'turbolinks'
+# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
+gem 'jbuilder', '~> 2.0'
+# bundle exec rake doc:rails generates the API under doc/api.
+gem 'sdoc', '~> 0.4.0', group: :doc
+
+# Use ActiveModel has_secure_password
+# gem 'bcrypt', '~> 3.1.7'
+
+# Use Unicorn as the app server
+# gem 'unicorn'
+
+# Use Capistrano for deployment
+# gem 'capistrano-rails', group: :development
+
+group :development, :test do
+ # Call 'byebug' anywhere in the code to stop execution and get a debugger console
+ gem 'byebug'
+end
+
+group :development do
+ # Access an IRB console on exception pages or by using <%= console %> in views
+ gem 'web-console', '~> 2.0'
+
+ # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
+ gem 'spring'
+end
+
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 000000000..187046034
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,163 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ actionmailer (4.2.7)
+ actionpack (= 4.2.7)
+ actionview (= 4.2.7)
+ activejob (= 4.2.7)
+ mail (~> 2.5, >= 2.5.4)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ actionpack (4.2.7)
+ actionview (= 4.2.7)
+ activesupport (= 4.2.7)
+ rack (~> 1.6)
+ rack-test (~> 0.6.2)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ actionview (4.2.7)
+ activesupport (= 4.2.7)
+ builder (~> 3.1)
+ erubis (~> 2.7.0)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ activejob (4.2.7)
+ activesupport (= 4.2.7)
+ globalid (>= 0.3.0)
+ activemodel (4.2.7)
+ activesupport (= 4.2.7)
+ builder (~> 3.1)
+ activerecord (4.2.7)
+ activemodel (= 4.2.7)
+ activesupport (= 4.2.7)
+ arel (~> 6.0)
+ activesupport (4.2.7)
+ i18n (~> 0.7)
+ json (~> 1.7, >= 1.7.7)
+ minitest (~> 5.1)
+ thread_safe (~> 0.3, >= 0.3.4)
+ tzinfo (~> 1.1)
+ arel (6.0.3)
+ binding_of_caller (0.7.2)
+ debug_inspector (>= 0.0.1)
+ builder (3.2.2)
+ byebug (9.0.5)
+ coffee-rails (4.1.1)
+ coffee-script (>= 2.2.0)
+ railties (>= 4.0.0, < 5.1.x)
+ coffee-script (2.4.1)
+ coffee-script-source
+ execjs
+ coffee-script-source (1.10.0)
+ concurrent-ruby (1.0.2)
+ debug_inspector (0.0.2)
+ erubis (2.7.0)
+ execjs (2.7.0)
+ globalid (0.3.7)
+ activesupport (>= 4.1.0)
+ i18n (0.7.0)
+ jbuilder (2.6.0)
+ activesupport (>= 3.0.0, < 5.1)
+ multi_json (~> 1.2)
+ jquery-rails (4.2.1)
+ rails-dom-testing (>= 1, < 3)
+ railties (>= 4.2.0)
+ thor (>= 0.14, < 2.0)
+ json (1.8.3)
+ loofah (2.0.3)
+ nokogiri (>= 1.5.9)
+ mail (2.6.4)
+ mime-types (>= 1.16, < 4)
+ mime-types (3.1)
+ mime-types-data (~> 3.2015)
+ mime-types-data (3.2016.0521)
+ mini_portile2 (2.1.0)
+ minitest (5.9.1)
+ multi_json (1.12.1)
+ nokogiri (1.6.8)
+ mini_portile2 (~> 2.1.0)
+ pkg-config (~> 1.1.7)
+ pkg-config (1.1.7)
+ rack (1.6.4)
+ rack-test (0.6.3)
+ rack (>= 1.0)
+ rails (4.2.7)
+ actionmailer (= 4.2.7)
+ actionpack (= 4.2.7)
+ actionview (= 4.2.7)
+ activejob (= 4.2.7)
+ activemodel (= 4.2.7)
+ activerecord (= 4.2.7)
+ activesupport (= 4.2.7)
+ bundler (>= 1.3.0, < 2.0)
+ railties (= 4.2.7)
+ sprockets-rails
+ rails-deprecated_sanitizer (1.0.3)
+ activesupport (>= 4.2.0.alpha)
+ rails-dom-testing (1.0.7)
+ activesupport (>= 4.2.0.beta, < 5.0)
+ nokogiri (~> 1.6.0)
+ rails-deprecated_sanitizer (>= 1.0.1)
+ rails-html-sanitizer (1.0.3)
+ loofah (~> 2.0)
+ railties (4.2.7)
+ actionpack (= 4.2.7)
+ activesupport (= 4.2.7)
+ rake (>= 0.8.7)
+ thor (>= 0.18.1, < 2.0)
+ rake (11.3.0)
+ rdoc (4.2.2)
+ json (~> 1.4)
+ sass (3.4.22)
+ sass-rails (5.0.6)
+ railties (>= 4.0.0, < 6)
+ sass (~> 3.1)
+ sprockets (>= 2.8, < 4.0)
+ sprockets-rails (>= 2.0, < 4.0)
+ tilt (>= 1.1, < 3)
+ sdoc (0.4.1)
+ json (~> 1.7, >= 1.7.7)
+ rdoc (~> 4.0)
+ spring (1.7.2)
+ sprockets (3.7.0)
+ concurrent-ruby (~> 1.0)
+ rack (> 1, < 3)
+ sprockets-rails (3.2.0)
+ actionpack (>= 4.0)
+ activesupport (>= 4.0)
+ sprockets (>= 3.0.0)
+ sqlite3 (1.3.11)
+ thor (0.19.1)
+ thread_safe (0.3.5)
+ tilt (2.0.5)
+ turbolinks (5.0.1)
+ turbolinks-source (~> 5)
+ turbolinks-source (5.0.0)
+ tzinfo (1.2.2)
+ thread_safe (~> 0.1)
+ uglifier (3.0.2)
+ execjs (>= 0.3.0, < 3)
+ web-console (2.3.0)
+ activemodel (>= 4.0)
+ binding_of_caller (>= 0.7.2)
+ railties (>= 4.0)
+ sprockets-rails (>= 2.0, < 4.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ byebug
+ coffee-rails (~> 4.1.0)
+ jbuilder (~> 2.0)
+ jquery-rails
+ rails (= 4.2.7)
+ sass-rails (~> 5.0)
+ sdoc (~> 0.4.0)
+ spring
+ sqlite3
+ turbolinks
+ uglifier (>= 1.3.0)
+ web-console (~> 2.0)
+
+BUNDLED WITH
+ 1.13.1
diff --git a/README.rdoc b/README.rdoc
new file mode 100644
index 000000000..dd4e97e22
--- /dev/null
+++ b/README.rdoc
@@ -0,0 +1,28 @@
+== README
+
+This README would normally document whatever steps are necessary to get the
+application up and running.
+
+Things you may want to cover:
+
+* Ruby version
+
+* System dependencies
+
+* Configuration
+
+* Database creation
+
+* Database initialization
+
+* How to run the test suite
+
+* Services (job queues, cache servers, search engines, etc.)
+
+* Deployment instructions
+
+* ...
+
+
+Please feel free to use a different markup language if you do not plan to run
+rake doc:app .
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 000000000..ba6b733dd
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,6 @@
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require File.expand_path('../config/application', __FILE__)
+
+Rails.application.load_tasks
diff --git a/app/assets/images/.keep b/app/assets/images/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
new file mode 100644
index 000000000..e07c5a830
--- /dev/null
+++ b/app/assets/javascripts/application.js
@@ -0,0 +1,16 @@
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
+//
+// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+// compiled file.
+//
+// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
+// about supported directives.
+//
+//= require jquery
+//= require jquery_ujs
+//= require turbolinks
+//= require_tree .
diff --git a/app/assets/javascripts/tasks.coffee b/app/assets/javascripts/tasks.coffee
new file mode 100644
index 000000000..24f83d18b
--- /dev/null
+++ b/app/assets/javascripts/tasks.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
new file mode 100644
index 000000000..f9cd5b348
--- /dev/null
+++ b/app/assets/stylesheets/application.css
@@ -0,0 +1,15 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
+ * compiled file so the styles you add here take precedence over styles defined in any styles
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
+ * file per style scope.
+ *
+ *= require_tree .
+ *= require_self
+ */
diff --git a/app/assets/stylesheets/tasks.scss b/app/assets/stylesheets/tasks.scss
new file mode 100644
index 000000000..c5e7712d4
--- /dev/null
+++ b/app/assets/stylesheets/tasks.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the Tasks controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
new file mode 100644
index 000000000..d83690e1b
--- /dev/null
+++ b/app/controllers/application_controller.rb
@@ -0,0 +1,5 @@
+class ApplicationController < ActionController::Base
+ # Prevent CSRF attacks by raising an exception.
+ # For APIs, you may want to use :null_session instead.
+ protect_from_forgery with: :exception
+end
diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
new file mode 100644
index 000000000..41c6f1257
--- /dev/null
+++ b/app/controllers/tasks_controller.rb
@@ -0,0 +1,37 @@
+class TasksController < ApplicationController
+ def index
+ @id = params[:id]
+ @tasks = [
+ {
+ task: "Grocery shopping",
+ description: "fruit, bread, turkey",
+ completion_status: "incomplete",
+ completion_date: "Sept 27, 2016"
+ },
+ {
+ task: "Laundry",
+ description: "darks",
+ completion_status: "in-progress",
+ completion_date: "Sept 30, 2016"
+ }
+ ]
+ end
+
+ def show
+ @id = params[:id]
+ @tasks = [
+ {
+ task: "Grocery shopping",
+ description: "fruit, bread, turkey",
+ completion_status: "incomplete",
+ completion_date: "Sept 27, 2016"
+ },
+ {
+ task: "Laundry",
+ description: "darks",
+ completion_status: "in-progress",
+ completion_date: "Sept 30, 2016"
+ }
+ ]
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
new file mode 100644
index 000000000..de6be7945
--- /dev/null
+++ b/app/helpers/application_helper.rb
@@ -0,0 +1,2 @@
+module ApplicationHelper
+end
diff --git a/app/helpers/tasks_helper.rb b/app/helpers/tasks_helper.rb
new file mode 100644
index 000000000..ce894d00c
--- /dev/null
+++ b/app/helpers/tasks_helper.rb
@@ -0,0 +1,2 @@
+module TasksHelper
+end
diff --git a/app/mailers/.keep b/app/mailers/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/app/models/.keep b/app/models/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
new file mode 100644
index 000000000..46eeb110b
--- /dev/null
+++ b/app/views/layouts/application.html.erb
@@ -0,0 +1,14 @@
+
+
+
+ TaskListRails
+ <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
+ <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
+ <%= csrf_meta_tags %>
+
+
+
+<%= yield %>
+
+
+
diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb
new file mode 100644
index 000000000..de537211d
--- /dev/null
+++ b/app/views/tasks/index.html.erb
@@ -0,0 +1,8 @@
+Hello! Welcome to the Task List!
+
+
+ <% @tasks.each_with_index do |task, index| %>
+ <% @index = index.to_s %>
+ <%= link_to(task[:task], '/tasks/' + @index ) %>
+ <% end %>
+
diff --git a/app/views/tasks/show.html.erb b/app/views/tasks/show.html.erb
new file mode 100644
index 000000000..284f9384d
--- /dev/null
+++ b/app/views/tasks/show.html.erb
@@ -0,0 +1,20 @@
+Here is the task you have selected!
+
+ Title:
+ <%= @tasks[@id.to_i][:task] %>
+
+
+
+ Description:
+ <%= @tasks[@id.to_i][:description] %>
+
+
+
+ Completion status:
+ <%= @tasks[@id.to_i][:completion_status] %>
+
+
+
+ Completion due date:
+ <%= @tasks[@id.to_i][:completion_date] %>
+
diff --git a/bin/bundle b/bin/bundle
new file mode 100755
index 000000000..66e9889e8
--- /dev/null
+++ b/bin/bundle
@@ -0,0 +1,3 @@
+#!/usr/bin/env ruby
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+load Gem.bin_path('bundler', 'bundle')
diff --git a/bin/rails b/bin/rails
new file mode 100755
index 000000000..0138d79b7
--- /dev/null
+++ b/bin/rails
@@ -0,0 +1,9 @@
+#!/usr/bin/env ruby
+begin
+ load File.expand_path('../spring', __FILE__)
+rescue LoadError => e
+ raise unless e.message.include?('spring')
+end
+APP_PATH = File.expand_path('../../config/application', __FILE__)
+require_relative '../config/boot'
+require 'rails/commands'
diff --git a/bin/rake b/bin/rake
new file mode 100755
index 000000000..d87d5f578
--- /dev/null
+++ b/bin/rake
@@ -0,0 +1,9 @@
+#!/usr/bin/env ruby
+begin
+ load File.expand_path('../spring', __FILE__)
+rescue LoadError => e
+ raise unless e.message.include?('spring')
+end
+require_relative '../config/boot'
+require 'rake'
+Rake.application.run
diff --git a/bin/setup b/bin/setup
new file mode 100755
index 000000000..acdb2c138
--- /dev/null
+++ b/bin/setup
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+require 'pathname'
+
+# path to your application root.
+APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
+
+Dir.chdir APP_ROOT do
+ # This script is a starting point to setup your application.
+ # Add necessary setup steps to this file:
+
+ puts "== Installing dependencies =="
+ system "gem install bundler --conservative"
+ system "bundle check || bundle install"
+
+ # puts "\n== Copying sample files =="
+ # unless File.exist?("config/database.yml")
+ # system "cp config/database.yml.sample config/database.yml"
+ # end
+
+ puts "\n== Preparing database =="
+ system "bin/rake db:setup"
+
+ puts "\n== Removing old logs and tempfiles =="
+ system "rm -f log/*"
+ system "rm -rf tmp/cache"
+
+ puts "\n== Restarting application server =="
+ system "touch tmp/restart.txt"
+end
diff --git a/bin/spring b/bin/spring
new file mode 100755
index 000000000..7fe232c3a
--- /dev/null
+++ b/bin/spring
@@ -0,0 +1,15 @@
+#!/usr/bin/env ruby
+
+# This file loads spring without using Bundler, in order to be fast.
+# It gets overwritten when you run the `spring binstub` command.
+
+unless defined?(Spring)
+ require 'rubygems'
+ require 'bundler'
+
+ if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m))
+ Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq.join(Gem.path_separator) }
+ gem 'spring', match[1]
+ require 'spring/binstub'
+ end
+end
diff --git a/config.ru b/config.ru
new file mode 100644
index 000000000..bd83b2541
--- /dev/null
+++ b/config.ru
@@ -0,0 +1,4 @@
+# This file is used by Rack-based servers to start the application.
+
+require ::File.expand_path('../config/environment', __FILE__)
+run Rails.application
diff --git a/config/application.rb b/config/application.rb
new file mode 100644
index 000000000..902432bad
--- /dev/null
+++ b/config/application.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../boot', __FILE__)
+
+require 'rails/all'
+
+# Require the gems listed in Gemfile, including any gems
+# you've limited to :test, :development, or :production.
+Bundler.require(*Rails.groups)
+
+module TaskListRails
+ class Application < Rails::Application
+ # Settings in config/environments/* take precedence over those specified here.
+ # Application configuration should go into files in config/initializers
+ # -- all .rb files in that directory are automatically loaded.
+
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
+ # config.time_zone = 'Central Time (US & Canada)'
+
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
+ # config.i18n.default_locale = :de
+
+ # Do not swallow errors in after_commit/after_rollback callbacks.
+ config.active_record.raise_in_transactional_callbacks = true
+ end
+end
diff --git a/config/boot.rb b/config/boot.rb
new file mode 100644
index 000000000..6b750f00b
--- /dev/null
+++ b/config/boot.rb
@@ -0,0 +1,3 @@
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+
+require 'bundler/setup' # Set up gems listed in the Gemfile.
diff --git a/config/database.yml b/config/database.yml
new file mode 100644
index 000000000..1c1a37ca8
--- /dev/null
+++ b/config/database.yml
@@ -0,0 +1,25 @@
+# SQLite version 3.x
+# gem install sqlite3
+#
+# Ensure the SQLite 3 gem is defined in your Gemfile
+# gem 'sqlite3'
+#
+default: &default
+ adapter: sqlite3
+ pool: 5
+ timeout: 5000
+
+development:
+ <<: *default
+ database: db/development.sqlite3
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+ <<: *default
+ database: db/test.sqlite3
+
+production:
+ <<: *default
+ database: db/production.sqlite3
diff --git a/config/environment.rb b/config/environment.rb
new file mode 100644
index 000000000..ee8d90dc6
--- /dev/null
+++ b/config/environment.rb
@@ -0,0 +1,5 @@
+# Load the Rails application.
+require File.expand_path('../application', __FILE__)
+
+# Initialize the Rails application.
+Rails.application.initialize!
diff --git a/config/environments/development.rb b/config/environments/development.rb
new file mode 100644
index 000000000..b55e2144b
--- /dev/null
+++ b/config/environments/development.rb
@@ -0,0 +1,41 @@
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # In the development environment your application's code is reloaded on
+ # every request. This slows down response time but is perfect for development
+ # since you don't have to restart the web server when you make code changes.
+ config.cache_classes = false
+
+ # Do not eager load code on boot.
+ config.eager_load = false
+
+ # Show full error reports and disable caching.
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Don't care if the mailer can't send.
+ config.action_mailer.raise_delivery_errors = false
+
+ # Print deprecation notices to the Rails logger.
+ config.active_support.deprecation = :log
+
+ # Raise an error on page load if there are pending migrations.
+ config.active_record.migration_error = :page_load
+
+ # Debug mode disables concatenation and preprocessing of assets.
+ # This option may cause significant delays in view rendering with a large
+ # number of complex assets.
+ config.assets.debug = true
+
+ # Asset digests allow you to set far-future HTTP expiration dates on all assets,
+ # yet still be able to expire them through the digest params.
+ config.assets.digest = true
+
+ # Adds additional error checking when serving assets at runtime.
+ # Checks for improperly declared sprockets dependencies.
+ # Raises helpful error messages.
+ config.assets.raise_runtime_errors = true
+
+ # Raises error for missing translations
+ # config.action_view.raise_on_missing_translations = true
+end
diff --git a/config/environments/production.rb b/config/environments/production.rb
new file mode 100644
index 000000000..5c1b32e48
--- /dev/null
+++ b/config/environments/production.rb
@@ -0,0 +1,79 @@
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # Code is not reloaded between requests.
+ config.cache_classes = true
+
+ # Eager load code on boot. This eager loads most of Rails and
+ # your application in memory, allowing both threaded web servers
+ # and those relying on copy on write to perform better.
+ # Rake tasks automatically ignore this option for performance.
+ config.eager_load = true
+
+ # Full error reports are disabled and caching is turned on.
+ config.consider_all_requests_local = false
+ config.action_controller.perform_caching = true
+
+ # Enable Rack::Cache to put a simple HTTP cache in front of your application
+ # Add `rack-cache` to your Gemfile before enabling this.
+ # For large-scale production use, consider using a caching reverse proxy like
+ # NGINX, varnish or squid.
+ # config.action_dispatch.rack_cache = true
+
+ # Disable serving static files from the `/public` folder by default since
+ # Apache or NGINX already handles this.
+ config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
+
+ # Compress JavaScripts and CSS.
+ config.assets.js_compressor = :uglifier
+ # config.assets.css_compressor = :sass
+
+ # Do not fallback to assets pipeline if a precompiled asset is missed.
+ config.assets.compile = false
+
+ # Asset digests allow you to set far-future HTTP expiration dates on all assets,
+ # yet still be able to expire them through the digest params.
+ config.assets.digest = true
+
+ # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
+
+ # Specifies the header that your server uses for sending files.
+ # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
+
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+ # config.force_ssl = true
+
+ # Use the lowest log level to ensure availability of diagnostic information
+ # when problems arise.
+ config.log_level = :debug
+
+ # Prepend all log lines with the following tags.
+ # config.log_tags = [ :subdomain, :uuid ]
+
+ # Use a different logger for distributed setups.
+ # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
+
+ # Use a different cache store in production.
+ # config.cache_store = :mem_cache_store
+
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server.
+ # config.action_controller.asset_host = 'http://assets.example.com'
+
+ # Ignore bad email addresses and do not raise email delivery errors.
+ # Set this to true and configure the email server for immediate delivery to raise delivery errors.
+ # config.action_mailer.raise_delivery_errors = false
+
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+ # the I18n.default_locale when a translation cannot be found).
+ config.i18n.fallbacks = true
+
+ # Send deprecation notices to registered listeners.
+ config.active_support.deprecation = :notify
+
+ # Use default logging formatter so that PID and timestamp are not suppressed.
+ config.log_formatter = ::Logger::Formatter.new
+
+ # Do not dump schema after migrations.
+ config.active_record.dump_schema_after_migration = false
+end
diff --git a/config/environments/test.rb b/config/environments/test.rb
new file mode 100644
index 000000000..1c19f08b2
--- /dev/null
+++ b/config/environments/test.rb
@@ -0,0 +1,42 @@
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # The test environment is used exclusively to run your application's
+ # test suite. You never need to work with it otherwise. Remember that
+ # your test database is "scratch space" for the test suite and is wiped
+ # and recreated between test runs. Don't rely on the data there!
+ config.cache_classes = true
+
+ # Do not eager load code on boot. This avoids loading your whole application
+ # just for the purpose of running a single test. If you are using a tool that
+ # preloads Rails for running tests, you may have to set it to true.
+ config.eager_load = false
+
+ # Configure static file server for tests with Cache-Control for performance.
+ config.serve_static_files = true
+ config.static_cache_control = 'public, max-age=3600'
+
+ # Show full error reports and disable caching.
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Raise exceptions instead of rendering exception templates.
+ config.action_dispatch.show_exceptions = false
+
+ # Disable request forgery protection in test environment.
+ config.action_controller.allow_forgery_protection = false
+
+ # Tell Action Mailer not to deliver emails to the real world.
+ # The :test delivery method accumulates sent emails in the
+ # ActionMailer::Base.deliveries array.
+ config.action_mailer.delivery_method = :test
+
+ # Randomize the order test cases are executed.
+ config.active_support.test_order = :random
+
+ # Print deprecation notices to the stderr.
+ config.active_support.deprecation = :stderr
+
+ # Raises error for missing translations
+ # config.action_view.raise_on_missing_translations = true
+end
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
new file mode 100644
index 000000000..01ef3e663
--- /dev/null
+++ b/config/initializers/assets.rb
@@ -0,0 +1,11 @@
+# Be sure to restart your server when you modify this file.
+
+# Version of your assets, change this if you want to expire all your assets.
+Rails.application.config.assets.version = '1.0'
+
+# Add additional assets to the asset load path
+# Rails.application.config.assets.paths << Emoji.images_path
+
+# Precompile additional assets.
+# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
+# Rails.application.config.assets.precompile += %w( search.js )
diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb
new file mode 100644
index 000000000..59385cdf3
--- /dev/null
+++ b/config/initializers/backtrace_silencers.rb
@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!
diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb
new file mode 100644
index 000000000..7f70458de
--- /dev/null
+++ b/config/initializers/cookies_serializer.rb
@@ -0,0 +1,3 @@
+# Be sure to restart your server when you modify this file.
+
+Rails.application.config.action_dispatch.cookies_serializer = :json
diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb
new file mode 100644
index 000000000..4a994e1e7
--- /dev/null
+++ b/config/initializers/filter_parameter_logging.rb
@@ -0,0 +1,4 @@
+# Be sure to restart your server when you modify this file.
+
+# Configure sensitive parameters which will be filtered from the log file.
+Rails.application.config.filter_parameters += [:password]
diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb
new file mode 100644
index 000000000..ac033bf9d
--- /dev/null
+++ b/config/initializers/inflections.rb
@@ -0,0 +1,16 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format. Inflections
+# are locale specific, and you may define rules for as many different
+# locales as you wish. All of these examples are active by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.plural /^(ox)$/i, '\1en'
+# inflect.singular /^(ox)en/i, '\1'
+# inflect.irregular 'person', 'people'
+# inflect.uncountable %w( fish sheep )
+# end
+
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.acronym 'RESTful'
+# end
diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb
new file mode 100644
index 000000000..dc1899682
--- /dev/null
+++ b/config/initializers/mime_types.rb
@@ -0,0 +1,4 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new mime types for use in respond_to blocks:
+# Mime::Type.register "text/richtext", :rtf
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
new file mode 100644
index 000000000..15d065a84
--- /dev/null
+++ b/config/initializers/session_store.rb
@@ -0,0 +1,3 @@
+# Be sure to restart your server when you modify this file.
+
+Rails.application.config.session_store :cookie_store, key: '_TaskListRails_session'
diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb
new file mode 100644
index 000000000..33725e95f
--- /dev/null
+++ b/config/initializers/wrap_parameters.rb
@@ -0,0 +1,14 @@
+# Be sure to restart your server when you modify this file.
+
+# This file contains settings for ActionController::ParamsWrapper which
+# is enabled by default.
+
+# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
+ActiveSupport.on_load(:action_controller) do
+ wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
+end
+
+# To enable root element in JSON for ActiveRecord objects.
+# ActiveSupport.on_load(:active_record) do
+# self.include_root_in_json = true
+# end
diff --git a/config/locales/en.yml b/config/locales/en.yml
new file mode 100644
index 000000000..065395716
--- /dev/null
+++ b/config/locales/en.yml
@@ -0,0 +1,23 @@
+# Files in the config/locales directory are used for internationalization
+# and are automatically loaded by Rails. If you want to use locales other
+# than English, add the necessary files in this directory.
+#
+# To use the locales, use `I18n.t`:
+#
+# I18n.t 'hello'
+#
+# In views, this is aliased to just `t`:
+#
+# <%= t('hello') %>
+#
+# To use a different locale, set it with `I18n.locale`:
+#
+# I18n.locale = :es
+#
+# This would use the information in config/locales/es.yml.
+#
+# To learn more, please read the Rails Internationalization guide
+# available at http://guides.rubyonrails.org/i18n.html.
+
+en:
+ hello: "Hello world"
diff --git a/config/routes.rb b/config/routes.rb
new file mode 100644
index 000000000..394a38f8d
--- /dev/null
+++ b/config/routes.rb
@@ -0,0 +1,59 @@
+Rails.application.routes.draw do
+ root 'tasks#index'
+ get '/tasks' => 'tasks#index'
+ get '/tasks/:id' => 'tasks#show'
+ # The priority is based upon order of creation: first created -> highest priority.
+ # See how all your routes lay out with "rake routes".
+
+ # You can have the root of your site routed with "root"
+ # root 'welcome#index'
+
+ # Example of regular route:
+ # get 'products/:id' => 'catalog#view'
+
+ # Example of named route that can be invoked with purchase_url(id: product.id)
+ # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
+
+ # Example resource route (maps HTTP verbs to controller actions automatically):
+ # resources :products
+
+ # Example resource route with options:
+ # resources :products do
+ # member do
+ # get 'short'
+ # post 'toggle'
+ # end
+ #
+ # collection do
+ # get 'sold'
+ # end
+ # end
+
+ # Example resource route with sub-resources:
+ # resources :products do
+ # resources :comments, :sales
+ # resource :seller
+ # end
+
+ # Example resource route with more complex sub-resources:
+ # resources :products do
+ # resources :comments
+ # resources :sales do
+ # get 'recent', on: :collection
+ # end
+ # end
+
+ # Example resource route with concerns:
+ # concern :toggleable do
+ # post 'toggle'
+ # end
+ # resources :posts, concerns: :toggleable
+ # resources :photos, concerns: :toggleable
+
+ # Example resource route within a namespace:
+ # namespace :admin do
+ # # Directs /admin/products/* to Admin::ProductsController
+ # # (app/controllers/admin/products_controller.rb)
+ # resources :products
+ # end
+end
diff --git a/config/secrets.yml b/config/secrets.yml
new file mode 100644
index 000000000..8a4bc7e55
--- /dev/null
+++ b/config/secrets.yml
@@ -0,0 +1,22 @@
+# Be sure to restart your server when you modify this file.
+
+# Your secret key is used for verifying the integrity of signed cookies.
+# If you change this key, all old signed cookies will become invalid!
+
+# Make sure the secret is at least 30 characters and all random,
+# no regular words or you'll be exposed to dictionary attacks.
+# You can use `rake secret` to generate a secure secret key.
+
+# Make sure the secrets in this file are kept private
+# if you're sharing your code publicly.
+
+development:
+ secret_key_base: 814d782bfa9a8697ffd3ad81532f7a48c56aef17bec66e146223933829abdfb03a7f1d4848d1a93ec7f346e9259510461d9164ad893eabaa0193350340b9d8e4
+
+test:
+ secret_key_base: 188631562aa626acf1e5d9510a3662acfef73e6f22b797fa919ea7c797d277518697e88660c6dd8d4db8e735d1f91343c92b191cbca46f1f12599ba3c92b07a3
+
+# Do not keep production secrets in the repository,
+# instead read values from the environment.
+production:
+ secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
diff --git a/db/seeds.rb b/db/seeds.rb
new file mode 100644
index 000000000..4edb1e857
--- /dev/null
+++ b/db/seeds.rb
@@ -0,0 +1,7 @@
+# This file should contain all the record creation needed to seed the database with its default values.
+# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
+#
+# Examples:
+#
+# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
+# Mayor.create(name: 'Emanuel', city: cities.first)
diff --git a/lib/assets/.keep b/lib/assets/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/lib/tasks/.keep b/lib/tasks/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/log/.keep b/log/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/public/404.html b/public/404.html
new file mode 100644
index 000000000..b612547fc
--- /dev/null
+++ b/public/404.html
@@ -0,0 +1,67 @@
+
+
+
+ The page you were looking for doesn't exist (404)
+
+
+
+
+
+
+
+
+
The page you were looking for doesn't exist.
+
You may have mistyped the address or the page may have moved.
+
+
If you are the application owner check the logs for more information.
+
+
+
diff --git a/public/422.html b/public/422.html
new file mode 100644
index 000000000..a21f82b3b
--- /dev/null
+++ b/public/422.html
@@ -0,0 +1,67 @@
+
+
+
+ The change you wanted was rejected (422)
+
+
+
+
+
+
+
+
+
The change you wanted was rejected.
+
Maybe you tried to change something you didn't have access to.
+
+
If you are the application owner check the logs for more information.
+
+
+
diff --git a/public/500.html b/public/500.html
new file mode 100644
index 000000000..061abc587
--- /dev/null
+++ b/public/500.html
@@ -0,0 +1,66 @@
+
+
+
+ We're sorry, but something went wrong (500)
+
+
+
+
+
+
+
+
+
We're sorry, but something went wrong.
+
+
If you are the application owner check the logs for more information.
+
+
+
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 000000000..e69de29bb
diff --git a/public/robots.txt b/public/robots.txt
new file mode 100644
index 000000000..3c9c7c01f
--- /dev/null
+++ b/public/robots.txt
@@ -0,0 +1,5 @@
+# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
+#
+# To ban all spiders from the entire site uncomment the next two lines:
+# User-agent: *
+# Disallow: /
diff --git a/test/controllers/.keep b/test/controllers/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/controllers/tasks_controller_test.rb b/test/controllers/tasks_controller_test.rb
new file mode 100644
index 000000000..ab48b116d
--- /dev/null
+++ b/test/controllers/tasks_controller_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class TasksControllerTest < ActionController::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/fixtures/.keep b/test/fixtures/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/helpers/.keep b/test/helpers/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/integration/.keep b/test/integration/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/mailers/.keep b/test/mailers/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/models/.keep b/test/models/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/test_helper.rb b/test/test_helper.rb
new file mode 100644
index 000000000..92e39b2d7
--- /dev/null
+++ b/test/test_helper.rb
@@ -0,0 +1,10 @@
+ENV['RAILS_ENV'] ||= 'test'
+require File.expand_path('../../config/environment', __FILE__)
+require 'rails/test_help'
+
+class ActiveSupport::TestCase
+ # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
+ fixtures :all
+
+ # Add more helper methods to be used by all tests here...
+end
diff --git a/vendor/assets/javascripts/.keep b/vendor/assets/javascripts/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/vendor/assets/stylesheets/.keep b/vendor/assets/stylesheets/.keep
new file mode 100644
index 000000000..e69de29bb
From f66746dfe180aabe00ffe93fcf14693be43fd8d0 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Wed, 28 Sep 2016 15:53:54 -0700
Subject: [PATCH 02/25] Wave 1 complete, form done, need to connect to DB
---
app/controllers/tasks_controller.rb | 39 ++++++-----------------
app/models/task.rb | 2 ++
app/views/tasks/index.html.erb | 16 ++++++----
app/views/tasks/new.html.erb | 24 ++++++++++++++
app/views/tasks/show.html.erb | 10 +++---
config/routes.rb | 5 ++-
db/migrate/20160928221310_create_tasks.rb | 12 +++++++
db/schema.rb | 25 +++++++++++++++
test/fixtures/tasks.yml | 13 ++++++++
test/models/task_test.rb | 7 ++++
10 files changed, 112 insertions(+), 41 deletions(-)
create mode 100644 app/models/task.rb
create mode 100644 app/views/tasks/new.html.erb
create mode 100644 db/migrate/20160928221310_create_tasks.rb
create mode 100644 db/schema.rb
create mode 100644 test/fixtures/tasks.yml
create mode 100644 test/models/task_test.rb
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index 41c6f1257..f85da658a 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -1,37 +1,16 @@
class TasksController < ApplicationController
def index
- @id = params[:id]
- @tasks = [
- {
- task: "Grocery shopping",
- description: "fruit, bread, turkey",
- completion_status: "incomplete",
- completion_date: "Sept 27, 2016"
- },
- {
- task: "Laundry",
- description: "darks",
- completion_status: "in-progress",
- completion_date: "Sept 30, 2016"
- }
- ]
+ @tasks = Task.all
end
def show
- @id = params[:id]
- @tasks = [
- {
- task: "Grocery shopping",
- description: "fruit, bread, turkey",
- completion_status: "incomplete",
- completion_date: "Sept 27, 2016"
- },
- {
- task: "Laundry",
- description: "darks",
- completion_status: "in-progress",
- completion_date: "Sept 30, 2016"
- }
- ]
+ @task = Task.find(params[:id])
+ end
+
+ def new; end
+
+ def create
+ # Here is where we would save to the database
+ redirect_to tasks_path
end
end
diff --git a/app/models/task.rb b/app/models/task.rb
new file mode 100644
index 000000000..935f76e12
--- /dev/null
+++ b/app/models/task.rb
@@ -0,0 +1,2 @@
+class Task < ActiveRecord::Base
+end
diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb
index de537211d..9ae2463e3 100644
--- a/app/views/tasks/index.html.erb
+++ b/app/views/tasks/index.html.erb
@@ -1,8 +1,12 @@
Hello! Welcome to the Task List!
-
- <% @tasks.each_with_index do |task, index| %>
- <% @index = index.to_s %>
- <%= link_to(task[:task], '/tasks/' + @index ) %>
- <% end %>
-
+<% @tasks.each do |t| %>
+
+ <%= "Task: #{ t.name }" %>
+ <%= link_to "Find more info here", task_path(t) %>
+
+<% end %>
+
+
+ Would you like to add a new task? If so, <%= link_to "click here", tasks_new_path %>
+
diff --git a/app/views/tasks/new.html.erb b/app/views/tasks/new.html.erb
new file mode 100644
index 000000000..9c22c7c0e
--- /dev/null
+++ b/app/views/tasks/new.html.erb
@@ -0,0 +1,24 @@
+
+
+<%= link_to("Back to the Tasks", tasks_path) %>
diff --git a/app/views/tasks/show.html.erb b/app/views/tasks/show.html.erb
index 284f9384d..0f5cfe390 100644
--- a/app/views/tasks/show.html.erb
+++ b/app/views/tasks/show.html.erb
@@ -1,20 +1,22 @@
Here is the task you have selected!
Title:
- <%= @tasks[@id.to_i][:task] %>
+ <%= @task.name %>
Description:
- <%= @tasks[@id.to_i][:description] %>
+ <%= @task.description %>
Completion status:
- <%= @tasks[@id.to_i][:completion_status] %>
+ <%= @task.is_completed %>
Completion due date:
- <%= @tasks[@id.to_i][:completion_date] %>
+ <%= @task.completed_at %>
+
+<%= link_to "Return back to the list", tasks_path %>
diff --git a/config/routes.rb b/config/routes.rb
index 394a38f8d..b8676cbef 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,7 +1,10 @@
Rails.application.routes.draw do
root 'tasks#index'
get '/tasks' => 'tasks#index'
- get '/tasks/:id' => 'tasks#show'
+ get '/tasks/new' => 'tasks#new'
+ get '/tasks/:id', to: 'tasks#show', as: 'task'
+
+ post '/tasks' => 'tasks#create'
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
diff --git a/db/migrate/20160928221310_create_tasks.rb b/db/migrate/20160928221310_create_tasks.rb
new file mode 100644
index 000000000..c1ca76f53
--- /dev/null
+++ b/db/migrate/20160928221310_create_tasks.rb
@@ -0,0 +1,12 @@
+class CreateTasks < ActiveRecord::Migration
+ def change
+ create_table :tasks do |t|
+ t.string :name
+ t.string :description
+ t.boolean :is_completed
+ t.datetime :completed_at
+
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
new file mode 100644
index 000000000..70d5fa310
--- /dev/null
+++ b/db/schema.rb
@@ -0,0 +1,25 @@
+# encoding: UTF-8
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your
+# database schema. If you need to create the application database on another
+# system, you should be using db:schema:load, not running all the migrations
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended that you check this file into your version control system.
+
+ActiveRecord::Schema.define(version: 20160928221310) do
+
+ create_table "tasks", force: :cascade do |t|
+ t.string "name"
+ t.string "description"
+ t.boolean "is_completed"
+ t.datetime "completed_at"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+end
diff --git a/test/fixtures/tasks.yml b/test/fixtures/tasks.yml
new file mode 100644
index 000000000..f39266e37
--- /dev/null
+++ b/test/fixtures/tasks.yml
@@ -0,0 +1,13 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ name: MyString
+ description: MyString
+ is_completed: false
+ completed_at: 2016-09-28 15:13:10
+
+two:
+ name: MyString
+ description: MyString
+ is_completed: false
+ completed_at: 2016-09-28 15:13:10
diff --git a/test/models/task_test.rb b/test/models/task_test.rb
new file mode 100644
index 000000000..3ca215970
--- /dev/null
+++ b/test/models/task_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class TaskTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
From dd999f7915bacb76110df9dbae36b004ddd7c69a Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Thu, 29 Sep 2016 16:39:36 -0700
Subject: [PATCH 03/25] Satisfied Wave 2 requirements
---
app/controllers/tasks_controller.rb | 41 +++++++++++++++++++++++--
app/views/tasks/delete_confirm.html.erb | 7 +++++
app/views/tasks/edit.html.erb | 17 ++++++++++
app/views/tasks/index.html.erb | 2 ++
app/views/tasks/new.html.erb | 31 ++++++++-----------
config/routes.rb | 11 ++++++-
6 files changed, 86 insertions(+), 23 deletions(-)
create mode 100644 app/views/tasks/delete_confirm.html.erb
create mode 100644 app/views/tasks/edit.html.erb
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index f85da658a..5d7b9e482 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -7,10 +7,45 @@ def show
@task = Task.find(params[:id])
end
- def new; end
+ def new
+ @task = Task.new
+ end
def create
- # Here is where we would save to the database
- redirect_to tasks_path
+ @task = Task.new(task_params)
+ if @task.save
+ redirect_to root_path
+ else
+ render :new
+ end
+ end
+
+ def delete_confirm
+ @task = Task.find(params[:id])
+ end
+
+ def delete
+ @task = Task.find(params[:id])
+ @task.destroy
+ redirect_to root_path
+ end
+
+ def edit # Will give the form, like new
+ @task = Task.find(params[:id])
+ end
+
+ def update # Actually do the update, like create
+ @task = Task.find(params[:id])
+ if @task.update(task_params)
+ redirect_to root_path
+ else
+ render :edit
+ end
+ end
+
+ private
+
+ def task_params
+ params.require(:task).permit(:name, :description, :is_completed, :completed_at)
end
end
diff --git a/app/views/tasks/delete_confirm.html.erb b/app/views/tasks/delete_confirm.html.erb
new file mode 100644
index 000000000..a8723a7ae
--- /dev/null
+++ b/app/views/tasks/delete_confirm.html.erb
@@ -0,0 +1,7 @@
+<%= @task.name %>
+<%= form_for @task, method: :delete do |f| %>
+ Are you sure you want to delete this task?
+ <%= f.submit "Delete" %>
+<% end %>
+
+<%= link_to("Back to the Tasks", tasks_path) %>
diff --git a/app/views/tasks/edit.html.erb b/app/views/tasks/edit.html.erb
new file mode 100644
index 000000000..cf4e4c5b2
--- /dev/null
+++ b/app/views/tasks/edit.html.erb
@@ -0,0 +1,17 @@
+<%= form_for @task, method: :patch do |f| %>
+ <%= f.label :name %>
+ <%= f.text_field :name %>
+
+ <%= f.label :description %>
+ <%= f.text_field :description %>
+
+ <%= f.label :is_completed %>
+ <%= f.check_box :is_completed %>
+
+ <%= f.label :completed_at %>
+ <%= f.date_field :completed_at %>
+
+ <%= f.submit %>
+<% end %>
+
+<%= link_to("Back to the Tasks", tasks_path) %>
diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb
index 9ae2463e3..014befa31 100644
--- a/app/views/tasks/index.html.erb
+++ b/app/views/tasks/index.html.erb
@@ -4,6 +4,8 @@
<%= "Task: #{ t.name }" %>
<%= link_to "Find more info here", task_path(t) %>
+ <%= link_to "Edit", task_edit_path(t) %>
+ <%= link_to "Delete", task_delete_confirm_path(t) %>
<% end %>
diff --git a/app/views/tasks/new.html.erb b/app/views/tasks/new.html.erb
index 9c22c7c0e..64cce05e0 100644
--- a/app/views/tasks/new.html.erb
+++ b/app/views/tasks/new.html.erb
@@ -1,24 +1,17 @@
-
+ <%= f.label :completed_at %>
+ <%= f.date_field :completed_at %>
+
+ <%= f.submit %>
+<% end %>
<%= link_to("Back to the Tasks", tasks_path) %>
diff --git a/config/routes.rb b/config/routes.rb
index b8676cbef..c60b79cc6 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,9 +2,18 @@
root 'tasks#index'
get '/tasks' => 'tasks#index'
get '/tasks/new' => 'tasks#new'
+ post '/tasks' => 'tasks#create'
+
+ get 'tasks/:id/edit', to: 'tasks#edit', as: 'task_edit'
+ patch 'tasks/:id' => 'tasks#update'
+
+ get 'tasks/:id/delete_confirm', to: 'tasks#delete_confirm', as: 'task_delete_confirm'
+
+ delete 'tasks/:id' => 'tasks#delete'
+
get '/tasks/:id', to: 'tasks#show', as: 'task'
- post '/tasks' => 'tasks#create'
+
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
From 8131255213e2ddde0ad9a47f2630f64fc0a4ac65 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Thu, 29 Sep 2016 16:57:30 -0700
Subject: [PATCH 04/25] Edit working, completed_by button in progress
---
app/views/tasks/index.html.erb | 1 +
config/routes.rb | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb
index 014befa31..b1bca0320 100644
--- a/app/views/tasks/index.html.erb
+++ b/app/views/tasks/index.html.erb
@@ -6,6 +6,7 @@
<%= link_to "Find more info here", task_path(t) %>
<%= link_to "Edit", task_edit_path(t) %>
<%= link_to "Delete", task_delete_confirm_path(t) %>
+ <%= button_to "Done!" %>
<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index c60b79cc6..9c797948e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -8,7 +8,6 @@
patch 'tasks/:id' => 'tasks#update'
get 'tasks/:id/delete_confirm', to: 'tasks#delete_confirm', as: 'task_delete_confirm'
-
delete 'tasks/:id' => 'tasks#delete'
get '/tasks/:id', to: 'tasks#show', as: 'task'
From bb3b8ca4fa676cd0fc749ef0591df1b13ce466b0 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Fri, 30 Sep 2016 10:24:45 -0700
Subject: [PATCH 05/25] Delete and confirm working
---
app/controllers/tasks_controller.rb | 9 ++-------
app/views/tasks/delete_confirm.html.erb | 7 -------
app/views/tasks/index.html.erb | 3 +--
app/views/tasks/show.html.erb | 1 +
config/routes.rb | 3 +--
5 files changed, 5 insertions(+), 18 deletions(-)
delete mode 100644 app/views/tasks/delete_confirm.html.erb
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index 5d7b9e482..894e6c798 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -20,13 +20,8 @@ def create
end
end
- def delete_confirm
- @task = Task.find(params[:id])
- end
-
- def delete
- @task = Task.find(params[:id])
- @task.destroy
+ def destroy
+ @task = Task.find(params[:id]).destroy
redirect_to root_path
end
diff --git a/app/views/tasks/delete_confirm.html.erb b/app/views/tasks/delete_confirm.html.erb
deleted file mode 100644
index a8723a7ae..000000000
--- a/app/views/tasks/delete_confirm.html.erb
+++ /dev/null
@@ -1,7 +0,0 @@
-<%= @task.name %>
-<%= form_for @task, method: :delete do |f| %>
- Are you sure you want to delete this task?
- <%= f.submit "Delete" %>
-<% end %>
-
-<%= link_to("Back to the Tasks", tasks_path) %>
diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb
index b1bca0320..133315e63 100644
--- a/app/views/tasks/index.html.erb
+++ b/app/views/tasks/index.html.erb
@@ -5,8 +5,7 @@
<%= "Task: #{ t.name }" %>
<%= link_to "Find more info here", task_path(t) %>
<%= link_to "Edit", task_edit_path(t) %>
- <%= link_to "Delete", task_delete_confirm_path(t) %>
- <%= button_to "Done!" %>
+ <%= link_to "Destroy", task_path(t), method: :delete, data: { confirm: "Are you really sure?" } %>
<% end %>
diff --git a/app/views/tasks/show.html.erb b/app/views/tasks/show.html.erb
index 0f5cfe390..96b0df29c 100644
--- a/app/views/tasks/show.html.erb
+++ b/app/views/tasks/show.html.erb
@@ -19,4 +19,5 @@
<%= @task.completed_at %>
+<%= link_to "Edit", task_edit_path(@task) %>
<%= link_to "Return back to the list", tasks_path %>
diff --git a/config/routes.rb b/config/routes.rb
index 9c797948e..9264138ca 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -7,8 +7,7 @@
get 'tasks/:id/edit', to: 'tasks#edit', as: 'task_edit'
patch 'tasks/:id' => 'tasks#update'
- get 'tasks/:id/delete_confirm', to: 'tasks#delete_confirm', as: 'task_delete_confirm'
- delete 'tasks/:id' => 'tasks#delete'
+ delete 'tasks/:id' => 'tasks#destroy'
get '/tasks/:id', to: 'tasks#show', as: 'task'
From bfe29fd3a0688bd7e2f364f6f8e60e2ed3e9fde4 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Fri, 30 Sep 2016 10:51:34 -0700
Subject: [PATCH 06/25] Task complete button updates is_completed and
completed_at time
---
app/views/tasks/index.html.erb | 5 +++++
app/views/tasks/show.html.erb | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb
index 133315e63..3f643988e 100644
--- a/app/views/tasks/index.html.erb
+++ b/app/views/tasks/index.html.erb
@@ -6,6 +6,11 @@
<%= link_to "Find more info here", task_path(t) %>
<%= link_to "Edit", task_edit_path(t) %>
<%= link_to "Destroy", task_path(t), method: :delete, data: { confirm: "Are you really sure?" } %>
+ <%= form_for t do |f| %>
+ <%= f.hidden_field :is_completed, :value=>true %>
+ <%= f.hidden_field :completed_at, :value=>Time.now %>
+ <%= f.submit "Task is complete" %>
+ <% end %>
<% end %>
diff --git a/app/views/tasks/show.html.erb b/app/views/tasks/show.html.erb
index 96b0df29c..768007a16 100644
--- a/app/views/tasks/show.html.erb
+++ b/app/views/tasks/show.html.erb
@@ -20,4 +20,4 @@
<%= link_to "Edit", task_edit_path(@task) %>
-<%= link_to "Return back to the list", tasks_path %>
+<%= link_to "Return back to the list", tasks_path %>
From 10424d68d1242887c9ba53dcaa1a9f86ca3e587e Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Fri, 30 Sep 2016 11:03:10 -0700
Subject: [PATCH 07/25] Optional DRY using _form.html.erb completed
---
app/views/tasks/_form.html.erb | 17 +++++++++++++++++
app/views/tasks/edit.html.erb | 18 +-----------------
app/views/tasks/new.html.erb | 18 +-----------------
3 files changed, 19 insertions(+), 34 deletions(-)
create mode 100644 app/views/tasks/_form.html.erb
diff --git a/app/views/tasks/_form.html.erb b/app/views/tasks/_form.html.erb
new file mode 100644
index 000000000..64cce05e0
--- /dev/null
+++ b/app/views/tasks/_form.html.erb
@@ -0,0 +1,17 @@
+<%= form_for @task do |f| %>
+ <%= f.label :name %>
+ <%= f.text_field :name %>
+
+ <%= f.label :description %>
+ <%= f.text_field :description %>
+
+ <%= f.label :is_completed %>
+ <%= f.check_box :is_completed %>
+
+ <%= f.label :completed_at %>
+ <%= f.date_field :completed_at %>
+
+ <%= f.submit %>
+<% end %>
+
+<%= link_to("Back to the Tasks", tasks_path) %>
diff --git a/app/views/tasks/edit.html.erb b/app/views/tasks/edit.html.erb
index cf4e4c5b2..612e47954 100644
--- a/app/views/tasks/edit.html.erb
+++ b/app/views/tasks/edit.html.erb
@@ -1,17 +1 @@
-<%= form_for @task, method: :patch do |f| %>
- <%= f.label :name %>
- <%= f.text_field :name %>
-
- <%= f.label :description %>
- <%= f.text_field :description %>
-
- <%= f.label :is_completed %>
- <%= f.check_box :is_completed %>
-
- <%= f.label :completed_at %>
- <%= f.date_field :completed_at %>
-
- <%= f.submit %>
-<% end %>
-
-<%= link_to("Back to the Tasks", tasks_path) %>
+<%= render partial: "form", method: :patch %>
diff --git a/app/views/tasks/new.html.erb b/app/views/tasks/new.html.erb
index 64cce05e0..d44c608b6 100644
--- a/app/views/tasks/new.html.erb
+++ b/app/views/tasks/new.html.erb
@@ -1,17 +1 @@
-<%= form_for @task do |f| %>
- <%= f.label :name %>
- <%= f.text_field :name %>
-
- <%= f.label :description %>
- <%= f.text_field :description %>
-
- <%= f.label :is_completed %>
- <%= f.check_box :is_completed %>
-
- <%= f.label :completed_at %>
- <%= f.date_field :completed_at %>
-
- <%= f.submit %>
-<% end %>
-
-<%= link_to("Back to the Tasks", tasks_path) %>
+<%= render partial: "form" %>
From bda3ad021dcdbb0bbf741c1684dbfc17878b424f Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Fri, 30 Sep 2016 11:52:18 -0700
Subject: [PATCH 08/25] Aesthetic improvements to project
---
app/assets/stylesheets/application.css | 22 ++++++++++++++++++++++
app/views/tasks/_form.html.erb | 26 +++++++++++++++-----------
app/views/tasks/index.html.erb | 14 +++++++-------
app/views/tasks/show.html.erb | 6 +++---
4 files changed, 47 insertions(+), 21 deletions(-)
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
index f9cd5b348..fc79ab5f1 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -13,3 +13,25 @@
*= require_tree .
*= require_self
*/
+
+ html {
+ font: normal normal 14px/1 "Helvetica Neue", Helvetica, Arial, sans-serif;
+ }
+
+ .task_header {
+ margin-top: 0px;
+ margin-bottom: 5px;
+ }
+
+ .task_list {
+ width: 25%;
+ float: left;
+ border: blue 1px solid;
+ padding: 10px;
+ margin: 10px;
+ }
+
+ footer {
+ clear: both;
+ margin-top: 100px;
+ }
diff --git a/app/views/tasks/_form.html.erb b/app/views/tasks/_form.html.erb
index 64cce05e0..dd0bcf80f 100644
--- a/app/views/tasks/_form.html.erb
+++ b/app/views/tasks/_form.html.erb
@@ -1,17 +1,21 @@
+Please enter or update your task!
+
<%= form_for @task do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
-
- <%= f.label :description %>
- <%= f.text_field :description %>
-
- <%= f.label :is_completed %>
- <%= f.check_box :is_completed %>
-
- <%= f.label :completed_at %>
- <%= f.date_field :completed_at %>
-
+
+ <%= f.label :description %>
+ <%= f.text_field :description %>
+
+
+ <%= f.label :is_completed %>
+ <%= f.check_box :is_completed %>
+
+
+ <%= f.label :completed_at %>
+ <%= f.date_field :completed_at %>
+
<%= f.submit %>
<% end %>
-<%= link_to("Back to the Tasks", tasks_path) %>
+<%= link_to("Back to the Tasks", tasks_path) %>
diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb
index 3f643988e..fde681db3 100644
--- a/app/views/tasks/index.html.erb
+++ b/app/views/tasks/index.html.erb
@@ -1,19 +1,19 @@
-Hello! Welcome to the Task List!
+Hello! Welcome to your Task List!
<% @tasks.each do |t| %>
-
- <%= "Task: #{ t.name }" %>
- <%= link_to "Find more info here", task_path(t) %>
+
+
<%= link_to "Edit", task_edit_path(t) %>
+
<%= link_to "Destroy", task_path(t), method: :delete, data: { confirm: "Are you really sure?" } %>
<%= form_for t do |f| %>
<%= f.hidden_field :is_completed, :value=>true %>
<%= f.hidden_field :completed_at, :value=>Time.now %>
<%= f.submit "Task is complete" %>
<% end %>
-
+
<% end %>
-
+
Would you like to add a new task? If so, <%= link_to "click here", tasks_new_path %>
-
+
diff --git a/app/views/tasks/show.html.erb b/app/views/tasks/show.html.erb
index 768007a16..258d799d2 100644
--- a/app/views/tasks/show.html.erb
+++ b/app/views/tasks/show.html.erb
@@ -1,6 +1,6 @@
Here is the task you have selected!
- Title:
+
<%= @task.name %>
@@ -15,9 +15,9 @@
- Completion due date:
+ Completion date:
<%= @task.completed_at %>
-<%= link_to "Edit", task_edit_path(@task) %>
+<%= link_to "Edit task", task_edit_path(@task) %>
<%= link_to "Return back to the list", tasks_path %>
From 6eb15413a31f653693bd02ca42edb55727a4d9be Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Fri, 30 Sep 2016 12:02:03 -0700
Subject: [PATCH 09/25] More CSS improvements - borders, colors
---
app/assets/stylesheets/application.css | 16 ++++++++++++---
app/views/tasks/index.html.erb | 28 ++++++++++++++------------
2 files changed, 28 insertions(+), 16 deletions(-)
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
index fc79ab5f1..2a2233fe9 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -18,20 +18,30 @@
font: normal normal 14px/1 "Helvetica Neue", Helvetica, Arial, sans-serif;
}
+ body {
+ padding-left: 20px;
+ padding-right: 20px;
+ }
+
.task_header {
- margin-top: 0px;
+ margin-top: 0;
margin-bottom: 5px;
}
+ .all_tasks {
+ max-width: 90%;
+ }
+
.task_list {
width: 25%;
float: left;
- border: blue 1px solid;
+ border: green 2px dotted;
padding: 10px;
margin: 10px;
}
footer {
clear: both;
- margin-top: 100px;
+ padding-top: 30px;
+ padding-left: 30px;
}
diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb
index fde681db3..91e3959b2 100644
--- a/app/views/tasks/index.html.erb
+++ b/app/views/tasks/index.html.erb
@@ -1,18 +1,20 @@
Hello! Welcome to your Task List!
-<% @tasks.each do |t| %>
-
-
- <%= link_to "Edit", task_edit_path(t) %>
-
- <%= link_to "Destroy", task_path(t), method: :delete, data: { confirm: "Are you really sure?" } %>
- <%= form_for t do |f| %>
- <%= f.hidden_field :is_completed, :value=>true %>
- <%= f.hidden_field :completed_at, :value=>Time.now %>
- <%= f.submit "Task is complete" %>
- <% end %>
-
-<% end %>
+
+ <% @tasks.each do |t| %>
+
+
+ <%= link_to "Edit", task_edit_path(t) %>
+
+ <%= link_to "Destroy", task_path(t), method: :delete, data: { confirm: "Are you really sure?" } %>
+ <%= form_for t do |f| %>
+ <%= f.hidden_field :is_completed, :value=>true %>
+ <%= f.hidden_field :completed_at, :value=>Time.now %>
+ <%= f.submit "Task is complete" %>
+ <% end %>
+
+ <% end %>
+
Would you like to add a new task? If so, <%= link_to "click here", tasks_new_path %>
From 04318c7f9c63b14e5f18a9865799c111fca7704f Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Fri, 30 Sep 2016 12:19:32 -0700
Subject: [PATCH 10/25] Alignment adjustments - aesthetics only
---
app/assets/stylesheets/application.css | 2 +-
app/views/tasks/index.html.erb | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
index 2a2233fe9..2ac3154f1 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -40,7 +40,7 @@
margin: 10px;
}
- footer {
+ .new_task {
clear: both;
padding-top: 30px;
padding-left: 30px;
diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb
index 91e3959b2..d7b11ee4c 100644
--- a/app/views/tasks/index.html.erb
+++ b/app/views/tasks/index.html.erb
@@ -16,6 +16,6 @@
<% end %>
-
+
From 0f7c48906eec9829660b0a197ac7c0d0540639fa Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Fri, 30 Sep 2016 14:39:34 -0700
Subject: [PATCH 11/25] Minor aesthetic changes
---
app/assets/stylesheets/application.css | 17 +++++++++++-
app/views/tasks/_form.html.erb | 6 ++--
app/views/tasks/index.html.erb | 38 ++++++++++++++++++--------
app/views/tasks/show.html.erb | 4 +--
4 files changed, 46 insertions(+), 19 deletions(-)
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
index 2ac3154f1..a40bb75f4 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -14,24 +14,32 @@
*= require_self
*/
+/*All pages*/
+/*Default font information for entire document*/
html {
font: normal normal 14px/1 "Helvetica Neue", Helvetica, Arial, sans-serif;
}
+/*Force document to not extend to borders of browser*/
body {
padding-left: 20px;
padding-right: 20px;
}
+
+/*Index page*/
+/*Specify how much space is between name of task and edit/destroy options*/
.task_header {
margin-top: 0;
margin-bottom: 5px;
}
+/*Decrease total width of grid of tasks*/
.all_tasks {
max-width: 90%;
}
+/*Formatting for task grid*/
.task_list {
width: 25%;
float: left;
@@ -40,7 +48,14 @@
margin: 10px;
}
- .new_task {
+/*Lower section with completed tasks for better readability*/
+ .finished_tasks {
+ clear: both;
+ padding-top: 30px;
+ }
+
+/*Lower link to add a new task for better readability*/
+ .create_new_task {
clear: both;
padding-top: 30px;
padding-left: 30px;
diff --git a/app/views/tasks/_form.html.erb b/app/views/tasks/_form.html.erb
index dd0bcf80f..e29373026 100644
--- a/app/views/tasks/_form.html.erb
+++ b/app/views/tasks/_form.html.erb
@@ -1,18 +1,18 @@
Please enter or update your task!
<%= form_for @task do |f| %>
- <%= f.label :name %>
+ <%= f.label "Task name" %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_field :description %>
- <%= f.label :is_completed %>
+ <%= f.label "Check if completed" %>
<%= f.check_box :is_completed %>
- <%= f.label :completed_at %>
+ <%= f.label "Completed on" %>
<%= f.date_field :completed_at %>
<%= f.submit %>
diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb
index d7b11ee4c..416f331f3 100644
--- a/app/views/tasks/index.html.erb
+++ b/app/views/tasks/index.html.erb
@@ -1,21 +1,35 @@
Hello! Welcome to your Task List!
+
Unfinished tasks
<% @tasks.each do |t| %>
-
-
- <%= link_to "Edit", task_edit_path(t) %>
-
- <%= link_to "Destroy", task_path(t), method: :delete, data: { confirm: "Are you really sure?" } %>
- <%= form_for t do |f| %>
- <%= f.hidden_field :is_completed, :value=>true %>
- <%= f.hidden_field :completed_at, :value=>Time.now %>
- <%= f.submit "Task is complete" %>
- <% end %>
-
+ <% if t.is_completed == false %>
+
+
+ <%= link_to "Edit", task_edit_path(t) %>
+
+ <%= link_to "Delete", task_path(t), method: :delete, data: { confirm: "Are you really sure?" } %>
+ <%= form_for t do |f| %>
+ <%= f.hidden_field :is_completed, :value=>true %>
+ <%= f.hidden_field :completed_at, :value=>Time.now %>
+ <%= f.submit "Click to mark task as complete" %>
+ <% end %>
+
+ <% end %>
+ <% end %>
+
Completed tasks
+ <% @tasks.each do |t| %>
+ <% if t.is_completed == true %>
+
+
+ <%= link_to "Edit", task_edit_path(t) %>
+
+ <%= link_to "Delete", task_path(t), method: :delete, data: { confirm: "Are you really sure?" } %>
+
+ <% end %>
<% end %>
-
+
Would you like to add a new task? If so, <%= link_to "click here", tasks_new_path %>
diff --git a/app/views/tasks/show.html.erb b/app/views/tasks/show.html.erb
index 258d799d2..b70270886 100644
--- a/app/views/tasks/show.html.erb
+++ b/app/views/tasks/show.html.erb
@@ -1,8 +1,6 @@
Here is the task you have selected!
-
- <%= @task.name %>
-
+<%= @task.name %>
Description:
From f7dd10fc1bb503ba64e13990e51508a58a041553 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Fri, 7 Oct 2016 09:15:40 -0700
Subject: [PATCH 12/25] Preparing to deploy to Heroku
---
app/views/tasks/index.html.erb | 6 +++---
app/views/tasks/show.html.erb | 2 +-
config/routes.rb | 12 +-----------
3 files changed, 5 insertions(+), 15 deletions(-)
diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb
index 416f331f3..a2a2c8149 100644
--- a/app/views/tasks/index.html.erb
+++ b/app/views/tasks/index.html.erb
@@ -6,7 +6,7 @@
<% if t.is_completed == false %>
- <%= link_to "Edit", task_edit_path(t) %>
+ <%= link_to "Edit", edit_task_path(t) %>
<%= link_to "Delete", task_path(t), method: :delete, data: { confirm: "Are you really sure?" } %>
<%= form_for t do |f| %>
@@ -22,7 +22,7 @@
<% if t.is_completed == true %>
- <%= link_to "Edit", task_edit_path(t) %>
+ <%= link_to "Edit", edit_task_path(t) %>
<%= link_to "Delete", task_path(t), method: :delete, data: { confirm: "Are you really sure?" } %>
@@ -31,5 +31,5 @@
- Would you like to add a new task? If so, <%= link_to "click here", tasks_new_path %>
+ Would you like to add a new task? If so, <%= link_to "click here", new_task_path %>
diff --git a/app/views/tasks/show.html.erb b/app/views/tasks/show.html.erb
index b70270886..6d22ed8c7 100644
--- a/app/views/tasks/show.html.erb
+++ b/app/views/tasks/show.html.erb
@@ -17,5 +17,5 @@
<%= @task.completed_at %>
-<%= link_to "Edit task", task_edit_path(@task) %>
+<%= link_to "Edit task", edit_task_path(@task) %>
<%= link_to "Return back to the list", tasks_path %>
diff --git a/config/routes.rb b/config/routes.rb
index 9264138ca..bcc68609b 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,16 +1,6 @@
Rails.application.routes.draw do
root 'tasks#index'
- get '/tasks' => 'tasks#index'
- get '/tasks/new' => 'tasks#new'
- post '/tasks' => 'tasks#create'
-
- get 'tasks/:id/edit', to: 'tasks#edit', as: 'task_edit'
- patch 'tasks/:id' => 'tasks#update'
-
- delete 'tasks/:id' => 'tasks#destroy'
-
- get '/tasks/:id', to: 'tasks#show', as: 'task'
-
+ resources :tasks
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
From dfb79f1671b7d2d8c498a4b03ff5465d9b0590bf Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Fri, 7 Oct 2016 09:18:58 -0700
Subject: [PATCH 13/25] Updated Gemfile for deployment
---
Gemfile | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/Gemfile b/Gemfile
index e87fad5fc..6c62e3d7a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,8 +3,6 @@ source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.7'
-# Use sqlite3 as the database for Active Record
-gem 'sqlite3'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
@@ -32,9 +30,17 @@ gem 'sdoc', '~> 0.4.0', group: :doc
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
+# gems to deploy to Heroku
+group :production do
+ gem 'pg'
+ gem 'rails_12factor'
+end
+
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug'
+ # Use sqlite3 as the database for Active Record
+ gem 'sqlite3'
end
group :development do
@@ -44,4 +50,3 @@ group :development do
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
end
-
From 8b71ee4ab9095208c95c4fb35b2c6df16d0fdee2 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Fri, 7 Oct 2016 09:25:44 -0700
Subject: [PATCH 14/25] Installed updated bundler gem
---
Gemfile.lock | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Gemfile.lock b/Gemfile.lock
index 187046034..8f5268410 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -76,6 +76,7 @@ GEM
nokogiri (1.6.8)
mini_portile2 (~> 2.1.0)
pkg-config (~> 1.1.7)
+ pg (0.19.0)
pkg-config (1.1.7)
rack (1.6.4)
rack-test (0.6.3)
@@ -99,6 +100,11 @@ GEM
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
+ rails_12factor (0.0.3)
+ rails_serve_static_assets
+ rails_stdout_logging
+ rails_serve_static_assets (0.0.5)
+ rails_stdout_logging (0.0.5)
railties (4.2.7)
actionpack (= 4.2.7)
activesupport (= 4.2.7)
@@ -150,7 +156,9 @@ DEPENDENCIES
coffee-rails (~> 4.1.0)
jbuilder (~> 2.0)
jquery-rails
+ pg
rails (= 4.2.7)
+ rails_12factor
sass-rails (~> 5.0)
sdoc (~> 0.4.0)
spring
From 27171d64ef50de31929d911d033b892b68e72019 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Fri, 7 Oct 2016 09:33:17 -0700
Subject: [PATCH 15/25] Added ruby version to Gemfile
---
Gemfile | 3 ++-
Gemfile.lock | 5 ++++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/Gemfile b/Gemfile
index 6c62e3d7a..519119955 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,7 @@
source 'https://rubygems.org'
-
+# Declare version of ruby
+ruby '2.3.1'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.7'
# Use SCSS for stylesheets
diff --git a/Gemfile.lock b/Gemfile.lock
index 8f5268410..c47dc6dbc 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -167,5 +167,8 @@ DEPENDENCIES
uglifier (>= 1.3.0)
web-console (~> 2.0)
+RUBY VERSION
+ ruby 2.3.1p112
+
BUNDLED WITH
- 1.13.1
+ 1.13.2
From 45ea48b0fb451df3075ec744e4160995de655e96 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Mon, 17 Oct 2016 14:36:46 -0700
Subject: [PATCH 16/25] Set up OmniAuth baseline files and paths for Github
---
.gitignore | 1 +
Gemfile | 6 ++++
Gemfile.lock | 35 ++++++++++++++++++++
app/assets/javascripts/sessions.coffee | 3 ++
app/assets/stylesheets/sessions.scss | 3 ++
app/controllers/sessions_controller.rb | 34 +++++++++++++++++++
app/helpers/sessions_helper.rb | 2 ++
app/models/user.rb | 13 ++++++++
app/views/layouts/application.html.erb | 3 ++
config/initializers/omniauth.rb | 3 ++
config/routes.rb | 7 ++++
db/migrate/20161017212955_create_users.rb | 12 +++++++
db/schema.rb | 11 +++++-
test/controllers/sessions_controller_test.rb | 7 ++++
test/fixtures/users.yml | 11 ++++++
test/models/user_test.rb | 7 ++++
16 files changed, 157 insertions(+), 1 deletion(-)
create mode 100644 app/assets/javascripts/sessions.coffee
create mode 100644 app/assets/stylesheets/sessions.scss
create mode 100644 app/controllers/sessions_controller.rb
create mode 100644 app/helpers/sessions_helper.rb
create mode 100644 app/models/user.rb
create mode 100644 config/initializers/omniauth.rb
create mode 100644 db/migrate/20161017212955_create_users.rb
create mode 100644 test/controllers/sessions_controller_test.rb
create mode 100644 test/fixtures/users.yml
create mode 100644 test/models/user_test.rb
diff --git a/.gitignore b/.gitignore
index 050c9d95c..72dcca089 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,4 @@
/log/*
!/log/.keep
/tmp
+.env
diff --git a/Gemfile b/Gemfile
index 519119955..b841132ae 100644
--- a/Gemfile
+++ b/Gemfile
@@ -22,6 +22,9 @@ gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
+gem 'omniauth'
+gem 'omniauth-github'
+
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
@@ -42,6 +45,9 @@ group :development, :test do
gem 'byebug'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
+ gem 'dotenv-rails'
+ gem 'better_errors'
+ gem 'binding_of_caller'
end
group :development do
diff --git a/Gemfile.lock b/Gemfile.lock
index c47dc6dbc..0e26c48dd 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -37,10 +37,15 @@ GEM
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
arel (6.0.3)
+ better_errors (2.1.1)
+ coderay (>= 1.0.0)
+ erubis (>= 2.6.6)
+ rack (>= 0.9.0)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
builder (3.2.2)
byebug (9.0.5)
+ coderay (1.1.1)
coffee-rails (4.1.1)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.1.x)
@@ -50,10 +55,17 @@ GEM
coffee-script-source (1.10.0)
concurrent-ruby (1.0.2)
debug_inspector (0.0.2)
+ dotenv (2.1.1)
+ dotenv-rails (2.1.1)
+ dotenv (= 2.1.1)
+ railties (>= 4.0, < 5.1)
erubis (2.7.0)
execjs (2.7.0)
+ faraday (0.9.2)
+ multipart-post (>= 1.2, < 3)
globalid (0.3.7)
activesupport (>= 4.1.0)
+ hashie (3.4.6)
i18n (0.7.0)
jbuilder (2.6.0)
activesupport (>= 3.0.0, < 5.1)
@@ -63,6 +75,7 @@ GEM
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (1.8.3)
+ jwt (1.5.6)
loofah (2.0.3)
nokogiri (>= 1.5.9)
mail (2.6.4)
@@ -73,9 +86,26 @@ GEM
mini_portile2 (2.1.0)
minitest (5.9.1)
multi_json (1.12.1)
+ multi_xml (0.5.5)
+ multipart-post (2.0.0)
nokogiri (1.6.8)
mini_portile2 (~> 2.1.0)
pkg-config (~> 1.1.7)
+ oauth2 (1.2.0)
+ faraday (>= 0.8, < 0.10)
+ jwt (~> 1.0)
+ multi_json (~> 1.3)
+ multi_xml (~> 0.5)
+ rack (>= 1.2, < 3)
+ omniauth (1.3.1)
+ hashie (>= 1.2, < 4)
+ rack (>= 1.0, < 3)
+ omniauth-github (1.1.2)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.1)
+ omniauth-oauth2 (1.4.0)
+ oauth2 (~> 1.0)
+ omniauth (~> 1.2)
pg (0.19.0)
pkg-config (1.1.7)
rack (1.6.4)
@@ -152,10 +182,15 @@ PLATFORMS
ruby
DEPENDENCIES
+ better_errors
+ binding_of_caller
byebug
coffee-rails (~> 4.1.0)
+ dotenv-rails
jbuilder (~> 2.0)
jquery-rails
+ omniauth
+ omniauth-github
pg
rails (= 4.2.7)
rails_12factor
diff --git a/app/assets/javascripts/sessions.coffee b/app/assets/javascripts/sessions.coffee
new file mode 100644
index 000000000..24f83d18b
--- /dev/null
+++ b/app/assets/javascripts/sessions.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/
diff --git a/app/assets/stylesheets/sessions.scss b/app/assets/stylesheets/sessions.scss
new file mode 100644
index 000000000..7bef9cf82
--- /dev/null
+++ b/app/assets/stylesheets/sessions.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the sessions controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
new file mode 100644
index 000000000..ea69f3562
--- /dev/null
+++ b/app/controllers/sessions_controller.rb
@@ -0,0 +1,34 @@
+class SessionsController < ApplicationController
+
+ def index
+ if session[:user_id].nil?
+ redirect_to login_failure_path
+ return
+ else
+ @user = User.find(session[:user_id]) # < recalls the value set in a previous request
+ end
+ end
+
+ def create
+ auth_hash = request.env['omniauth.auth']
+ redirect_to login_failure_path unless auth_hash['uid']
+
+ @user = User.find_by(uid: auth_hash[:uid], provider: 'github')
+ if @user.nil?
+ # User doesn't match anything in the DB.
+ # Attempt to create a new user.
+ @user = User.build_from_github(auth_hash)
+ render :creation_failure unless @user.save
+ end
+
+ # Save the user ID in the session
+ session[:user_id] = @user.id
+
+ redirect_to sessions_path
+ end
+
+ def destroy
+ session.delete(:user_id)
+ redirect_to login_failure_path
+ end
+end
diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb
new file mode 100644
index 000000000..309f8b2eb
--- /dev/null
+++ b/app/helpers/sessions_helper.rb
@@ -0,0 +1,2 @@
+module SessionsHelper
+end
diff --git a/app/models/user.rb b/app/models/user.rb
new file mode 100644
index 000000000..46b60dd71
--- /dev/null
+++ b/app/models/user.rb
@@ -0,0 +1,13 @@
+class User < ActiveRecord::Base
+ validates :email, :uid, :provider, presence: true
+
+ def self.build_from_github(auth_hash)
+ user = User.new
+ user.uid = auth_hash[:uid]
+ user.provider = 'github'
+ user.name = auth_hash['info']['name']
+ user.email = auth_hash['info']['email']
+
+ return user
+ end
+end
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 46eeb110b..f7c91ac27 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -7,6 +7,9 @@
<%= csrf_meta_tags %>
+
+ <%= button_to "Log out", sessions_path, method: :delete %>
+
<%= yield %>
diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb
new file mode 100644
index 000000000..fd4416122
--- /dev/null
+++ b/config/initializers/omniauth.rb
@@ -0,0 +1,3 @@
+Rails.application.config.middleware.use OmniAuth::Builder do
+ provider :github, ENV["GITHUB_CLIENT_ID"], ENV["GITHUB_CLIENT_SECRET"], scope: "user:email"
+end
diff --git a/config/routes.rb b/config/routes.rb
index bcc68609b..4bad95983 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,6 +2,13 @@
root 'tasks#index'
resources :tasks
+ get "/auth/:provider/callback" => "sessions#create"
+ get "/sessions/login_failure", to: "sessions#login_failure", as: "login_failure"
+
+ get "/sessions", to: "sessions#index", as: "sessions"
+
+ delete "/sessions", to: "sessions#destroy"
+
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
diff --git a/db/migrate/20161017212955_create_users.rb b/db/migrate/20161017212955_create_users.rb
new file mode 100644
index 000000000..605ce98fa
--- /dev/null
+++ b/db/migrate/20161017212955_create_users.rb
@@ -0,0 +1,12 @@
+class CreateUsers < ActiveRecord::Migration
+ def change
+ create_table :users do |t|
+ t.string :name
+ t.string :email
+ t.integer :uid, null: false # this is the identifier provided by Github
+ t.string :provider, null: false # this tells us who provided the identifier
+
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 70d5fa310..42fdf1d0f 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20160928221310) do
+ActiveRecord::Schema.define(version: 20161017212955) do
create_table "tasks", force: :cascade do |t|
t.string "name"
@@ -22,4 +22,13 @@
t.datetime "updated_at", null: false
end
+ create_table "users", force: :cascade do |t|
+ t.string "name"
+ t.string "email"
+ t.integer "uid", null: false
+ t.string "provider", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
end
diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb
new file mode 100644
index 000000000..d30ebc380
--- /dev/null
+++ b/test/controllers/sessions_controller_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class SessionsControllerTest < ActionController::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml
new file mode 100644
index 000000000..937a0c002
--- /dev/null
+++ b/test/fixtures/users.yml
@@ -0,0 +1,11 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+# This model initially had no columns defined. If you add columns to the
+# model remove the '{}' from the fixture names and add the columns immediately
+# below each fixture, per the syntax in the comments below
+#
+one: {}
+# column: value
+#
+two: {}
+# column: value
diff --git a/test/models/user_test.rb b/test/models/user_test.rb
new file mode 100644
index 000000000..82f61e010
--- /dev/null
+++ b/test/models/user_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class UserTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
From 8b5adf10706ba2ff63c998745ad4234cf1d48294 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Mon, 17 Oct 2016 15:05:01 -0700
Subject: [PATCH 17/25] Added logic for logged in vs not, WIP login button
functionality
---
app/controllers/application_controller.rb | 8 ++++++++
app/controllers/sessions_controller.rb | 6 ++++--
app/views/layouts/application.html.erb | 8 +++++++-
app/views/sessions/creation_failed.html.erb | 5 +++++
app/views/sessions/index.html.erb | 0
app/views/sessions/login_failure.html.erb | 1 +
config/routes.rb | 6 +++++-
7 files changed, 30 insertions(+), 4 deletions(-)
create mode 100644 app/views/sessions/creation_failed.html.erb
create mode 100644 app/views/sessions/index.html.erb
create mode 100644 app/views/sessions/login_failure.html.erb
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index d83690e1b..a199f95e9 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -2,4 +2,12 @@ class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
+
+ private
+
+ def current_user
+ @current_user ||= User.find_by(id: session[:user_id])
+ end
+
+ helper_method :current_user
end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index ea69f3562..1b6c225d8 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -28,7 +28,9 @@ def create
end
def destroy
- session.delete(:user_id)
- redirect_to login_failure_path
+ if current_user
+ session.delete(:user_id)
+ end
+ redirect_to root_path
end
end
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index f7c91ac27..568128ac7 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -8,7 +8,13 @@
- <%= button_to "Log out", sessions_path, method: :delete %>
+
+ <% if current_user %>
+ <%= button_to "Log out", sessions_path, method: :delete %>
+ <% else %>
+ <%= button_to "Log in", sessions_login_path, method: :post %>
+ <% end %>
+
<%= yield %>
diff --git a/app/views/sessions/creation_failed.html.erb b/app/views/sessions/creation_failed.html.erb
new file mode 100644
index 000000000..f4902f901
--- /dev/null
+++ b/app/views/sessions/creation_failed.html.erb
@@ -0,0 +1,5 @@
+User creation failed
+
+
+ Tell user why it failed, iterating through errors like we would with a form.
+
diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb
new file mode 100644
index 000000000..e69de29bb
diff --git a/app/views/sessions/login_failure.html.erb b/app/views/sessions/login_failure.html.erb
new file mode 100644
index 000000000..49f3bc923
--- /dev/null
+++ b/app/views/sessions/login_failure.html.erb
@@ -0,0 +1 @@
+Login failure
diff --git a/config/routes.rb b/config/routes.rb
index 4bad95983..c273a2028 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -3,11 +3,15 @@
resources :tasks
get "/auth/:provider/callback" => "sessions#create"
+ post "/auth/:provider" => "sessions#create"
+
get "/sessions/login_failure", to: "sessions#login_failure", as: "login_failure"
get "/sessions", to: "sessions#index", as: "sessions"
- delete "/sessions", to: "sessions#destroy"
+ post "/sessions", to: "sessions#index", as: "sessions_login"
+
+ delete "/logout", to: "sessions#destroy"
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
From 0e05cdf569077a1716d12961af70e2472b7b999b Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Sun, 23 Oct 2016 18:07:43 -0700
Subject: [PATCH 18/25] Login and logout functionality done
---
app/controllers/sessions_controller.rb | 2 +-
app/controllers/tasks_controller.rb | 3 ++-
app/views/layouts/application.html.erb | 4 ++--
app/views/sessions/index.html.erb | 1 +
config/routes.rb | 13 +++++++------
5 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 1b6c225d8..c5303a6ed 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -24,7 +24,7 @@ def create
# Save the user ID in the session
session[:user_id] = @user.id
- redirect_to sessions_path
+ redirect_to root_path
end
def destroy
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index 894e6c798..3d56568a2 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -21,7 +21,8 @@ def create
end
def destroy
- @task = Task.find(params[:id]).destroy
+ @task = Task.find(params[:id])
+ @task.destroy
redirect_to root_path
end
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 568128ac7..199469387 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -10,9 +10,9 @@
<% if current_user %>
- <%= button_to "Log out", sessions_path, method: :delete %>
+ <%= button_to "Log out", sessions_path, method: :delete, data: { confirm: "Are you sure you want to log out?" } %>
<% else %>
- <%= button_to "Log in", sessions_login_path, method: :post %>
+ <%= button_to "Log in with Github", '/auth/github', method: :post %>
<% end %>
diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb
index e69de29bb..2b538bc9f 100644
--- a/app/views/sessions/index.html.erb
+++ b/app/views/sessions/index.html.erb
@@ -0,0 +1 @@
+<%= button_to "Log in with Github", '/auth/github', method: :post %>
diff --git a/config/routes.rb b/config/routes.rb
index c273a2028..0f2987da5 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,17 +1,18 @@
Rails.application.routes.draw do
- root 'tasks#index'
+ root 'sessions#index'
resources :tasks
+
+ # User authentication
get "/auth/:provider/callback" => "sessions#create"
- post "/auth/:provider" => "sessions#create"
+ get "/auth/login", to: "sessions#login", as: "login"
+ delete "/auth/logout", to: "sessions#logout", as: "logout"
- get "/sessions/login_failure", to: "sessions#login_failure", as: "login_failure"
- get "/sessions", to: "sessions#index", as: "sessions"
+ get "/sessions/login_failure", to: "sessions#login_failure", as: "login_failure"
post "/sessions", to: "sessions#index", as: "sessions_login"
-
- delete "/logout", to: "sessions#destroy"
+ delete "/sessions", to: "sessions#destroy"
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
From e56f9baac1427da67aa55b3ec2b4c59081cac0a6 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Sun, 23 Oct 2016 18:27:54 -0700
Subject: [PATCH 19/25] Added minitest gem and increased functionality to
sessions controller
---
Gemfile | 4 ++++
app/controllers/application_controller.rb | 14 +++++++++++++-
app/controllers/sessions_controller.rb | 12 +++++++++---
app/controllers/tasks_controller.rb | 8 ++++++++
app/views/layouts/application.html.erb | 3 +++
app/views/sessions/creation_failed.html.erb | 6 ++----
app/views/sessions/login_failure.html.erb | 4 +++-
app/views/tasks/welcome.html.erb | 7 +++++++
config/routes.rb | 2 +-
9 files changed, 50 insertions(+), 10 deletions(-)
create mode 100644 app/views/tasks/welcome.html.erb
diff --git a/Gemfile b/Gemfile
index b841132ae..5a269f1d6 100644
--- a/Gemfile
+++ b/Gemfile
@@ -40,6 +40,10 @@ group :production do
gem 'rails_12factor'
end
+group :test do
+ gem 'minitest-reporters'
+end
+
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug'
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index a199f95e9..012d0282c 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -2,11 +2,23 @@ class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
+ before_action :require_login
private
def current_user
- @current_user ||= User.find_by(id: session[:user_id])
+ begin
+ @current_user ||= User.find_by(id: session[:user_id])
+ rescue ActiveRecord::RecordNotFound
+ nil
+ end
+ end
+
+ def require_login
+ if current_user.nil?
+ flash[:error] = "You must be logged in"
+ redirect_to root_path
+ end
end
helper_method :current_user
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index c5303a6ed..251a4ea3a 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -1,8 +1,9 @@
class SessionsController < ApplicationController
+ skip_before_action :require_login, only: [:login, :create]
def index
if session[:user_id].nil?
- redirect_to login_failure_path
+ redirect_to root_path
return
else
@user = User.find(session[:user_id]) # < recalls the value set in a previous request
@@ -18,19 +19,24 @@ def create
# User doesn't match anything in the DB.
# Attempt to create a new user.
@user = User.build_from_github(auth_hash)
- render :creation_failure unless @user.save
+ render :creation_failure and return unless @user.save
end
# Save the user ID in the session
session[:user_id] = @user.id
- redirect_to root_path
+ redirect_to :tasks
end
def destroy
if current_user
session.delete(:user_id)
+ flash[:logged_out] = "You are now logged out"
end
redirect_to root_path
end
+
+ def login_failure; end
+
+ def creation_failure; end
end
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index 3d56568a2..220279045 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -1,4 +1,12 @@
class TasksController < ApplicationController
+ skip_before_action :require_login, only: [:welcome, :create]
+
+ def welcome
+ if !session[:user_id].blank?
+ redirect_to :tasks and return
+ end
+ end
+
def index
@tasks = Task.all
end
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 199469387..90635333a 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -14,6 +14,9 @@
<% else %>
<%= button_to "Log in with Github", '/auth/github', method: :post %>
<% end %>
+ <% if current_user %>
+ <%= button_to "Add New Task", new_task_path %>
+ <% end %>
diff --git a/app/views/sessions/creation_failed.html.erb b/app/views/sessions/creation_failed.html.erb
index f4902f901..b6a70745f 100644
--- a/app/views/sessions/creation_failed.html.erb
+++ b/app/views/sessions/creation_failed.html.erb
@@ -1,5 +1,3 @@
-User creation failed
+User creation failed. Please try again
-
- Tell user why it failed, iterating through errors like we would with a form.
-
+<%= button_to "Try again", '/auth/github' %>
diff --git a/app/views/sessions/login_failure.html.erb b/app/views/sessions/login_failure.html.erb
index 49f3bc923..ab96f50fb 100644
--- a/app/views/sessions/login_failure.html.erb
+++ b/app/views/sessions/login_failure.html.erb
@@ -1 +1,3 @@
-Login failure
+Login failed. Please try again.
+
+<%= button_to "Try again", '/auth/github' %>
diff --git a/app/views/tasks/welcome.html.erb b/app/views/tasks/welcome.html.erb
new file mode 100644
index 000000000..b8c002162
--- /dev/null
+++ b/app/views/tasks/welcome.html.erb
@@ -0,0 +1,7 @@
+<% if flash[:logged_out] %>
+
+ <%= flash[:logged_out] %>
+
+
+Welcome to Task List
+<%= button_to "Please log in via Github", 'auth/github' %>
diff --git a/config/routes.rb b/config/routes.rb
index 0f2987da5..c956da3ab 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,5 +1,5 @@
Rails.application.routes.draw do
- root 'sessions#index'
+ root 'tasks#welcome'
resources :tasks
From cd6ed881e4def8ee6d53acb0719c2e3471e07dce Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Sun, 23 Oct 2016 18:43:57 -0700
Subject: [PATCH 20/25] Added controller and model tests
---
Gemfile.lock | 8 ++++
app/models/user.rb | 6 ++-
...led.html.erb => creation_failure.html.erb} | 0
test/controllers/sessions_controller_test.rb | 38 +++++++++++++++++--
test/controllers/tasks_controller_test.rb | 4 +-
test/fixtures/users.yml | 10 ++---
test/models/user_test.rb | 30 +++++++++++++--
test/test_helper.rb | 8 ++++
8 files changed, 88 insertions(+), 16 deletions(-)
rename app/views/sessions/{creation_failed.html.erb => creation_failure.html.erb} (100%)
diff --git a/Gemfile.lock b/Gemfile.lock
index 0e26c48dd..1dd5e8016 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -36,6 +36,7 @@ GEM
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
+ ansi (1.5.0)
arel (6.0.3)
better_errors (2.1.1)
coderay (>= 1.0.0)
@@ -85,6 +86,11 @@ GEM
mime-types-data (3.2016.0521)
mini_portile2 (2.1.0)
minitest (5.9.1)
+ minitest-reporters (1.1.11)
+ ansi
+ builder
+ minitest (>= 5.0)
+ ruby-progressbar
multi_json (1.12.1)
multi_xml (0.5.5)
multipart-post (2.0.0)
@@ -143,6 +149,7 @@ GEM
rake (11.3.0)
rdoc (4.2.2)
json (~> 1.4)
+ ruby-progressbar (1.8.1)
sass (3.4.22)
sass-rails (5.0.6)
railties (>= 4.0.0, < 6)
@@ -189,6 +196,7 @@ DEPENDENCIES
dotenv-rails
jbuilder (~> 2.0)
jquery-rails
+ minitest-reporters
omniauth
omniauth-github
pg
diff --git a/app/models/user.rb b/app/models/user.rb
index 46b60dd71..a539bcca6 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,9 +1,11 @@
class User < ActiveRecord::Base
- validates :email, :uid, :provider, presence: true
+ validates :uid, presence: true, uniqueness: { scope: :provider, message: "Cannot have multiple users from the same provider with the same User ID"}
+ validates :provider, presence: true
+ validates :email, presence: true
def self.build_from_github(auth_hash)
user = User.new
- user.uid = auth_hash[:uid]
+ user.uid = auth_hash['uid']
user.provider = 'github'
user.name = auth_hash['info']['name']
user.email = auth_hash['info']['email']
diff --git a/app/views/sessions/creation_failed.html.erb b/app/views/sessions/creation_failure.html.erb
similarity index 100%
rename from app/views/sessions/creation_failed.html.erb
rename to app/views/sessions/creation_failure.html.erb
diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb
index d30ebc380..178680d10 100644
--- a/test/controllers/sessions_controller_test.rb
+++ b/test/controllers/sessions_controller_test.rb
@@ -1,7 +1,39 @@
require 'test_helper'
class SessionsControllerTest < ActionController::TestCase
- # test "the truth" do
- # assert true
- # end
+ def login_a_user
+ request.env['omniauth.auth'] = OmniAuth.config.mock_auth[:github]
+ get :create, { provider: "github" }
+ end
+
+ test "can create a user" do
+ assert_difference('User.count', 1) do
+ login_a_user
+ assert_response :redirect
+ assert_redirected_to :tasks
+ assert_not_nil session[:user_id]
+ end
+ end
+
+ test "Logging in twice should not create two users" do
+ assert_difference('User.count', 1) do
+ login_a_user
+ end
+
+ assert_no_difference('User.count') do
+ login_a_user
+ assert_response :redirect
+ assert_redirected_to :tasks
+ assert_not_nil session[:user_id]
+ end
+ end
+
+ test "Attempting to login without email shouldn't work" do
+ request.env['omniauth.auth'] = OmniAuth.config.mock_auth[:github]
+ request.env['omniauth.auth'][:info].delete(:email)
+
+ assert_no_difference("User.count") do
+ get :create, { provider: "github" }
+ end
+ end
end
diff --git a/test/controllers/tasks_controller_test.rb b/test/controllers/tasks_controller_test.rb
index ab48b116d..8bb82457a 100644
--- a/test/controllers/tasks_controller_test.rb
+++ b/test/controllers/tasks_controller_test.rb
@@ -1,7 +1,5 @@
require 'test_helper'
class TasksControllerTest < ActionController::TestCase
- # test "the truth" do
- # assert true
- # end
+
end
diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml
index 937a0c002..4516db4d2 100644
--- a/test/fixtures/users.yml
+++ b/test/fixtures/users.yml
@@ -4,8 +4,8 @@
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
-one: {}
-# column: value
-#
-two: {}
-# column: value
+userone:
+ name: Ian
+ email: ian@gmail.com
+ uid: 12345
+ provider: github
diff --git a/test/models/user_test.rb b/test/models/user_test.rb
index 82f61e010..ac1a6c868 100644
--- a/test/models/user_test.rb
+++ b/test/models/user_test.rb
@@ -1,7 +1,31 @@
require 'test_helper'
class UserTest < ActiveSupport::TestCase
- # test "the truth" do
- # assert true
- # end
+ test "Can create a user" do
+ assert_difference('User.count', 1) do
+ User.create(name: "Heather", email: "email@gmail.com", provider: "github", uid: 1352)
+ end
+ end
+
+ test "Cannot create a user without an email address" do
+ user = User.new(name: "Heather", provider: "github", uid: 1352)
+ assert_no_difference('User.count') do
+ user.save
+ end
+ end
+
+ test "Cannot create a user without a provider" do
+ user = User.new(name: "Heather", email: "email@gmail.com", uid: 1352)
+ assert_no_difference('User.count') do
+ user.save
+ end
+ end
+
+ test "Cannot create a user with the same uid and provider" do
+ user = users(:userone)
+ user1 = User.new(name: "Heather", email: "email@gmail.com", provider: "github", uid: 12345)
+ assert_no_difference('User.count') do
+ user1.save
+ end
+ end
end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 92e39b2d7..a7b5001e3 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -1,10 +1,18 @@
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
+require 'minitest/reporters'
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
# Add more helper methods to be used by all tests here...
+ Minitest::Reporters.use!
+
+ def setup
+ OmniAuth.config.test_mode = true
+
+ OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new({ provider: 'github', uid: 123545, info: { email: "a@b.com", name: "Ada" } })
+ end
end
From ce943a46ef5037c06969e0d0d049667fcfa532e2 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Sun, 23 Oct 2016 19:06:38 -0700
Subject: [PATCH 21/25] Added belongs_to relationship between user and task
---
app/controllers/tasks_controller.rb | 39 +++++++++++++------
app/models/task.rb | 1 +
app/models/user.rb | 1 +
app/views/tasks/unauthorized_request.html.erb | 5 +++
app/views/tasks/welcome.html.erb | 1 +
config/routes.rb | 2 +
...61024015245_add_belongs_to_user_to_task.rb | 7 ++++
db/schema.rb | 5 ++-
8 files changed, 49 insertions(+), 12 deletions(-)
create mode 100644 app/views/tasks/unauthorized_request.html.erb
create mode 100644 db/migrate/20161024015245_add_belongs_to_user_to_task.rb
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index 220279045..b27b47f84 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -4,25 +4,35 @@ class TasksController < ApplicationController
def welcome
if !session[:user_id].blank?
redirect_to :tasks and return
+ else
+ render :welcome
end
end
def index
- @tasks = Task.all
+ @tasks = current_user.tasks
+ @complete_tasks = @tasks.complete_tasks
+ @incomplete_tasks = @tasks.incomplete_tasks
end
def show
- @task = Task.find(params[:id])
+ requested_task = Task.find(params[:id])
+
+ if requested_task.user_id == current_user.id
+ @task = current_user.tasks.find(params[:id])
+ else
+ redirect_to :unauth_req
+ end
end
def new
- @task = Task.new
+ @task = current_user.tasks.new
end
def create
- @task = Task.new(task_params)
+ @task = current_user.tasks.new(task_params)
if @task.save
- redirect_to root_path
+ redirect_to tasks_path
else
render :new
end
@@ -31,19 +41,26 @@ def create
def destroy
@task = Task.find(params[:id])
@task.destroy
- redirect_to root_path
+ redirect_to tasks_path
end
def edit # Will give the form, like new
- @task = Task.find(params[:id])
+ requested_task = Task.find(params[:id])
+
+ if requested_task.user_id == current_user.id
+ @task = current_user.tasks.find(params[:id])
+ else
+ redirect_to :unauth_req and return
+ end
end
def update # Actually do the update, like create
- @task = Task.find(params[:id])
- if @task.update(task_params)
- redirect_to root_path
+ requested_task = Task.find(params[:id])
+
+ if requested_task.user_id == current_user.id
+ @task = current_user.tasks.find(params[:id])
else
- render :edit
+ redirect_to :unauth_req and return
end
end
diff --git a/app/models/task.rb b/app/models/task.rb
index 935f76e12..5c58542c4 100644
--- a/app/models/task.rb
+++ b/app/models/task.rb
@@ -1,2 +1,3 @@
class Task < ActiveRecord::Base
+ belongs_to :user
end
diff --git a/app/models/user.rb b/app/models/user.rb
index a539bcca6..a140f30d0 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,4 +1,5 @@
class User < ActiveRecord::Base
+ has_many :tasks
validates :uid, presence: true, uniqueness: { scope: :provider, message: "Cannot have multiple users from the same provider with the same User ID"}
validates :provider, presence: true
validates :email, presence: true
diff --git a/app/views/tasks/unauthorized_request.html.erb b/app/views/tasks/unauthorized_request.html.erb
new file mode 100644
index 000000000..5f83aa8b6
--- /dev/null
+++ b/app/views/tasks/unauthorized_request.html.erb
@@ -0,0 +1,5 @@
+<%= content_tag(:h1) { "Invalid request; please try again" } %>
+
+
+ <%= button_to "See all Tasks", tasks_path %>
+
diff --git a/app/views/tasks/welcome.html.erb b/app/views/tasks/welcome.html.erb
index b8c002162..ccc41d635 100644
--- a/app/views/tasks/welcome.html.erb
+++ b/app/views/tasks/welcome.html.erb
@@ -2,6 +2,7 @@
<%= flash[:logged_out] %>
+<% end %>
Welcome to Task List
<%= button_to "Please log in via Github", 'auth/github' %>
diff --git a/config/routes.rb b/config/routes.rb
index c956da3ab..9080d3689 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,5 +1,7 @@
Rails.application.routes.draw do
root 'tasks#welcome'
+
+ get 'tasks/unauthorized', to: 'tasks#unauthorized_request', as: :unauth_req
resources :tasks
diff --git a/db/migrate/20161024015245_add_belongs_to_user_to_task.rb b/db/migrate/20161024015245_add_belongs_to_user_to_task.rb
new file mode 100644
index 000000000..10a229ca0
--- /dev/null
+++ b/db/migrate/20161024015245_add_belongs_to_user_to_task.rb
@@ -0,0 +1,7 @@
+class AddBelongsToUserToTask < ActiveRecord::Migration
+ def change
+ change_table :tasks do |t|
+ t.belongs_to :user, index: true
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 42fdf1d0f..ba8bf2c5a 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20161017212955) do
+ActiveRecord::Schema.define(version: 20161024015245) do
create_table "tasks", force: :cascade do |t|
t.string "name"
@@ -20,8 +20,11 @@
t.datetime "completed_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.integer "user_id"
end
+ add_index "tasks", ["user_id"], name: "index_tasks_on_user_id"
+
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
From d51c59a61ed363f54ebbd309be7b44afeae008f8 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Sun, 23 Oct 2016 19:11:04 -0700
Subject: [PATCH 22/25] Edited tasks controller method
---
app/controllers/tasks_controller.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index b27b47f84..13609665f 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -11,8 +11,8 @@ def welcome
def index
@tasks = current_user.tasks
- @complete_tasks = @tasks.complete_tasks
- @incomplete_tasks = @tasks.incomplete_tasks
+ # @complete_tasks = @tasks.complete_tasks
+ # @incomplete_tasks = @tasks.incomplete_tasks
end
def show
From 8e83b6ad9ca1f01ace3d4a6b7a12acfe2757ee22 Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Sun, 23 Oct 2016 19:17:48 -0700
Subject: [PATCH 23/25] DRY code
---
app/controllers/tasks_controller.rb | 33 +++++++++--------------------
1 file changed, 10 insertions(+), 23 deletions(-)
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index 13609665f..d5cac940a 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -1,5 +1,6 @@
class TasksController < ApplicationController
skip_before_action :require_login, only: [:welcome, :create]
+ before_action :edit_or_update, only: [:edit, :update, :show]
def welcome
if !session[:user_id].blank?
@@ -15,15 +16,7 @@ def index
# @incomplete_tasks = @tasks.incomplete_tasks
end
- def show
- requested_task = Task.find(params[:id])
-
- if requested_task.user_id == current_user.id
- @task = current_user.tasks.find(params[:id])
- else
- redirect_to :unauth_req
- end
- end
+ def show; end
def new
@task = current_user.tasks.new
@@ -44,17 +37,17 @@ def destroy
redirect_to tasks_path
end
- def edit # Will give the form, like new
- requested_task = Task.find(params[:id])
+ def edit; end
- if requested_task.user_id == current_user.id
- @task = current_user.tasks.find(params[:id])
- else
- redirect_to :unauth_req and return
- end
+ def update; end
+
+ private
+
+ def task_params
+ params.require(:task).permit(:name, :description, :is_completed, :completed_at)
end
- def update # Actually do the update, like create
+ def edit_update_show
requested_task = Task.find(params[:id])
if requested_task.user_id == current_user.id
@@ -63,10 +56,4 @@ def update # Actually do the update, like create
redirect_to :unauth_req and return
end
end
-
- private
-
- def task_params
- params.require(:task).permit(:name, :description, :is_completed, :completed_at)
- end
end
From c5eb017ffd8568ffd26f2448f031e72dfd888d8d Mon Sep 17 00:00:00 2001
From: heatherherrington
Date: Mon, 24 Oct 2016 18:06:33 -0700
Subject: [PATCH 24/25] Added Foundation and semantic HTML
---
app/assets/stylesheets/application.css | 26 +
app/assets/stylesheets/foundation.css | 4226 ++++++++++++++++++++++++
app/controllers/tasks_controller.rb | 2 +-
app/views/layouts/application.html.erb | 28 +-
app/views/tasks/_form.html.erb | 2 +-
app/views/tasks/show.html.erb | 32 +-
6 files changed, 4289 insertions(+), 27 deletions(-)
create mode 100644 app/assets/stylesheets/foundation.css
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
index a40bb75f4..21ffff1c8 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -16,6 +16,8 @@
/*All pages*/
/*Default font information for entire document*/
+@import url('foundation.css');
+
html {
font: normal normal 14px/1 "Helvetica Neue", Helvetica, Arial, sans-serif;
}
@@ -26,6 +28,30 @@
padding-right: 20px;
}
+ /*Header formatting*/
+ .title-area {
+ text-align: center;
+ }
+
+.logout-button {
+ background-color: red;
+}
+
+.new-task-button {
+ background-color: green;
+}
+
+.logout-button, .new-task-button {
+ border-radius: 45px;
+ color: white;
+ font-weight: bold;
+}
+
+/*Footer formatting*/
+footer {
+ margin-top: 100px;
+}
+
/*Index page*/
/*Specify how much space is between name of task and edit/destroy options*/
diff --git a/app/assets/stylesheets/foundation.css b/app/assets/stylesheets/foundation.css
new file mode 100644
index 000000000..c59eaf55b
--- /dev/null
+++ b/app/assets/stylesheets/foundation.css
@@ -0,0 +1,4226 @@
+@charset "UTF-8";
+/**
+ * Foundation for Sites by ZURB
+ * Version 6.2.4
+ * foundation.zurb.com
+ * Licensed under MIT Open Source
+ */
+/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS and IE text size adjust after device orientation change,
+ * without disabling user zoom.
+ */
+html {
+ font-family: sans-serif;
+ /* 1 */
+ -ms-text-size-adjust: 100%;
+ /* 2 */
+ -webkit-text-size-adjust: 100%;
+ /* 2 */ }
+
+/**
+ * Remove default margin.
+ */
+body {
+ margin: 0; }
+
+/* HTML5 display definitions
+ ========================================================================== */
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11
+ * and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block; }
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+audio,
+canvas,
+progress,
+video {
+ display: inline-block;
+ /* 1 */
+ vertical-align: baseline;
+ /* 2 */ }
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+audio:not([controls]) {
+ display: none;
+ height: 0; }
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
+ */
+[hidden],
+template {
+ display: none; }
+
+/* Links
+ ========================================================================== */
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+a {
+ background-color: transparent; }
+
+/**
+ * Improve readability of focused elements when they are also in an
+ * active/hover state.
+ */
+a:active,
+a:hover {
+ outline: 0; }
+
+/* Text-level semantics
+ ========================================================================== */
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+abbr[title] {
+ border-bottom: 1px dotted; }
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+b,
+strong {
+ font-weight: bold; }
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+dfn {
+ font-style: italic; }
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0; }
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+mark {
+ background: #ff0;
+ color: #000; }
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+small {
+ font-size: 80%; }
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline; }
+
+sup {
+ top: -0.5em; }
+
+sub {
+ bottom: -0.25em; }
+
+/* Embedded content
+ ========================================================================== */
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+img {
+ border: 0; }
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+svg:not(:root) {
+ overflow: hidden; }
+
+/* Grouping content
+ ========================================================================== */
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+figure {
+ margin: 1em 40px; }
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+hr {
+ box-sizing: content-box;
+ height: 0; }
+
+/**
+ * Contain overflow in all browsers.
+ */
+pre {
+ overflow: auto; }
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em; }
+
+/* Forms
+ ========================================================================== */
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit;
+ /* 1 */
+ font: inherit;
+ /* 2 */
+ margin: 0;
+ /* 3 */ }
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+button {
+ overflow: visible; }
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+button,
+select {
+ text-transform: none; }
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button;
+ /* 2 */
+ cursor: pointer;
+ /* 3 */ }
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+button[disabled],
+html input[disabled] {
+ cursor: not-allowed; }
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0; }
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+input {
+ line-height: normal; }
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box;
+ /* 1 */
+ padding: 0;
+ /* 2 */ }
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto; }
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
+ */
+input[type="search"] {
+ -webkit-appearance: textfield;
+ /* 1 */
+ box-sizing: content-box;
+ /* 2 */ }
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none; }
+
+/**
+ * Define consistent border, margin, and padding.
+ * [NOTE] We don't enable this ruleset in Foundation, because we want the element to have plain styling.
+ */
+/* fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+ } */
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+legend {
+ border: 0;
+ /* 1 */
+ padding: 0;
+ /* 2 */ }
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+textarea {
+ overflow: auto; }
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+optgroup {
+ font-weight: bold; }
+
+/* Tables
+ ========================================================================== */
+/**
+ * Remove most spacing between table cells.
+ */
+table {
+ border-collapse: collapse;
+ border-spacing: 0; }
+
+td,
+th {
+ padding: 0; }
+
+.foundation-mq {
+ font-family: "small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"; }
+
+html {
+ font-size: 100%;
+ box-sizing: border-box; }
+
+*,
+*::before,
+*::after {
+ box-sizing: inherit; }
+
+body {
+ padding: 0;
+ margin: 0;
+ font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;
+ font-weight: normal;
+ line-height: 1.5;
+ color: #0a0a0a;
+ background: #fefefe;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale; }
+
+img {
+ max-width: 100%;
+ height: auto;
+ -ms-interpolation-mode: bicubic;
+ display: inline-block;
+ vertical-align: middle; }
+
+textarea {
+ height: auto;
+ min-height: 50px;
+ border-radius: 0; }
+
+select {
+ width: 100%;
+ border-radius: 0; }
+
+#map_canvas img,
+#map_canvas embed,
+#map_canvas object,
+.map_canvas img,
+.map_canvas embed,
+.map_canvas object,
+.mqa-display img,
+.mqa-display embed,
+.mqa-display object {
+ max-width: none !important; }
+
+button {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ background: transparent;
+ padding: 0;
+ border: 0;
+ border-radius: 0;
+ line-height: 1; }
+ [data-whatinput='mouse'] button {
+ outline: 0; }
+
+.is-visible {
+ display: block !important; }
+
+.is-hidden {
+ display: none !important; }
+
+.row {
+ max-width: 75rem;
+ margin-left: auto;
+ margin-right: auto; }
+ .row::before, .row::after {
+ content: ' ';
+ display: table; }
+ .row::after {
+ clear: both; }
+ .row.collapse > .column, .row.collapse > .columns {
+ padding-left: 0;
+ padding-right: 0; }
+ .row .row {
+ margin-left: -0.625rem;
+ margin-right: -0.625rem; }
+ @media screen and (min-width: 40em) {
+ .row .row {
+ margin-left: -0.9375rem;
+ margin-right: -0.9375rem; } }
+ .row .row.collapse {
+ margin-left: 0;
+ margin-right: 0; }
+ .row.expanded {
+ max-width: none; }
+ .row.expanded .row {
+ margin-left: auto;
+ margin-right: auto; }
+
+.column, .columns {
+ width: 100%;
+ float: left;
+ padding-left: 0.625rem;
+ padding-right: 0.625rem; }
+ @media screen and (min-width: 40em) {
+ .column, .columns {
+ padding-left: 0.9375rem;
+ padding-right: 0.9375rem; } }
+ .column:last-child:not(:first-child), .columns:last-child:not(:first-child) {
+ float: right; }
+ .column.end:last-child:last-child, .end.columns:last-child:last-child {
+ float: left; }
+
+.column.row.row, .row.row.columns {
+ float: none; }
+
+.row .column.row.row, .row .row.row.columns {
+ padding-left: 0;
+ padding-right: 0;
+ margin-left: 0;
+ margin-right: 0; }
+
+.small-1 {
+ width: 8.33333%; }
+
+.small-push-1 {
+ position: relative;
+ left: 8.33333%; }
+
+.small-pull-1 {
+ position: relative;
+ left: -8.33333%; }
+
+.small-offset-0 {
+ margin-left: 0%; }
+
+.small-2 {
+ width: 16.66667%; }
+
+.small-push-2 {
+ position: relative;
+ left: 16.66667%; }
+
+.small-pull-2 {
+ position: relative;
+ left: -16.66667%; }
+
+.small-offset-1 {
+ margin-left: 8.33333%; }
+
+.small-3 {
+ width: 25%; }
+
+.small-push-3 {
+ position: relative;
+ left: 25%; }
+
+.small-pull-3 {
+ position: relative;
+ left: -25%; }
+
+.small-offset-2 {
+ margin-left: 16.66667%; }
+
+.small-4 {
+ width: 33.33333%; }
+
+.small-push-4 {
+ position: relative;
+ left: 33.33333%; }
+
+.small-pull-4 {
+ position: relative;
+ left: -33.33333%; }
+
+.small-offset-3 {
+ margin-left: 25%; }
+
+.small-5 {
+ width: 41.66667%; }
+
+.small-push-5 {
+ position: relative;
+ left: 41.66667%; }
+
+.small-pull-5 {
+ position: relative;
+ left: -41.66667%; }
+
+.small-offset-4 {
+ margin-left: 33.33333%; }
+
+.small-6 {
+ width: 50%; }
+
+.small-push-6 {
+ position: relative;
+ left: 50%; }
+
+.small-pull-6 {
+ position: relative;
+ left: -50%; }
+
+.small-offset-5 {
+ margin-left: 41.66667%; }
+
+.small-7 {
+ width: 58.33333%; }
+
+.small-push-7 {
+ position: relative;
+ left: 58.33333%; }
+
+.small-pull-7 {
+ position: relative;
+ left: -58.33333%; }
+
+.small-offset-6 {
+ margin-left: 50%; }
+
+.small-8 {
+ width: 66.66667%; }
+
+.small-push-8 {
+ position: relative;
+ left: 66.66667%; }
+
+.small-pull-8 {
+ position: relative;
+ left: -66.66667%; }
+
+.small-offset-7 {
+ margin-left: 58.33333%; }
+
+.small-9 {
+ width: 75%; }
+
+.small-push-9 {
+ position: relative;
+ left: 75%; }
+
+.small-pull-9 {
+ position: relative;
+ left: -75%; }
+
+.small-offset-8 {
+ margin-left: 66.66667%; }
+
+.small-10 {
+ width: 83.33333%; }
+
+.small-push-10 {
+ position: relative;
+ left: 83.33333%; }
+
+.small-pull-10 {
+ position: relative;
+ left: -83.33333%; }
+
+.small-offset-9 {
+ margin-left: 75%; }
+
+.small-11 {
+ width: 91.66667%; }
+
+.small-push-11 {
+ position: relative;
+ left: 91.66667%; }
+
+.small-pull-11 {
+ position: relative;
+ left: -91.66667%; }
+
+.small-offset-10 {
+ margin-left: 83.33333%; }
+
+.small-12 {
+ width: 100%; }
+
+.small-offset-11 {
+ margin-left: 91.66667%; }
+
+.small-up-1 > .column, .small-up-1 > .columns {
+ width: 100%;
+ float: left; }
+ .small-up-1 > .column:nth-of-type(1n), .small-up-1 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .small-up-1 > .column:nth-of-type(1n+1), .small-up-1 > .columns:nth-of-type(1n+1) {
+ clear: both; }
+ .small-up-1 > .column:last-child, .small-up-1 > .columns:last-child {
+ float: left; }
+
+.small-up-2 > .column, .small-up-2 > .columns {
+ width: 50%;
+ float: left; }
+ .small-up-2 > .column:nth-of-type(1n), .small-up-2 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .small-up-2 > .column:nth-of-type(2n+1), .small-up-2 > .columns:nth-of-type(2n+1) {
+ clear: both; }
+ .small-up-2 > .column:last-child, .small-up-2 > .columns:last-child {
+ float: left; }
+
+.small-up-3 > .column, .small-up-3 > .columns {
+ width: 33.33333%;
+ float: left; }
+ .small-up-3 > .column:nth-of-type(1n), .small-up-3 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .small-up-3 > .column:nth-of-type(3n+1), .small-up-3 > .columns:nth-of-type(3n+1) {
+ clear: both; }
+ .small-up-3 > .column:last-child, .small-up-3 > .columns:last-child {
+ float: left; }
+
+.small-up-4 > .column, .small-up-4 > .columns {
+ width: 25%;
+ float: left; }
+ .small-up-4 > .column:nth-of-type(1n), .small-up-4 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .small-up-4 > .column:nth-of-type(4n+1), .small-up-4 > .columns:nth-of-type(4n+1) {
+ clear: both; }
+ .small-up-4 > .column:last-child, .small-up-4 > .columns:last-child {
+ float: left; }
+
+.small-up-5 > .column, .small-up-5 > .columns {
+ width: 20%;
+ float: left; }
+ .small-up-5 > .column:nth-of-type(1n), .small-up-5 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .small-up-5 > .column:nth-of-type(5n+1), .small-up-5 > .columns:nth-of-type(5n+1) {
+ clear: both; }
+ .small-up-5 > .column:last-child, .small-up-5 > .columns:last-child {
+ float: left; }
+
+.small-up-6 > .column, .small-up-6 > .columns {
+ width: 16.66667%;
+ float: left; }
+ .small-up-6 > .column:nth-of-type(1n), .small-up-6 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .small-up-6 > .column:nth-of-type(6n+1), .small-up-6 > .columns:nth-of-type(6n+1) {
+ clear: both; }
+ .small-up-6 > .column:last-child, .small-up-6 > .columns:last-child {
+ float: left; }
+
+.small-up-7 > .column, .small-up-7 > .columns {
+ width: 14.28571%;
+ float: left; }
+ .small-up-7 > .column:nth-of-type(1n), .small-up-7 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .small-up-7 > .column:nth-of-type(7n+1), .small-up-7 > .columns:nth-of-type(7n+1) {
+ clear: both; }
+ .small-up-7 > .column:last-child, .small-up-7 > .columns:last-child {
+ float: left; }
+
+.small-up-8 > .column, .small-up-8 > .columns {
+ width: 12.5%;
+ float: left; }
+ .small-up-8 > .column:nth-of-type(1n), .small-up-8 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .small-up-8 > .column:nth-of-type(8n+1), .small-up-8 > .columns:nth-of-type(8n+1) {
+ clear: both; }
+ .small-up-8 > .column:last-child, .small-up-8 > .columns:last-child {
+ float: left; }
+
+.small-collapse > .column, .small-collapse > .columns {
+ padding-left: 0;
+ padding-right: 0; }
+
+.small-collapse .row {
+ margin-left: 0;
+ margin-right: 0; }
+
+.expanded.row .small-collapse.row {
+ margin-left: 0;
+ margin-right: 0; }
+
+.small-uncollapse > .column, .small-uncollapse > .columns {
+ padding-left: 0.625rem;
+ padding-right: 0.625rem; }
+
+.small-centered {
+ margin-left: auto;
+ margin-right: auto; }
+ .small-centered, .small-centered:last-child:not(:first-child) {
+ float: none;
+ clear: both; }
+
+.small-uncentered,
+.small-push-0,
+.small-pull-0 {
+ position: static;
+ margin-left: 0;
+ margin-right: 0;
+ float: left; }
+
+@media screen and (min-width: 40em) {
+ .medium-1 {
+ width: 8.33333%; }
+ .medium-push-1 {
+ position: relative;
+ left: 8.33333%; }
+ .medium-pull-1 {
+ position: relative;
+ left: -8.33333%; }
+ .medium-offset-0 {
+ margin-left: 0%; }
+ .medium-2 {
+ width: 16.66667%; }
+ .medium-push-2 {
+ position: relative;
+ left: 16.66667%; }
+ .medium-pull-2 {
+ position: relative;
+ left: -16.66667%; }
+ .medium-offset-1 {
+ margin-left: 8.33333%; }
+ .medium-3 {
+ width: 25%; }
+ .medium-push-3 {
+ position: relative;
+ left: 25%; }
+ .medium-pull-3 {
+ position: relative;
+ left: -25%; }
+ .medium-offset-2 {
+ margin-left: 16.66667%; }
+ .medium-4 {
+ width: 33.33333%; }
+ .medium-push-4 {
+ position: relative;
+ left: 33.33333%; }
+ .medium-pull-4 {
+ position: relative;
+ left: -33.33333%; }
+ .medium-offset-3 {
+ margin-left: 25%; }
+ .medium-5 {
+ width: 41.66667%; }
+ .medium-push-5 {
+ position: relative;
+ left: 41.66667%; }
+ .medium-pull-5 {
+ position: relative;
+ left: -41.66667%; }
+ .medium-offset-4 {
+ margin-left: 33.33333%; }
+ .medium-6 {
+ width: 50%; }
+ .medium-push-6 {
+ position: relative;
+ left: 50%; }
+ .medium-pull-6 {
+ position: relative;
+ left: -50%; }
+ .medium-offset-5 {
+ margin-left: 41.66667%; }
+ .medium-7 {
+ width: 58.33333%; }
+ .medium-push-7 {
+ position: relative;
+ left: 58.33333%; }
+ .medium-pull-7 {
+ position: relative;
+ left: -58.33333%; }
+ .medium-offset-6 {
+ margin-left: 50%; }
+ .medium-8 {
+ width: 66.66667%; }
+ .medium-push-8 {
+ position: relative;
+ left: 66.66667%; }
+ .medium-pull-8 {
+ position: relative;
+ left: -66.66667%; }
+ .medium-offset-7 {
+ margin-left: 58.33333%; }
+ .medium-9 {
+ width: 75%; }
+ .medium-push-9 {
+ position: relative;
+ left: 75%; }
+ .medium-pull-9 {
+ position: relative;
+ left: -75%; }
+ .medium-offset-8 {
+ margin-left: 66.66667%; }
+ .medium-10 {
+ width: 83.33333%; }
+ .medium-push-10 {
+ position: relative;
+ left: 83.33333%; }
+ .medium-pull-10 {
+ position: relative;
+ left: -83.33333%; }
+ .medium-offset-9 {
+ margin-left: 75%; }
+ .medium-11 {
+ width: 91.66667%; }
+ .medium-push-11 {
+ position: relative;
+ left: 91.66667%; }
+ .medium-pull-11 {
+ position: relative;
+ left: -91.66667%; }
+ .medium-offset-10 {
+ margin-left: 83.33333%; }
+ .medium-12 {
+ width: 100%; }
+ .medium-offset-11 {
+ margin-left: 91.66667%; }
+ .medium-up-1 > .column, .medium-up-1 > .columns {
+ width: 100%;
+ float: left; }
+ .medium-up-1 > .column:nth-of-type(1n), .medium-up-1 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .medium-up-1 > .column:nth-of-type(1n+1), .medium-up-1 > .columns:nth-of-type(1n+1) {
+ clear: both; }
+ .medium-up-1 > .column:last-child, .medium-up-1 > .columns:last-child {
+ float: left; }
+ .medium-up-2 > .column, .medium-up-2 > .columns {
+ width: 50%;
+ float: left; }
+ .medium-up-2 > .column:nth-of-type(1n), .medium-up-2 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .medium-up-2 > .column:nth-of-type(2n+1), .medium-up-2 > .columns:nth-of-type(2n+1) {
+ clear: both; }
+ .medium-up-2 > .column:last-child, .medium-up-2 > .columns:last-child {
+ float: left; }
+ .medium-up-3 > .column, .medium-up-3 > .columns {
+ width: 33.33333%;
+ float: left; }
+ .medium-up-3 > .column:nth-of-type(1n), .medium-up-3 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .medium-up-3 > .column:nth-of-type(3n+1), .medium-up-3 > .columns:nth-of-type(3n+1) {
+ clear: both; }
+ .medium-up-3 > .column:last-child, .medium-up-3 > .columns:last-child {
+ float: left; }
+ .medium-up-4 > .column, .medium-up-4 > .columns {
+ width: 25%;
+ float: left; }
+ .medium-up-4 > .column:nth-of-type(1n), .medium-up-4 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .medium-up-4 > .column:nth-of-type(4n+1), .medium-up-4 > .columns:nth-of-type(4n+1) {
+ clear: both; }
+ .medium-up-4 > .column:last-child, .medium-up-4 > .columns:last-child {
+ float: left; }
+ .medium-up-5 > .column, .medium-up-5 > .columns {
+ width: 20%;
+ float: left; }
+ .medium-up-5 > .column:nth-of-type(1n), .medium-up-5 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .medium-up-5 > .column:nth-of-type(5n+1), .medium-up-5 > .columns:nth-of-type(5n+1) {
+ clear: both; }
+ .medium-up-5 > .column:last-child, .medium-up-5 > .columns:last-child {
+ float: left; }
+ .medium-up-6 > .column, .medium-up-6 > .columns {
+ width: 16.66667%;
+ float: left; }
+ .medium-up-6 > .column:nth-of-type(1n), .medium-up-6 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .medium-up-6 > .column:nth-of-type(6n+1), .medium-up-6 > .columns:nth-of-type(6n+1) {
+ clear: both; }
+ .medium-up-6 > .column:last-child, .medium-up-6 > .columns:last-child {
+ float: left; }
+ .medium-up-7 > .column, .medium-up-7 > .columns {
+ width: 14.28571%;
+ float: left; }
+ .medium-up-7 > .column:nth-of-type(1n), .medium-up-7 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .medium-up-7 > .column:nth-of-type(7n+1), .medium-up-7 > .columns:nth-of-type(7n+1) {
+ clear: both; }
+ .medium-up-7 > .column:last-child, .medium-up-7 > .columns:last-child {
+ float: left; }
+ .medium-up-8 > .column, .medium-up-8 > .columns {
+ width: 12.5%;
+ float: left; }
+ .medium-up-8 > .column:nth-of-type(1n), .medium-up-8 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .medium-up-8 > .column:nth-of-type(8n+1), .medium-up-8 > .columns:nth-of-type(8n+1) {
+ clear: both; }
+ .medium-up-8 > .column:last-child, .medium-up-8 > .columns:last-child {
+ float: left; }
+ .medium-collapse > .column, .medium-collapse > .columns {
+ padding-left: 0;
+ padding-right: 0; }
+ .medium-collapse .row {
+ margin-left: 0;
+ margin-right: 0; }
+ .expanded.row .medium-collapse.row {
+ margin-left: 0;
+ margin-right: 0; }
+ .medium-uncollapse > .column, .medium-uncollapse > .columns {
+ padding-left: 0.9375rem;
+ padding-right: 0.9375rem; }
+ .medium-centered {
+ margin-left: auto;
+ margin-right: auto; }
+ .medium-centered, .medium-centered:last-child:not(:first-child) {
+ float: none;
+ clear: both; }
+ .medium-uncentered,
+ .medium-push-0,
+ .medium-pull-0 {
+ position: static;
+ margin-left: 0;
+ margin-right: 0;
+ float: left; } }
+
+@media screen and (min-width: 64em) {
+ .large-1 {
+ width: 8.33333%; }
+ .large-push-1 {
+ position: relative;
+ left: 8.33333%; }
+ .large-pull-1 {
+ position: relative;
+ left: -8.33333%; }
+ .large-offset-0 {
+ margin-left: 0%; }
+ .large-2 {
+ width: 16.66667%; }
+ .large-push-2 {
+ position: relative;
+ left: 16.66667%; }
+ .large-pull-2 {
+ position: relative;
+ left: -16.66667%; }
+ .large-offset-1 {
+ margin-left: 8.33333%; }
+ .large-3 {
+ width: 25%; }
+ .large-push-3 {
+ position: relative;
+ left: 25%; }
+ .large-pull-3 {
+ position: relative;
+ left: -25%; }
+ .large-offset-2 {
+ margin-left: 16.66667%; }
+ .large-4 {
+ width: 33.33333%; }
+ .large-push-4 {
+ position: relative;
+ left: 33.33333%; }
+ .large-pull-4 {
+ position: relative;
+ left: -33.33333%; }
+ .large-offset-3 {
+ margin-left: 25%; }
+ .large-5 {
+ width: 41.66667%; }
+ .large-push-5 {
+ position: relative;
+ left: 41.66667%; }
+ .large-pull-5 {
+ position: relative;
+ left: -41.66667%; }
+ .large-offset-4 {
+ margin-left: 33.33333%; }
+ .large-6 {
+ width: 50%; }
+ .large-push-6 {
+ position: relative;
+ left: 50%; }
+ .large-pull-6 {
+ position: relative;
+ left: -50%; }
+ .large-offset-5 {
+ margin-left: 41.66667%; }
+ .large-7 {
+ width: 58.33333%; }
+ .large-push-7 {
+ position: relative;
+ left: 58.33333%; }
+ .large-pull-7 {
+ position: relative;
+ left: -58.33333%; }
+ .large-offset-6 {
+ margin-left: 50%; }
+ .large-8 {
+ width: 66.66667%; }
+ .large-push-8 {
+ position: relative;
+ left: 66.66667%; }
+ .large-pull-8 {
+ position: relative;
+ left: -66.66667%; }
+ .large-offset-7 {
+ margin-left: 58.33333%; }
+ .large-9 {
+ width: 75%; }
+ .large-push-9 {
+ position: relative;
+ left: 75%; }
+ .large-pull-9 {
+ position: relative;
+ left: -75%; }
+ .large-offset-8 {
+ margin-left: 66.66667%; }
+ .large-10 {
+ width: 83.33333%; }
+ .large-push-10 {
+ position: relative;
+ left: 83.33333%; }
+ .large-pull-10 {
+ position: relative;
+ left: -83.33333%; }
+ .large-offset-9 {
+ margin-left: 75%; }
+ .large-11 {
+ width: 91.66667%; }
+ .large-push-11 {
+ position: relative;
+ left: 91.66667%; }
+ .large-pull-11 {
+ position: relative;
+ left: -91.66667%; }
+ .large-offset-10 {
+ margin-left: 83.33333%; }
+ .large-12 {
+ width: 100%; }
+ .large-offset-11 {
+ margin-left: 91.66667%; }
+ .large-up-1 > .column, .large-up-1 > .columns {
+ width: 100%;
+ float: left; }
+ .large-up-1 > .column:nth-of-type(1n), .large-up-1 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .large-up-1 > .column:nth-of-type(1n+1), .large-up-1 > .columns:nth-of-type(1n+1) {
+ clear: both; }
+ .large-up-1 > .column:last-child, .large-up-1 > .columns:last-child {
+ float: left; }
+ .large-up-2 > .column, .large-up-2 > .columns {
+ width: 50%;
+ float: left; }
+ .large-up-2 > .column:nth-of-type(1n), .large-up-2 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .large-up-2 > .column:nth-of-type(2n+1), .large-up-2 > .columns:nth-of-type(2n+1) {
+ clear: both; }
+ .large-up-2 > .column:last-child, .large-up-2 > .columns:last-child {
+ float: left; }
+ .large-up-3 > .column, .large-up-3 > .columns {
+ width: 33.33333%;
+ float: left; }
+ .large-up-3 > .column:nth-of-type(1n), .large-up-3 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .large-up-3 > .column:nth-of-type(3n+1), .large-up-3 > .columns:nth-of-type(3n+1) {
+ clear: both; }
+ .large-up-3 > .column:last-child, .large-up-3 > .columns:last-child {
+ float: left; }
+ .large-up-4 > .column, .large-up-4 > .columns {
+ width: 25%;
+ float: left; }
+ .large-up-4 > .column:nth-of-type(1n), .large-up-4 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .large-up-4 > .column:nth-of-type(4n+1), .large-up-4 > .columns:nth-of-type(4n+1) {
+ clear: both; }
+ .large-up-4 > .column:last-child, .large-up-4 > .columns:last-child {
+ float: left; }
+ .large-up-5 > .column, .large-up-5 > .columns {
+ width: 20%;
+ float: left; }
+ .large-up-5 > .column:nth-of-type(1n), .large-up-5 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .large-up-5 > .column:nth-of-type(5n+1), .large-up-5 > .columns:nth-of-type(5n+1) {
+ clear: both; }
+ .large-up-5 > .column:last-child, .large-up-5 > .columns:last-child {
+ float: left; }
+ .large-up-6 > .column, .large-up-6 > .columns {
+ width: 16.66667%;
+ float: left; }
+ .large-up-6 > .column:nth-of-type(1n), .large-up-6 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .large-up-6 > .column:nth-of-type(6n+1), .large-up-6 > .columns:nth-of-type(6n+1) {
+ clear: both; }
+ .large-up-6 > .column:last-child, .large-up-6 > .columns:last-child {
+ float: left; }
+ .large-up-7 > .column, .large-up-7 > .columns {
+ width: 14.28571%;
+ float: left; }
+ .large-up-7 > .column:nth-of-type(1n), .large-up-7 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .large-up-7 > .column:nth-of-type(7n+1), .large-up-7 > .columns:nth-of-type(7n+1) {
+ clear: both; }
+ .large-up-7 > .column:last-child, .large-up-7 > .columns:last-child {
+ float: left; }
+ .large-up-8 > .column, .large-up-8 > .columns {
+ width: 12.5%;
+ float: left; }
+ .large-up-8 > .column:nth-of-type(1n), .large-up-8 > .columns:nth-of-type(1n) {
+ clear: none; }
+ .large-up-8 > .column:nth-of-type(8n+1), .large-up-8 > .columns:nth-of-type(8n+1) {
+ clear: both; }
+ .large-up-8 > .column:last-child, .large-up-8 > .columns:last-child {
+ float: left; }
+ .large-collapse > .column, .large-collapse > .columns {
+ padding-left: 0;
+ padding-right: 0; }
+ .large-collapse .row {
+ margin-left: 0;
+ margin-right: 0; }
+ .expanded.row .large-collapse.row {
+ margin-left: 0;
+ margin-right: 0; }
+ .large-uncollapse > .column, .large-uncollapse > .columns {
+ padding-left: 0.9375rem;
+ padding-right: 0.9375rem; }
+ .large-centered {
+ margin-left: auto;
+ margin-right: auto; }
+ .large-centered, .large-centered:last-child:not(:first-child) {
+ float: none;
+ clear: both; }
+ .large-uncentered,
+ .large-push-0,
+ .large-pull-0 {
+ position: static;
+ margin-left: 0;
+ margin-right: 0;
+ float: left; } }
+
+div,
+dl,
+dt,
+dd,
+ul,
+ol,
+li,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+pre,
+form,
+p,
+blockquote,
+th,
+td {
+ margin: 0;
+ padding: 0; }
+
+p {
+ font-size: inherit;
+ line-height: 1.6;
+ margin-bottom: 1rem;
+ text-rendering: optimizeLegibility; }
+
+em,
+i {
+ font-style: italic;
+ line-height: inherit; }
+
+strong,
+b {
+ font-weight: bold;
+ line-height: inherit; }
+
+small {
+ font-size: 80%;
+ line-height: inherit; }
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;
+ font-weight: normal;
+ font-style: normal;
+ color: inherit;
+ text-rendering: optimizeLegibility;
+ margin-top: 0;
+ margin-bottom: 0.5rem;
+ line-height: 1.4; }
+ h1 small,
+ h2 small,
+ h3 small,
+ h4 small,
+ h5 small,
+ h6 small {
+ color: #cacaca;
+ line-height: 0; }
+
+h1 {
+ font-size: 1.5rem; }
+
+h2 {
+ font-size: 1.25rem; }
+
+h3 {
+ font-size: 1.1875rem; }
+
+h4 {
+ font-size: 1.125rem; }
+
+h5 {
+ font-size: 1.0625rem; }
+
+h6 {
+ font-size: 1rem; }
+
+@media screen and (min-width: 40em) {
+ h1 {
+ font-size: 3rem; }
+ h2 {
+ font-size: 2.5rem; }
+ h3 {
+ font-size: 1.9375rem; }
+ h4 {
+ font-size: 1.5625rem; }
+ h5 {
+ font-size: 1.25rem; }
+ h6 {
+ font-size: 1rem; } }
+
+a {
+ color: #2199e8;
+ text-decoration: none;
+ line-height: inherit;
+ cursor: pointer; }
+ a:hover, a:focus {
+ color: #1585cf; }
+ a img {
+ border: 0; }
+
+hr {
+ max-width: 75rem;
+ height: 0;
+ border-right: 0;
+ border-top: 0;
+ border-bottom: 1px solid #cacaca;
+ border-left: 0;
+ margin: 1.25rem auto;
+ clear: both; }
+
+ul,
+ol,
+dl {
+ line-height: 1.6;
+ margin-bottom: 1rem;
+ list-style-position: outside; }
+
+li {
+ font-size: inherit; }
+
+ul {
+ list-style-type: disc;
+ margin-left: 1.25rem; }
+
+ol {
+ margin-left: 1.25rem; }
+
+ul ul, ol ul, ul ol, ol ol {
+ margin-left: 1.25rem;
+ margin-bottom: 0; }
+
+dl {
+ margin-bottom: 1rem; }
+ dl dt {
+ margin-bottom: 0.3rem;
+ font-weight: bold; }
+
+blockquote {
+ margin: 0 0 1rem;
+ padding: 0.5625rem 1.25rem 0 1.1875rem;
+ border-left: 1px solid #cacaca; }
+ blockquote, blockquote p {
+ line-height: 1.6;
+ color: #8a8a8a; }
+
+cite {
+ display: block;
+ font-size: 0.8125rem;
+ color: #8a8a8a; }
+ cite:before {
+ content: '\2014 \0020'; }
+
+abbr {
+ color: #0a0a0a;
+ cursor: help;
+ border-bottom: 1px dotted #0a0a0a; }
+
+code {
+ font-family: Consolas, "Liberation Mono", Courier, monospace;
+ font-weight: normal;
+ color: #0a0a0a;
+ background-color: #e6e6e6;
+ border: 1px solid #cacaca;
+ padding: 0.125rem 0.3125rem 0.0625rem; }
+
+kbd {
+ padding: 0.125rem 0.25rem 0;
+ margin: 0;
+ background-color: #e6e6e6;
+ color: #0a0a0a;
+ font-family: Consolas, "Liberation Mono", Courier, monospace; }
+
+.subheader {
+ margin-top: 0.2rem;
+ margin-bottom: 0.5rem;
+ font-weight: normal;
+ line-height: 1.4;
+ color: #8a8a8a; }
+
+.lead {
+ font-size: 125%;
+ line-height: 1.6; }
+
+.stat {
+ font-size: 2.5rem;
+ line-height: 1; }
+ p + .stat {
+ margin-top: -1rem; }
+
+.no-bullet {
+ margin-left: 0;
+ list-style: none; }
+
+.text-left {
+ text-align: left; }
+
+.text-right {
+ text-align: right; }
+
+.text-center {
+ text-align: center; }
+
+.text-justify {
+ text-align: justify; }
+
+@media screen and (min-width: 40em) {
+ .medium-text-left {
+ text-align: left; }
+ .medium-text-right {
+ text-align: right; }
+ .medium-text-center {
+ text-align: center; }
+ .medium-text-justify {
+ text-align: justify; } }
+
+@media screen and (min-width: 64em) {
+ .large-text-left {
+ text-align: left; }
+ .large-text-right {
+ text-align: right; }
+ .large-text-center {
+ text-align: center; }
+ .large-text-justify {
+ text-align: justify; } }
+
+.show-for-print {
+ display: none !important; }
+
+@media print {
+ * {
+ background: transparent !important;
+ color: black !important;
+ box-shadow: none !important;
+ text-shadow: none !important; }
+ .show-for-print {
+ display: block !important; }
+ .hide-for-print {
+ display: none !important; }
+ table.show-for-print {
+ display: table !important; }
+ thead.show-for-print {
+ display: table-header-group !important; }
+ tbody.show-for-print {
+ display: table-row-group !important; }
+ tr.show-for-print {
+ display: table-row !important; }
+ td.show-for-print {
+ display: table-cell !important; }
+ th.show-for-print {
+ display: table-cell !important; }
+ a,
+ a:visited {
+ text-decoration: underline; }
+ a[href]:after {
+ content: " (" attr(href) ")"; }
+ .ir a:after,
+ a[href^='javascript:']:after,
+ a[href^='#']:after {
+ content: ''; }
+ abbr[title]:after {
+ content: " (" attr(title) ")"; }
+ pre,
+ blockquote {
+ border: 1px solid #8a8a8a;
+ page-break-inside: avoid; }
+ thead {
+ display: table-header-group; }
+ tr,
+ img {
+ page-break-inside: avoid; }
+ img {
+ max-width: 100% !important; }
+ @page {
+ margin: 0.5cm; }
+ p,
+ h2,
+ h3 {
+ orphans: 3;
+ widows: 3; }
+ h2,
+ h3 {
+ page-break-after: avoid; } }
+
+.button {
+ display: inline-block;
+ text-align: center;
+ line-height: 1;
+ cursor: pointer;
+ -webkit-appearance: none;
+ transition: background-color 0.25s ease-out, color 0.25s ease-out;
+ vertical-align: middle;
+ border: 1px solid transparent;
+ border-radius: 0;
+ padding: 0.85em 1em;
+ margin: 0 0 1rem 0;
+ font-size: 0.9rem;
+ background-color: #2199e8;
+ color: #fefefe; }
+ [data-whatinput='mouse'] .button {
+ outline: 0; }
+ .button:hover, .button:focus {
+ background-color: #1583cc;
+ color: #fefefe; }
+ .button.tiny {
+ font-size: 0.6rem; }
+ .button.small {
+ font-size: 0.75rem; }
+ .button.large {
+ font-size: 1.25rem; }
+ .button.expanded {
+ display: block;
+ width: 100%;
+ margin-left: 0;
+ margin-right: 0; }
+ .button.primary {
+ background-color: #2199e8;
+ color: #fefefe; }
+ .button.primary:hover, .button.primary:focus {
+ background-color: #147cc0;
+ color: #fefefe; }
+ .button.secondary {
+ background-color: #777;
+ color: #fefefe; }
+ .button.secondary:hover, .button.secondary:focus {
+ background-color: #5f5f5f;
+ color: #fefefe; }
+ .button.success {
+ background-color: #3adb76;
+ color: #fefefe; }
+ .button.success:hover, .button.success:focus {
+ background-color: #22bb5b;
+ color: #fefefe; }
+ .button.warning {
+ background-color: #ffae00;
+ color: #fefefe; }
+ .button.warning:hover, .button.warning:focus {
+ background-color: #cc8b00;
+ color: #fefefe; }
+ .button.alert {
+ background-color: #ec5840;
+ color: #fefefe; }
+ .button.alert:hover, .button.alert:focus {
+ background-color: #da3116;
+ color: #fefefe; }
+ .button.hollow {
+ border: 1px solid #2199e8;
+ color: #2199e8; }
+ .button.hollow, .button.hollow:hover, .button.hollow:focus {
+ background-color: transparent; }
+ .button.hollow:hover, .button.hollow:focus {
+ border-color: #0c4d78;
+ color: #0c4d78; }
+ .button.hollow.primary {
+ border: 1px solid #2199e8;
+ color: #2199e8; }
+ .button.hollow.primary:hover, .button.hollow.primary:focus {
+ border-color: #0c4d78;
+ color: #0c4d78; }
+ .button.hollow.secondary {
+ border: 1px solid #777;
+ color: #777; }
+ .button.hollow.secondary:hover, .button.hollow.secondary:focus {
+ border-color: #3c3c3c;
+ color: #3c3c3c; }
+ .button.hollow.success {
+ border: 1px solid #3adb76;
+ color: #3adb76; }
+ .button.hollow.success:hover, .button.hollow.success:focus {
+ border-color: #157539;
+ color: #157539; }
+ .button.hollow.warning {
+ border: 1px solid #ffae00;
+ color: #ffae00; }
+ .button.hollow.warning:hover, .button.hollow.warning:focus {
+ border-color: #805700;
+ color: #805700; }
+ .button.hollow.alert {
+ border: 1px solid #ec5840;
+ color: #ec5840; }
+ .button.hollow.alert:hover, .button.hollow.alert:focus {
+ border-color: #881f0e;
+ color: #881f0e; }
+ .button.disabled, .button[disabled] {
+ opacity: 0.25;
+ cursor: not-allowed; }
+ .button.disabled:hover, .button.disabled:focus, .button[disabled]:hover, .button[disabled]:focus {
+ background-color: #2199e8;
+ color: #fefefe; }
+ .button.disabled.primary, .button[disabled].primary {
+ opacity: 0.25;
+ cursor: not-allowed; }
+ .button.disabled.primary:hover, .button.disabled.primary:focus, .button[disabled].primary:hover, .button[disabled].primary:focus {
+ background-color: #2199e8;
+ color: #fefefe; }
+ .button.disabled.secondary, .button[disabled].secondary {
+ opacity: 0.25;
+ cursor: not-allowed; }
+ .button.disabled.secondary:hover, .button.disabled.secondary:focus, .button[disabled].secondary:hover, .button[disabled].secondary:focus {
+ background-color: #777;
+ color: #fefefe; }
+ .button.disabled.success, .button[disabled].success {
+ opacity: 0.25;
+ cursor: not-allowed; }
+ .button.disabled.success:hover, .button.disabled.success:focus, .button[disabled].success:hover, .button[disabled].success:focus {
+ background-color: #3adb76;
+ color: #fefefe; }
+ .button.disabled.warning, .button[disabled].warning {
+ opacity: 0.25;
+ cursor: not-allowed; }
+ .button.disabled.warning:hover, .button.disabled.warning:focus, .button[disabled].warning:hover, .button[disabled].warning:focus {
+ background-color: #ffae00;
+ color: #fefefe; }
+ .button.disabled.alert, .button[disabled].alert {
+ opacity: 0.25;
+ cursor: not-allowed; }
+ .button.disabled.alert:hover, .button.disabled.alert:focus, .button[disabled].alert:hover, .button[disabled].alert:focus {
+ background-color: #ec5840;
+ color: #fefefe; }
+ .button.dropdown::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 0.4em;
+ border-color: #fefefe transparent transparent;
+ border-top-style: solid;
+ border-bottom-width: 0;
+ position: relative;
+ top: 0.4em;
+ float: right;
+ margin-left: 1em;
+ display: inline-block; }
+ .button.arrow-only::after {
+ margin-left: 0;
+ float: none;
+ top: -0.1em; }
+
+[type='text'], [type='password'], [type='date'], [type='datetime'], [type='datetime-local'], [type='month'], [type='week'], [type='email'], [type='number'], [type='search'], [type='tel'], [type='time'], [type='url'], [type='color'],
+textarea {
+ display: block;
+ box-sizing: border-box;
+ width: 100%;
+ height: 2.4375rem;
+ padding: 0.5rem;
+ border: 1px solid #cacaca;
+ margin: 0 0 1rem;
+ font-family: inherit;
+ font-size: 1rem;
+ color: #0a0a0a;
+ background-color: #fefefe;
+ box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1);
+ border-radius: 0;
+ transition: box-shadow 0.5s, border-color 0.25s ease-in-out;
+ -webkit-appearance: none;
+ -moz-appearance: none; }
+ [type='text']:focus, [type='password']:focus, [type='date']:focus, [type='datetime']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='week']:focus, [type='email']:focus, [type='number']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='url']:focus, [type='color']:focus,
+ textarea:focus {
+ border: 1px solid #8a8a8a;
+ background-color: #fefefe;
+ outline: none;
+ box-shadow: 0 0 5px #cacaca;
+ transition: box-shadow 0.5s, border-color 0.25s ease-in-out; }
+
+textarea {
+ max-width: 100%; }
+ textarea[rows] {
+ height: auto; }
+
+input::-webkit-input-placeholder,
+textarea::-webkit-input-placeholder {
+ color: #cacaca; }
+
+input::-moz-placeholder,
+textarea::-moz-placeholder {
+ color: #cacaca; }
+
+input:-ms-input-placeholder,
+textarea:-ms-input-placeholder {
+ color: #cacaca; }
+
+input::placeholder,
+textarea::placeholder {
+ color: #cacaca; }
+
+input:disabled, input[readonly],
+textarea:disabled,
+textarea[readonly] {
+ background-color: #e6e6e6;
+ cursor: not-allowed; }
+
+[type='submit'],
+[type='button'] {
+ border-radius: 0;
+ -webkit-appearance: none;
+ -moz-appearance: none; }
+
+input[type='search'] {
+ box-sizing: border-box; }
+
+[type='file'],
+[type='checkbox'],
+[type='radio'] {
+ margin: 0 0 1rem; }
+
+[type='checkbox'] + label,
+[type='radio'] + label {
+ display: inline-block;
+ margin-left: 0.5rem;
+ margin-right: 1rem;
+ margin-bottom: 0;
+ vertical-align: baseline; }
+ [type='checkbox'] + label[for],
+ [type='radio'] + label[for] {
+ cursor: pointer; }
+
+label > [type='checkbox'],
+label > [type='radio'] {
+ margin-right: 0.5rem; }
+
+[type='file'] {
+ width: 100%; }
+
+label {
+ display: block;
+ margin: 0;
+ font-size: 0.875rem;
+ font-weight: normal;
+ line-height: 1.8;
+ color: #0a0a0a; }
+ label.middle {
+ margin: 0 0 1rem;
+ padding: 0.5625rem 0; }
+
+.help-text {
+ margin-top: -0.5rem;
+ font-size: 0.8125rem;
+ font-style: italic;
+ color: #0a0a0a; }
+
+.input-group {
+ display: table;
+ width: 100%;
+ margin-bottom: 1rem; }
+ .input-group > :first-child {
+ border-radius: 0 0 0 0; }
+ .input-group > :last-child > * {
+ border-radius: 0 0 0 0; }
+
+.input-group-label, .input-group-field, .input-group-button {
+ margin: 0;
+ white-space: nowrap;
+ display: table-cell;
+ vertical-align: middle; }
+
+.input-group-label {
+ text-align: center;
+ padding: 0 1rem;
+ background: #e6e6e6;
+ color: #0a0a0a;
+ border: 1px solid #cacaca;
+ white-space: nowrap;
+ width: 1%;
+ height: 100%; }
+ .input-group-label:first-child {
+ border-right: 0; }
+ .input-group-label:last-child {
+ border-left: 0; }
+
+.input-group-field {
+ border-radius: 0;
+ height: 2.5rem; }
+
+.input-group-button {
+ padding-top: 0;
+ padding-bottom: 0;
+ text-align: center;
+ height: 100%;
+ width: 1%; }
+ .input-group-button a,
+ .input-group-button input,
+ .input-group-button button {
+ margin: 0; }
+
+.input-group .input-group-button {
+ display: table-cell; }
+
+fieldset {
+ border: 0;
+ padding: 0;
+ margin: 0; }
+
+legend {
+ margin-bottom: 0.5rem;
+ max-width: 100%; }
+
+.fieldset {
+ border: 1px solid #cacaca;
+ padding: 1.25rem;
+ margin: 1.125rem 0; }
+ .fieldset legend {
+ background: #fefefe;
+ padding: 0 0.1875rem;
+ margin: 0;
+ margin-left: -0.1875rem; }
+
+select {
+ height: 2.4375rem;
+ padding: 0.5rem;
+ border: 1px solid #cacaca;
+ margin: 0 0 1rem;
+ font-size: 1rem;
+ font-family: inherit;
+ line-height: normal;
+ color: #0a0a0a;
+ background-color: #fefefe;
+ border-radius: 0;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ background-image: url("data:image/svg+xml;utf8, ");
+ background-size: 9px 6px;
+ background-position: right -1rem center;
+ background-origin: content-box;
+ background-repeat: no-repeat;
+ padding-right: 1.5rem; }
+ @media screen and (min-width: 0\0) {
+ select {
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg=="); } }
+ select:disabled {
+ background-color: #e6e6e6;
+ cursor: not-allowed; }
+ select::-ms-expand {
+ display: none; }
+ select[multiple] {
+ height: auto;
+ background-image: none; }
+
+.is-invalid-input:not(:focus) {
+ background-color: rgba(236, 88, 64, 0.1);
+ border-color: #ec5840; }
+
+.is-invalid-label {
+ color: #ec5840; }
+
+.form-error {
+ display: none;
+ margin-top: -0.5rem;
+ margin-bottom: 1rem;
+ font-size: 0.75rem;
+ font-weight: bold;
+ color: #ec5840; }
+ .form-error.is-visible {
+ display: block; }
+
+.accordion {
+ list-style-type: none;
+ background: #fefefe;
+ margin-left: 0; }
+
+.accordion-item:first-child > :first-child {
+ border-radius: 0 0 0 0; }
+
+.accordion-item:last-child > :last-child {
+ border-radius: 0 0 0 0; }
+
+.accordion-title {
+ display: block;
+ padding: 1.25rem 1rem;
+ line-height: 1;
+ font-size: 0.75rem;
+ color: #2199e8;
+ position: relative;
+ border: 1px solid #e6e6e6;
+ border-bottom: 0; }
+ :last-child:not(.is-active) > .accordion-title {
+ border-radius: 0 0 0 0;
+ border-bottom: 1px solid #e6e6e6; }
+ .accordion-title:hover, .accordion-title:focus {
+ background-color: #e6e6e6; }
+ .accordion-title::before {
+ content: '+';
+ position: absolute;
+ right: 1rem;
+ top: 50%;
+ margin-top: -0.5rem; }
+ .is-active > .accordion-title::before {
+ content: '–'; }
+
+.accordion-content {
+ padding: 1rem;
+ display: none;
+ border: 1px solid #e6e6e6;
+ border-bottom: 0;
+ background-color: #fefefe;
+ color: #0a0a0a; }
+ :last-child > .accordion-content:last-child {
+ border-bottom: 1px solid #e6e6e6; }
+
+.is-accordion-submenu-parent > a {
+ position: relative; }
+ .is-accordion-submenu-parent > a::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 6px;
+ border-color: #2199e8 transparent transparent;
+ border-top-style: solid;
+ border-bottom-width: 0;
+ position: absolute;
+ top: 50%;
+ margin-top: -4px;
+ right: 1rem; }
+
+.is-accordion-submenu-parent[aria-expanded='true'] > a::after {
+ -webkit-transform-origin: 50% 50%;
+ -ms-transform-origin: 50% 50%;
+ transform-origin: 50% 50%;
+ -webkit-transform: scaleY(-1);
+ -ms-transform: scaleY(-1);
+ transform: scaleY(-1); }
+
+.badge {
+ display: inline-block;
+ padding: 0.3em;
+ min-width: 2.1em;
+ font-size: 0.6rem;
+ text-align: center;
+ border-radius: 50%;
+ background: #2199e8;
+ color: #fefefe; }
+ .badge.secondary {
+ background: #777;
+ color: #fefefe; }
+ .badge.success {
+ background: #3adb76;
+ color: #fefefe; }
+ .badge.warning {
+ background: #ffae00;
+ color: #fefefe; }
+ .badge.alert {
+ background: #ec5840;
+ color: #fefefe; }
+
+.breadcrumbs {
+ list-style: none;
+ margin: 0 0 1rem 0; }
+ .breadcrumbs::before, .breadcrumbs::after {
+ content: ' ';
+ display: table; }
+ .breadcrumbs::after {
+ clear: both; }
+ .breadcrumbs li {
+ float: left;
+ color: #0a0a0a;
+ font-size: 0.6875rem;
+ cursor: default;
+ text-transform: uppercase; }
+ .breadcrumbs li:not(:last-child)::after {
+ color: #cacaca;
+ content: "/";
+ margin: 0 0.75rem;
+ position: relative;
+ top: 1px;
+ opacity: 1; }
+ .breadcrumbs a {
+ color: #2199e8; }
+ .breadcrumbs a:hover {
+ text-decoration: underline; }
+ .breadcrumbs .disabled {
+ color: #cacaca;
+ cursor: not-allowed; }
+
+.button-group {
+ margin-bottom: 1rem;
+ font-size: 0; }
+ .button-group::before, .button-group::after {
+ content: ' ';
+ display: table; }
+ .button-group::after {
+ clear: both; }
+ .button-group .button {
+ margin: 0;
+ margin-right: 1px;
+ margin-bottom: 1px;
+ font-size: 0.9rem; }
+ .button-group .button:last-child {
+ margin-right: 0; }
+ .button-group.tiny .button {
+ font-size: 0.6rem; }
+ .button-group.small .button {
+ font-size: 0.75rem; }
+ .button-group.large .button {
+ font-size: 1.25rem; }
+ .button-group.expanded {
+ margin-right: -1px; }
+ .button-group.expanded::before, .button-group.expanded::after {
+ display: none; }
+ .button-group.expanded .button:first-child:nth-last-child(2), .button-group.expanded .button:first-child:nth-last-child(2):first-child:nth-last-child(2) ~ .button {
+ display: inline-block;
+ width: calc(50% - 1px);
+ margin-right: 1px; }
+ .button-group.expanded .button:first-child:nth-last-child(2):last-child, .button-group.expanded .button:first-child:nth-last-child(2):first-child:nth-last-child(2) ~ .button:last-child {
+ margin-right: -6px; }
+ .button-group.expanded .button:first-child:nth-last-child(3), .button-group.expanded .button:first-child:nth-last-child(3):first-child:nth-last-child(3) ~ .button {
+ display: inline-block;
+ width: calc(33.33333% - 1px);
+ margin-right: 1px; }
+ .button-group.expanded .button:first-child:nth-last-child(3):last-child, .button-group.expanded .button:first-child:nth-last-child(3):first-child:nth-last-child(3) ~ .button:last-child {
+ margin-right: -6px; }
+ .button-group.expanded .button:first-child:nth-last-child(4), .button-group.expanded .button:first-child:nth-last-child(4):first-child:nth-last-child(4) ~ .button {
+ display: inline-block;
+ width: calc(25% - 1px);
+ margin-right: 1px; }
+ .button-group.expanded .button:first-child:nth-last-child(4):last-child, .button-group.expanded .button:first-child:nth-last-child(4):first-child:nth-last-child(4) ~ .button:last-child {
+ margin-right: -6px; }
+ .button-group.expanded .button:first-child:nth-last-child(5), .button-group.expanded .button:first-child:nth-last-child(5):first-child:nth-last-child(5) ~ .button {
+ display: inline-block;
+ width: calc(20% - 1px);
+ margin-right: 1px; }
+ .button-group.expanded .button:first-child:nth-last-child(5):last-child, .button-group.expanded .button:first-child:nth-last-child(5):first-child:nth-last-child(5) ~ .button:last-child {
+ margin-right: -6px; }
+ .button-group.expanded .button:first-child:nth-last-child(6), .button-group.expanded .button:first-child:nth-last-child(6):first-child:nth-last-child(6) ~ .button {
+ display: inline-block;
+ width: calc(16.66667% - 1px);
+ margin-right: 1px; }
+ .button-group.expanded .button:first-child:nth-last-child(6):last-child, .button-group.expanded .button:first-child:nth-last-child(6):first-child:nth-last-child(6) ~ .button:last-child {
+ margin-right: -6px; }
+ .button-group.primary .button {
+ background-color: #2199e8;
+ color: #fefefe; }
+ .button-group.primary .button:hover, .button-group.primary .button:focus {
+ background-color: #147cc0;
+ color: #fefefe; }
+ .button-group.secondary .button {
+ background-color: #777;
+ color: #fefefe; }
+ .button-group.secondary .button:hover, .button-group.secondary .button:focus {
+ background-color: #5f5f5f;
+ color: #fefefe; }
+ .button-group.success .button {
+ background-color: #3adb76;
+ color: #fefefe; }
+ .button-group.success .button:hover, .button-group.success .button:focus {
+ background-color: #22bb5b;
+ color: #fefefe; }
+ .button-group.warning .button {
+ background-color: #ffae00;
+ color: #fefefe; }
+ .button-group.warning .button:hover, .button-group.warning .button:focus {
+ background-color: #cc8b00;
+ color: #fefefe; }
+ .button-group.alert .button {
+ background-color: #ec5840;
+ color: #fefefe; }
+ .button-group.alert .button:hover, .button-group.alert .button:focus {
+ background-color: #da3116;
+ color: #fefefe; }
+ .button-group.stacked .button, .button-group.stacked-for-small .button, .button-group.stacked-for-medium .button {
+ width: 100%; }
+ .button-group.stacked .button:last-child, .button-group.stacked-for-small .button:last-child, .button-group.stacked-for-medium .button:last-child {
+ margin-bottom: 0; }
+ @media screen and (min-width: 40em) {
+ .button-group.stacked-for-small .button {
+ width: auto;
+ margin-bottom: 0; } }
+ @media screen and (min-width: 64em) {
+ .button-group.stacked-for-medium .button {
+ width: auto;
+ margin-bottom: 0; } }
+ @media screen and (max-width: 39.9375em) {
+ .button-group.stacked-for-small.expanded {
+ display: block; }
+ .button-group.stacked-for-small.expanded .button {
+ display: block;
+ margin-right: 0; } }
+
+.callout {
+ margin: 0 0 1rem 0;
+ padding: 1rem;
+ border: 1px solid rgba(10, 10, 10, 0.25);
+ border-radius: 0;
+ position: relative;
+ color: #0a0a0a;
+ background-color: white; }
+ .callout > :first-child {
+ margin-top: 0; }
+ .callout > :last-child {
+ margin-bottom: 0; }
+ .callout.primary {
+ background-color: #def0fc; }
+ .callout.secondary {
+ background-color: #ebebeb; }
+ .callout.success {
+ background-color: #e1faea; }
+ .callout.warning {
+ background-color: #fff3d9; }
+ .callout.alert {
+ background-color: #fce6e2; }
+ .callout.small {
+ padding-top: 0.5rem;
+ padding-right: 0.5rem;
+ padding-bottom: 0.5rem;
+ padding-left: 0.5rem; }
+ .callout.large {
+ padding-top: 3rem;
+ padding-right: 3rem;
+ padding-bottom: 3rem;
+ padding-left: 3rem; }
+
+.close-button {
+ position: absolute;
+ color: #8a8a8a;
+ right: 1rem;
+ top: 0.5rem;
+ font-size: 2em;
+ line-height: 1;
+ cursor: pointer; }
+ [data-whatinput='mouse'] .close-button {
+ outline: 0; }
+ .close-button:hover, .close-button:focus {
+ color: #0a0a0a; }
+
+.menu {
+ margin: 0;
+ list-style-type: none; }
+ .menu > li {
+ display: table-cell;
+ vertical-align: middle; }
+ [data-whatinput='mouse'] .menu > li {
+ outline: 0; }
+ .menu > li > a {
+ display: block;
+ padding: 0.7rem 1rem;
+ line-height: 1; }
+ .menu input,
+ .menu a,
+ .menu button {
+ margin-bottom: 0; }
+ .menu > li > a img,
+ .menu > li > a i,
+ .menu > li > a svg {
+ vertical-align: middle; }
+ .menu > li > a img + span,
+ .menu > li > a i + span,
+ .menu > li > a svg + span {
+ vertical-align: middle; }
+ .menu > li > a img,
+ .menu > li > a i,
+ .menu > li > a svg {
+ margin-right: 0.25rem;
+ display: inline-block; }
+ .menu > li {
+ display: table-cell; }
+ .menu.vertical > li {
+ display: block; }
+ @media screen and (min-width: 40em) {
+ .menu.medium-horizontal > li {
+ display: table-cell; }
+ .menu.medium-vertical > li {
+ display: block; } }
+ @media screen and (min-width: 64em) {
+ .menu.large-horizontal > li {
+ display: table-cell; }
+ .menu.large-vertical > li {
+ display: block; } }
+ .menu.simple li {
+ line-height: 1;
+ display: inline-block;
+ margin-right: 1rem; }
+ .menu.simple a {
+ padding: 0; }
+ .menu.align-right::before, .menu.align-right::after {
+ content: ' ';
+ display: table; }
+ .menu.align-right::after {
+ clear: both; }
+ .menu.align-right > li {
+ float: right; }
+ .menu.expanded {
+ width: 100%;
+ display: table;
+ table-layout: fixed; }
+ .menu.expanded > li:first-child:last-child {
+ width: 100%; }
+ .menu.icon-top > li > a {
+ text-align: center; }
+ .menu.icon-top > li > a img,
+ .menu.icon-top > li > a i,
+ .menu.icon-top > li > a svg {
+ display: block;
+ margin: 0 auto 0.25rem; }
+ .menu.nested {
+ margin-left: 1rem; }
+ .menu .active > a {
+ color: #fefefe;
+ background: #2199e8; }
+
+.menu-text {
+ font-weight: bold;
+ color: inherit;
+ line-height: 1;
+ padding-top: 0;
+ padding-bottom: 0;
+ padding: 0.7rem 1rem; }
+
+.menu-centered {
+ text-align: center; }
+ .menu-centered > .menu {
+ display: inline-block; }
+
+.no-js [data-responsive-menu] ul {
+ display: none; }
+
+.menu-icon {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+ cursor: pointer;
+ width: 20px;
+ height: 16px; }
+ .menu-icon::after {
+ content: '';
+ position: absolute;
+ display: block;
+ width: 100%;
+ height: 2px;
+ background: #fefefe;
+ top: 0;
+ left: 0;
+ box-shadow: 0 7px 0 #fefefe, 0 14px 0 #fefefe; }
+ .menu-icon:hover::after {
+ background: #cacaca;
+ box-shadow: 0 7px 0 #cacaca, 0 14px 0 #cacaca; }
+
+.menu-icon.dark {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+ cursor: pointer;
+ width: 20px;
+ height: 16px; }
+ .menu-icon.dark::after {
+ content: '';
+ position: absolute;
+ display: block;
+ width: 100%;
+ height: 2px;
+ background: #0a0a0a;
+ top: 0;
+ left: 0;
+ box-shadow: 0 7px 0 #0a0a0a, 0 14px 0 #0a0a0a; }
+ .menu-icon.dark:hover::after {
+ background: #8a8a8a;
+ box-shadow: 0 7px 0 #8a8a8a, 0 14px 0 #8a8a8a; }
+
+.is-drilldown {
+ position: relative;
+ overflow: hidden; }
+ .is-drilldown li {
+ display: block !important; }
+
+.is-drilldown-submenu {
+ position: absolute;
+ top: 0;
+ left: 100%;
+ z-index: -1;
+ width: 100%;
+ background: #fefefe;
+ transition: -webkit-transform 0.15s linear;
+ transition: transform 0.15s linear; }
+ .is-drilldown-submenu.is-active {
+ z-index: 1;
+ display: block;
+ -webkit-transform: translateX(-100%);
+ -ms-transform: translateX(-100%);
+ transform: translateX(-100%); }
+ .is-drilldown-submenu.is-closing {
+ -webkit-transform: translateX(100%);
+ -ms-transform: translateX(100%);
+ transform: translateX(100%); }
+
+.is-drilldown-submenu-parent > a {
+ position: relative; }
+ .is-drilldown-submenu-parent > a::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 6px;
+ border-color: transparent transparent transparent #2199e8;
+ border-left-style: solid;
+ border-right-width: 0;
+ position: absolute;
+ top: 50%;
+ margin-top: -6px;
+ right: 1rem; }
+
+.js-drilldown-back > a::before {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 6px;
+ border-color: transparent #2199e8 transparent transparent;
+ border-right-style: solid;
+ border-left-width: 0;
+ border-left-width: 0;
+ display: inline-block;
+ vertical-align: middle;
+ margin-right: 0.75rem; }
+
+.dropdown-pane {
+ background-color: #fefefe;
+ border: 1px solid #cacaca;
+ border-radius: 0;
+ display: block;
+ font-size: 1rem;
+ padding: 1rem;
+ position: absolute;
+ visibility: hidden;
+ width: 300px;
+ z-index: 10; }
+ .dropdown-pane.is-open {
+ visibility: visible; }
+
+.dropdown-pane.tiny {
+ width: 100px; }
+
+.dropdown-pane.small {
+ width: 200px; }
+
+.dropdown-pane.large {
+ width: 400px; }
+
+.dropdown.menu > li.opens-left > .is-dropdown-submenu {
+ left: auto;
+ right: 0;
+ top: 100%; }
+
+.dropdown.menu > li.opens-right > .is-dropdown-submenu {
+ right: auto;
+ left: 0;
+ top: 100%; }
+
+.dropdown.menu > li.is-dropdown-submenu-parent > a {
+ padding-right: 1.5rem;
+ position: relative; }
+
+.dropdown.menu > li.is-dropdown-submenu-parent > a::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 5px;
+ border-color: #2199e8 transparent transparent;
+ border-top-style: solid;
+ border-bottom-width: 0;
+ right: 5px;
+ margin-top: -2px; }
+
+[data-whatinput='mouse'] .dropdown.menu a {
+ outline: 0; }
+
+.no-js .dropdown.menu ul {
+ display: none; }
+
+.dropdown.menu.vertical > li .is-dropdown-submenu {
+ top: 0; }
+
+.dropdown.menu.vertical > li.opens-left > .is-dropdown-submenu {
+ left: auto;
+ right: 100%; }
+
+.dropdown.menu.vertical > li.opens-right > .is-dropdown-submenu {
+ right: auto;
+ left: 100%; }
+
+.dropdown.menu.vertical > li > a::after {
+ right: 14px;
+ margin-top: -3px; }
+
+.dropdown.menu.vertical > li.opens-left > a::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 5px;
+ border-color: transparent #2199e8 transparent transparent;
+ border-right-style: solid;
+ border-left-width: 0; }
+
+.dropdown.menu.vertical > li.opens-right > a::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 5px;
+ border-color: transparent transparent transparent #2199e8;
+ border-left-style: solid;
+ border-right-width: 0; }
+
+@media screen and (min-width: 40em) {
+ .dropdown.menu.medium-horizontal > li.opens-left > .is-dropdown-submenu {
+ left: auto;
+ right: 0;
+ top: 100%; }
+ .dropdown.menu.medium-horizontal > li.opens-right > .is-dropdown-submenu {
+ right: auto;
+ left: 0;
+ top: 100%; }
+ .dropdown.menu.medium-horizontal > li.is-dropdown-submenu-parent > a {
+ padding-right: 1.5rem;
+ position: relative; }
+ .dropdown.menu.medium-horizontal > li.is-dropdown-submenu-parent > a::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 5px;
+ border-color: #2199e8 transparent transparent;
+ border-top-style: solid;
+ border-bottom-width: 0;
+ right: 5px;
+ margin-top: -2px; }
+ .dropdown.menu.medium-vertical > li .is-dropdown-submenu {
+ top: 0; }
+ .dropdown.menu.medium-vertical > li.opens-left > .is-dropdown-submenu {
+ left: auto;
+ right: 100%; }
+ .dropdown.menu.medium-vertical > li.opens-right > .is-dropdown-submenu {
+ right: auto;
+ left: 100%; }
+ .dropdown.menu.medium-vertical > li > a::after {
+ right: 14px;
+ margin-top: -3px; }
+ .dropdown.menu.medium-vertical > li.opens-left > a::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 5px;
+ border-color: transparent #2199e8 transparent transparent;
+ border-right-style: solid;
+ border-left-width: 0; }
+ .dropdown.menu.medium-vertical > li.opens-right > a::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 5px;
+ border-color: transparent transparent transparent #2199e8;
+ border-left-style: solid;
+ border-right-width: 0; } }
+
+@media screen and (min-width: 64em) {
+ .dropdown.menu.large-horizontal > li.opens-left > .is-dropdown-submenu {
+ left: auto;
+ right: 0;
+ top: 100%; }
+ .dropdown.menu.large-horizontal > li.opens-right > .is-dropdown-submenu {
+ right: auto;
+ left: 0;
+ top: 100%; }
+ .dropdown.menu.large-horizontal > li.is-dropdown-submenu-parent > a {
+ padding-right: 1.5rem;
+ position: relative; }
+ .dropdown.menu.large-horizontal > li.is-dropdown-submenu-parent > a::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 5px;
+ border-color: #2199e8 transparent transparent;
+ border-top-style: solid;
+ border-bottom-width: 0;
+ right: 5px;
+ margin-top: -2px; }
+ .dropdown.menu.large-vertical > li .is-dropdown-submenu {
+ top: 0; }
+ .dropdown.menu.large-vertical > li.opens-left > .is-dropdown-submenu {
+ left: auto;
+ right: 100%; }
+ .dropdown.menu.large-vertical > li.opens-right > .is-dropdown-submenu {
+ right: auto;
+ left: 100%; }
+ .dropdown.menu.large-vertical > li > a::after {
+ right: 14px;
+ margin-top: -3px; }
+ .dropdown.menu.large-vertical > li.opens-left > a::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 5px;
+ border-color: transparent #2199e8 transparent transparent;
+ border-right-style: solid;
+ border-left-width: 0; }
+ .dropdown.menu.large-vertical > li.opens-right > a::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 5px;
+ border-color: transparent transparent transparent #2199e8;
+ border-left-style: solid;
+ border-right-width: 0; } }
+
+.dropdown.menu.align-right .is-dropdown-submenu.first-sub {
+ top: 100%;
+ left: auto;
+ right: 0; }
+
+.is-dropdown-menu.vertical {
+ width: 100px; }
+ .is-dropdown-menu.vertical.align-right {
+ float: right; }
+
+.is-dropdown-submenu-parent {
+ position: relative; }
+ .is-dropdown-submenu-parent a::after {
+ position: absolute;
+ top: 50%;
+ right: 5px;
+ margin-top: -2px; }
+ .is-dropdown-submenu-parent.opens-inner > .is-dropdown-submenu {
+ top: 100%;
+ left: auto; }
+ .is-dropdown-submenu-parent.opens-left > .is-dropdown-submenu {
+ left: auto;
+ right: 100%; }
+ .is-dropdown-submenu-parent.opens-right > .is-dropdown-submenu {
+ right: auto;
+ left: 100%; }
+
+.is-dropdown-submenu {
+ display: none;
+ position: absolute;
+ top: 0;
+ left: 100%;
+ min-width: 200px;
+ z-index: 1;
+ background: #fefefe;
+ border: 1px solid #cacaca; }
+ .is-dropdown-submenu .is-dropdown-submenu-parent > a::after {
+ right: 14px;
+ margin-top: -3px; }
+ .is-dropdown-submenu .is-dropdown-submenu-parent.opens-left > a::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 5px;
+ border-color: transparent #2199e8 transparent transparent;
+ border-right-style: solid;
+ border-left-width: 0; }
+ .is-dropdown-submenu .is-dropdown-submenu-parent.opens-right > a::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 5px;
+ border-color: transparent transparent transparent #2199e8;
+ border-left-style: solid;
+ border-right-width: 0; }
+ .is-dropdown-submenu .is-dropdown-submenu {
+ margin-top: -1px; }
+ .is-dropdown-submenu > li {
+ width: 100%; }
+ .is-dropdown-submenu.js-dropdown-active {
+ display: block; }
+
+.flex-video {
+ position: relative;
+ height: 0;
+ padding-bottom: 75%;
+ margin-bottom: 1rem;
+ overflow: hidden; }
+ .flex-video iframe,
+ .flex-video object,
+ .flex-video embed,
+ .flex-video video {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%; }
+ .flex-video.widescreen {
+ padding-bottom: 56.25%; }
+ .flex-video.vimeo {
+ padding-top: 0; }
+
+.label {
+ display: inline-block;
+ padding: 0.33333rem 0.5rem;
+ font-size: 0.8rem;
+ line-height: 1;
+ white-space: nowrap;
+ cursor: default;
+ border-radius: 0;
+ background: #2199e8;
+ color: #fefefe; }
+ .label.secondary {
+ background: #777;
+ color: #fefefe; }
+ .label.success {
+ background: #3adb76;
+ color: #fefefe; }
+ .label.warning {
+ background: #ffae00;
+ color: #fefefe; }
+ .label.alert {
+ background: #ec5840;
+ color: #fefefe; }
+
+.media-object {
+ margin-bottom: 1rem;
+ display: block; }
+ .media-object img {
+ max-width: none; }
+ @media screen and (max-width: 39.9375em) {
+ .media-object.stack-for-small .media-object-section {
+ padding: 0;
+ padding-bottom: 1rem;
+ display: block; }
+ .media-object.stack-for-small .media-object-section img {
+ width: 100%; } }
+
+.media-object-section {
+ display: table-cell;
+ vertical-align: top; }
+ .media-object-section:first-child {
+ padding-right: 1rem; }
+ .media-object-section:last-child:not(:nth-child(2)) {
+ padding-left: 1rem; }
+ .media-object-section > :last-child {
+ margin-bottom: 0; }
+ .media-object-section.middle {
+ vertical-align: middle; }
+ .media-object-section.bottom {
+ vertical-align: bottom; }
+
+html,
+body {
+ height: 100%; }
+
+.off-canvas-wrapper {
+ width: 100%;
+ overflow-x: hidden;
+ position: relative;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-overflow-scrolling: auto; }
+
+.off-canvas-wrapper-inner {
+ position: relative;
+ width: 100%;
+ min-height: 100%;
+ transition: -webkit-transform 0.5s ease;
+ transition: transform 0.5s ease; }
+ .off-canvas-wrapper-inner::before, .off-canvas-wrapper-inner::after {
+ content: ' ';
+ display: table; }
+ .off-canvas-wrapper-inner::after {
+ clear: both; }
+
+.off-canvas-content,
+.off-canvas-content {
+ min-height: 100%;
+ background: #fefefe;
+ transition: -webkit-transform 0.5s ease;
+ transition: transform 0.5s ease;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ z-index: 1;
+ padding-bottom: 0.1px;
+ box-shadow: 0 0 10px rgba(10, 10, 10, 0.5); }
+
+.js-off-canvas-exit {
+ display: none;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(254, 254, 254, 0.25);
+ cursor: pointer;
+ transition: background 0.5s ease; }
+
+.off-canvas {
+ position: absolute;
+ background: #e6e6e6;
+ z-index: -1;
+ max-height: 100%;
+ overflow-y: auto;
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0); }
+ [data-whatinput='mouse'] .off-canvas {
+ outline: 0; }
+ .off-canvas.position-left {
+ left: -250px;
+ top: 0;
+ width: 250px; }
+ .is-open-left {
+ -webkit-transform: translateX(250px);
+ -ms-transform: translateX(250px);
+ transform: translateX(250px); }
+ .off-canvas.position-right {
+ right: -250px;
+ top: 0;
+ width: 250px; }
+ .is-open-right {
+ -webkit-transform: translateX(-250px);
+ -ms-transform: translateX(-250px);
+ transform: translateX(-250px); }
+
+@media screen and (min-width: 40em) {
+ .position-left.reveal-for-medium {
+ left: 0;
+ z-index: auto;
+ position: fixed; }
+ .position-left.reveal-for-medium ~ .off-canvas-content {
+ margin-left: 250px; }
+ .position-right.reveal-for-medium {
+ right: 0;
+ z-index: auto;
+ position: fixed; }
+ .position-right.reveal-for-medium ~ .off-canvas-content {
+ margin-right: 250px; } }
+
+@media screen and (min-width: 64em) {
+ .position-left.reveal-for-large {
+ left: 0;
+ z-index: auto;
+ position: fixed; }
+ .position-left.reveal-for-large ~ .off-canvas-content {
+ margin-left: 250px; }
+ .position-right.reveal-for-large {
+ right: 0;
+ z-index: auto;
+ position: fixed; }
+ .position-right.reveal-for-large ~ .off-canvas-content {
+ margin-right: 250px; } }
+
+.orbit {
+ position: relative; }
+
+.orbit-container {
+ position: relative;
+ margin: 0;
+ overflow: hidden;
+ list-style: none; }
+
+.orbit-slide {
+ width: 100%;
+ max-height: 100%; }
+ .orbit-slide.no-motionui.is-active {
+ top: 0;
+ left: 0; }
+
+.orbit-figure {
+ margin: 0; }
+
+.orbit-image {
+ margin: 0;
+ width: 100%;
+ max-width: 100%; }
+
+.orbit-caption {
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ padding: 1rem;
+ margin-bottom: 0;
+ color: #fefefe;
+ background-color: rgba(10, 10, 10, 0.5); }
+
+.orbit-previous, .orbit-next {
+ position: absolute;
+ top: 50%;
+ -webkit-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ transform: translateY(-50%);
+ z-index: 10;
+ padding: 1rem;
+ color: #fefefe; }
+ [data-whatinput='mouse'] .orbit-previous, [data-whatinput='mouse'] .orbit-next {
+ outline: 0; }
+ .orbit-previous:hover, .orbit-next:hover, .orbit-previous:active, .orbit-next:active, .orbit-previous:focus, .orbit-next:focus {
+ background-color: rgba(10, 10, 10, 0.5); }
+
+.orbit-previous {
+ left: 0; }
+
+.orbit-next {
+ left: auto;
+ right: 0; }
+
+.orbit-bullets {
+ position: relative;
+ margin-top: 0.8rem;
+ margin-bottom: 0.8rem;
+ text-align: center; }
+ [data-whatinput='mouse'] .orbit-bullets {
+ outline: 0; }
+ .orbit-bullets button {
+ width: 1.2rem;
+ height: 1.2rem;
+ margin: 0.1rem;
+ background-color: #cacaca;
+ border-radius: 50%; }
+ .orbit-bullets button:hover {
+ background-color: #8a8a8a; }
+ .orbit-bullets button.is-active {
+ background-color: #8a8a8a; }
+
+.pagination {
+ margin-left: 0;
+ margin-bottom: 1rem; }
+ .pagination::before, .pagination::after {
+ content: ' ';
+ display: table; }
+ .pagination::after {
+ clear: both; }
+ .pagination li {
+ font-size: 0.875rem;
+ margin-right: 0.0625rem;
+ border-radius: 0;
+ display: none; }
+ .pagination li:last-child, .pagination li:first-child {
+ display: inline-block; }
+ @media screen and (min-width: 40em) {
+ .pagination li {
+ display: inline-block; } }
+ .pagination a,
+ .pagination button {
+ color: #0a0a0a;
+ display: block;
+ padding: 0.1875rem 0.625rem;
+ border-radius: 0; }
+ .pagination a:hover,
+ .pagination button:hover {
+ background: #e6e6e6; }
+ .pagination .current {
+ padding: 0.1875rem 0.625rem;
+ background: #2199e8;
+ color: #fefefe;
+ cursor: default; }
+ .pagination .disabled {
+ padding: 0.1875rem 0.625rem;
+ color: #cacaca;
+ cursor: not-allowed; }
+ .pagination .disabled:hover {
+ background: transparent; }
+ .pagination .ellipsis::after {
+ content: '\2026';
+ padding: 0.1875rem 0.625rem;
+ color: #0a0a0a; }
+
+.pagination-previous a::before,
+.pagination-previous.disabled::before {
+ content: '\00ab';
+ display: inline-block;
+ margin-right: 0.5rem; }
+
+.pagination-next a::after,
+.pagination-next.disabled::after {
+ content: '\00bb';
+ display: inline-block;
+ margin-left: 0.5rem; }
+
+.progress {
+ background-color: #cacaca;
+ height: 1rem;
+ margin-bottom: 1rem;
+ border-radius: 0; }
+ .progress.primary .progress-meter {
+ background-color: #2199e8; }
+ .progress.secondary .progress-meter {
+ background-color: #777; }
+ .progress.success .progress-meter {
+ background-color: #3adb76; }
+ .progress.warning .progress-meter {
+ background-color: #ffae00; }
+ .progress.alert .progress-meter {
+ background-color: #ec5840; }
+
+.progress-meter {
+ position: relative;
+ display: block;
+ width: 0%;
+ height: 100%;
+ background-color: #2199e8; }
+
+.progress-meter-text {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ -webkit-transform: translate(-50%, -50%);
+ -ms-transform: translate(-50%, -50%);
+ transform: translate(-50%, -50%);
+ position: absolute;
+ margin: 0;
+ font-size: 0.75rem;
+ font-weight: bold;
+ color: #fefefe;
+ white-space: nowrap; }
+
+body.is-reveal-open {
+ overflow: hidden; }
+
+html.is-reveal-open,
+html.is-reveal-open body {
+ min-height: 100%;
+ overflow: hidden;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none; }
+
+.reveal-overlay {
+ display: none;
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ z-index: 1005;
+ background-color: rgba(10, 10, 10, 0.45);
+ overflow-y: scroll; }
+
+.reveal {
+ display: none;
+ z-index: 1006;
+ padding: 1rem;
+ border: 1px solid #cacaca;
+ background-color: #fefefe;
+ border-radius: 0;
+ position: relative;
+ top: 100px;
+ margin-left: auto;
+ margin-right: auto;
+ overflow-y: auto; }
+ [data-whatinput='mouse'] .reveal {
+ outline: 0; }
+ @media screen and (min-width: 40em) {
+ .reveal {
+ min-height: 0; } }
+ .reveal .column, .reveal .columns,
+ .reveal .columns {
+ min-width: 0; }
+ .reveal > :last-child {
+ margin-bottom: 0; }
+ @media screen and (min-width: 40em) {
+ .reveal {
+ width: 600px;
+ max-width: 75rem; } }
+ @media screen and (min-width: 40em) {
+ .reveal .reveal {
+ left: auto;
+ right: auto;
+ margin: 0 auto; } }
+ .reveal.collapse {
+ padding: 0; }
+ @media screen and (min-width: 40em) {
+ .reveal.tiny {
+ width: 30%;
+ max-width: 75rem; } }
+ @media screen and (min-width: 40em) {
+ .reveal.small {
+ width: 50%;
+ max-width: 75rem; } }
+ @media screen and (min-width: 40em) {
+ .reveal.large {
+ width: 90%;
+ max-width: 75rem; } }
+ .reveal.full {
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ height: 100vh;
+ min-height: 100vh;
+ max-width: none;
+ margin-left: 0;
+ border: 0;
+ border-radius: 0; }
+ @media screen and (max-width: 39.9375em) {
+ .reveal {
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ height: 100vh;
+ min-height: 100vh;
+ max-width: none;
+ margin-left: 0;
+ border: 0;
+ border-radius: 0; } }
+ .reveal.without-overlay {
+ position: fixed; }
+
+.slider {
+ position: relative;
+ height: 0.5rem;
+ margin-top: 1.25rem;
+ margin-bottom: 2.25rem;
+ background-color: #e6e6e6;
+ cursor: pointer;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -ms-touch-action: none;
+ touch-action: none; }
+
+.slider-fill {
+ position: absolute;
+ top: 0;
+ left: 0;
+ display: inline-block;
+ max-width: 100%;
+ height: 0.5rem;
+ background-color: #cacaca;
+ transition: all 0.2s ease-in-out; }
+ .slider-fill.is-dragging {
+ transition: all 0s linear; }
+
+.slider-handle {
+ position: absolute;
+ top: 50%;
+ -webkit-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ transform: translateY(-50%);
+ position: absolute;
+ left: 0;
+ z-index: 1;
+ display: inline-block;
+ width: 1.4rem;
+ height: 1.4rem;
+ background-color: #2199e8;
+ transition: all 0.2s ease-in-out;
+ -ms-touch-action: manipulation;
+ touch-action: manipulation;
+ border-radius: 0; }
+ [data-whatinput='mouse'] .slider-handle {
+ outline: 0; }
+ .slider-handle:hover {
+ background-color: #1583cc; }
+ .slider-handle.is-dragging {
+ transition: all 0s linear; }
+
+.slider.disabled,
+.slider[disabled] {
+ opacity: 0.25;
+ cursor: not-allowed; }
+
+.slider.vertical {
+ display: inline-block;
+ width: 0.5rem;
+ height: 12.5rem;
+ margin: 0 1.25rem;
+ -webkit-transform: scale(1, -1);
+ -ms-transform: scale(1, -1);
+ transform: scale(1, -1); }
+ .slider.vertical .slider-fill {
+ top: 0;
+ width: 0.5rem;
+ max-height: 100%; }
+ .slider.vertical .slider-handle {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ width: 1.4rem;
+ height: 1.4rem;
+ -webkit-transform: translateX(-50%);
+ -ms-transform: translateX(-50%);
+ transform: translateX(-50%); }
+
+.sticky-container {
+ position: relative; }
+
+.sticky {
+ position: absolute;
+ z-index: 0;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0); }
+
+.sticky.is-stuck {
+ position: fixed;
+ z-index: 5; }
+ .sticky.is-stuck.is-at-top {
+ top: 0; }
+ .sticky.is-stuck.is-at-bottom {
+ bottom: 0; }
+
+.sticky.is-anchored {
+ position: absolute;
+ left: auto;
+ right: auto; }
+ .sticky.is-anchored.is-at-bottom {
+ bottom: 0; }
+
+.switch {
+ height: 2rem;
+ margin-bottom: 1rem;
+ outline: 0;
+ position: relative;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ color: #fefefe;
+ font-weight: bold;
+ font-size: 0.875rem; }
+
+.switch-input {
+ opacity: 0;
+ position: absolute;
+ margin-bottom: 0; }
+
+.switch-paddle {
+ background: #cacaca;
+ cursor: pointer;
+ display: block;
+ position: relative;
+ width: 4rem;
+ height: 2rem;
+ transition: all 0.25s ease-out;
+ border-radius: 0;
+ color: inherit;
+ font-weight: inherit; }
+ input + .switch-paddle {
+ margin: 0; }
+ .switch-paddle::after {
+ background: #fefefe;
+ content: '';
+ display: block;
+ position: absolute;
+ height: 1.5rem;
+ left: 0.25rem;
+ top: 0.25rem;
+ width: 1.5rem;
+ transition: all 0.25s ease-out;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ border-radius: 0; }
+ input:checked ~ .switch-paddle {
+ background: #2199e8; }
+ input:checked ~ .switch-paddle::after {
+ left: 2.25rem; }
+ [data-whatinput='mouse'] input:focus ~ .switch-paddle {
+ outline: 0; }
+
+.switch-active, .switch-inactive {
+ position: absolute;
+ top: 50%;
+ -webkit-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ transform: translateY(-50%); }
+
+.switch-active {
+ left: 8%;
+ display: none; }
+ input:checked + label > .switch-active {
+ display: block; }
+
+.switch-inactive {
+ right: 15%; }
+ input:checked + label > .switch-inactive {
+ display: none; }
+
+.switch.tiny {
+ height: 1.5rem; }
+ .switch.tiny .switch-paddle {
+ width: 3rem;
+ height: 1.5rem;
+ font-size: 0.625rem; }
+ .switch.tiny .switch-paddle::after {
+ width: 1rem;
+ height: 1rem; }
+ .switch.tiny input:checked ~ .switch-paddle::after {
+ left: 1.75rem; }
+
+.switch.small {
+ height: 1.75rem; }
+ .switch.small .switch-paddle {
+ width: 3.5rem;
+ height: 1.75rem;
+ font-size: 0.75rem; }
+ .switch.small .switch-paddle::after {
+ width: 1.25rem;
+ height: 1.25rem; }
+ .switch.small input:checked ~ .switch-paddle::after {
+ left: 2rem; }
+
+.switch.large {
+ height: 2.5rem; }
+ .switch.large .switch-paddle {
+ width: 5rem;
+ height: 2.5rem;
+ font-size: 1rem; }
+ .switch.large .switch-paddle::after {
+ width: 2rem;
+ height: 2rem; }
+ .switch.large input:checked ~ .switch-paddle::after {
+ left: 2.75rem; }
+
+table {
+ width: 100%;
+ margin-bottom: 1rem;
+ border-radius: 0; }
+ table thead,
+ table tbody,
+ table tfoot {
+ border: 1px solid #f1f1f1;
+ background-color: #fefefe; }
+ table caption {
+ font-weight: bold;
+ padding: 0.5rem 0.625rem 0.625rem; }
+ table thead {
+ background: #f8f8f8;
+ color: #0a0a0a; }
+ table tfoot {
+ background: #f1f1f1;
+ color: #0a0a0a; }
+ table thead tr,
+ table tfoot tr {
+ background: transparent; }
+ table thead th,
+ table thead td,
+ table tfoot th,
+ table tfoot td {
+ padding: 0.5rem 0.625rem 0.625rem;
+ font-weight: bold;
+ text-align: left; }
+ table tbody tr:nth-child(even) {
+ background-color: #f1f1f1; }
+ table tbody th,
+ table tbody td {
+ padding: 0.5rem 0.625rem 0.625rem; }
+
+@media screen and (max-width: 63.9375em) {
+ table.stack thead {
+ display: none; }
+ table.stack tfoot {
+ display: none; }
+ table.stack tr,
+ table.stack th,
+ table.stack td {
+ display: block; }
+ table.stack td {
+ border-top: 0; } }
+
+table.scroll {
+ display: block;
+ width: 100%;
+ overflow-x: auto; }
+
+table.hover thead tr:hover {
+ background-color: #f3f3f3; }
+
+table.hover tfoot tr:hover {
+ background-color: #ececec; }
+
+table.hover tbody tr:hover {
+ background-color: #f9f9f9; }
+
+table.hover tbody tr:nth-of-type(even):hover {
+ background-color: #ececec; }
+
+.table-scroll {
+ overflow-x: auto; }
+ .table-scroll table {
+ width: auto; }
+
+.tabs {
+ margin: 0;
+ list-style-type: none;
+ background: #fefefe;
+ border: 1px solid #e6e6e6; }
+ .tabs::before, .tabs::after {
+ content: ' ';
+ display: table; }
+ .tabs::after {
+ clear: both; }
+
+.tabs.vertical > li {
+ width: auto;
+ float: none;
+ display: block; }
+
+.tabs.simple > li > a {
+ padding: 0; }
+ .tabs.simple > li > a:hover {
+ background: transparent; }
+
+.tabs.primary {
+ background: #2199e8; }
+ .tabs.primary > li > a {
+ color: #fefefe; }
+ .tabs.primary > li > a:hover, .tabs.primary > li > a:focus {
+ background: #1893e4; }
+
+.tabs-title {
+ float: left; }
+ .tabs-title > a {
+ display: block;
+ padding: 1.25rem 1.5rem;
+ line-height: 1;
+ font-size: 0.75rem; }
+ .tabs-title > a:hover {
+ background: #fefefe; }
+ .tabs-title > a:focus, .tabs-title > a[aria-selected='true'] {
+ background: #e6e6e6; }
+
+.tabs-content {
+ background: #fefefe;
+ transition: all 0.5s ease;
+ border: 1px solid #e6e6e6;
+ border-top: 0; }
+
+.tabs-content.vertical {
+ border: 1px solid #e6e6e6;
+ border-left: 0; }
+
+.tabs-panel {
+ display: none;
+ padding: 1rem; }
+ .tabs-panel.is-active {
+ display: block; }
+
+.thumbnail {
+ border: solid 4px #fefefe;
+ box-shadow: 0 0 0 1px rgba(10, 10, 10, 0.2);
+ display: inline-block;
+ line-height: 0;
+ max-width: 100%;
+ transition: box-shadow 200ms ease-out;
+ border-radius: 0;
+ margin-bottom: 1rem; }
+ .thumbnail:hover, .thumbnail:focus {
+ box-shadow: 0 0 6px 1px rgba(33, 153, 232, 0.5); }
+
+.title-bar {
+ background: #0a0a0a;
+ color: #fefefe;
+ padding: 0.5rem; }
+ .title-bar::before, .title-bar::after {
+ content: ' ';
+ display: table; }
+ .title-bar::after {
+ clear: both; }
+ .title-bar .menu-icon {
+ margin-left: 0.25rem;
+ margin-right: 0.25rem; }
+
+.title-bar-left {
+ float: left; }
+
+.title-bar-right {
+ float: right;
+ text-align: right; }
+
+.title-bar-title {
+ font-weight: bold;
+ vertical-align: middle;
+ display: inline-block; }
+
+.has-tip {
+ border-bottom: dotted 1px #8a8a8a;
+ font-weight: bold;
+ position: relative;
+ display: inline-block;
+ cursor: help; }
+
+.tooltip {
+ background-color: #0a0a0a;
+ color: #fefefe;
+ font-size: 80%;
+ padding: 0.75rem;
+ position: absolute;
+ z-index: 10;
+ top: calc(100% + 0.6495rem);
+ max-width: 10rem !important;
+ border-radius: 0; }
+ .tooltip::before {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 0.75rem;
+ border-color: transparent transparent #0a0a0a;
+ border-bottom-style: solid;
+ border-top-width: 0;
+ bottom: 100%;
+ position: absolute;
+ left: 50%;
+ -webkit-transform: translateX(-50%);
+ -ms-transform: translateX(-50%);
+ transform: translateX(-50%); }
+ .tooltip.top::before {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 0.75rem;
+ border-color: #0a0a0a transparent transparent;
+ border-top-style: solid;
+ border-bottom-width: 0;
+ top: 100%;
+ bottom: auto; }
+ .tooltip.left::before {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 0.75rem;
+ border-color: transparent transparent transparent #0a0a0a;
+ border-left-style: solid;
+ border-right-width: 0;
+ bottom: auto;
+ left: 100%;
+ top: 50%;
+ -webkit-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ transform: translateY(-50%); }
+ .tooltip.right::before {
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ border: inset 0.75rem;
+ border-color: transparent #0a0a0a transparent transparent;
+ border-right-style: solid;
+ border-left-width: 0;
+ bottom: auto;
+ left: auto;
+ right: 100%;
+ top: 50%;
+ -webkit-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ transform: translateY(-50%); }
+
+.top-bar {
+ padding: 0.5rem; }
+ .top-bar::before, .top-bar::after {
+ content: ' ';
+ display: table; }
+ .top-bar::after {
+ clear: both; }
+ .top-bar,
+ .top-bar ul {
+ background-color: #e6e6e6; }
+ .top-bar input {
+ max-width: 200px;
+ margin-right: 1rem; }
+ .top-bar .input-group-field {
+ width: 100%;
+ margin-right: 0; }
+ .top-bar input.button {
+ width: auto; }
+ .top-bar .top-bar-left,
+ .top-bar .top-bar-right {
+ width: 100%; }
+ @media screen and (min-width: 40em) {
+ .top-bar .top-bar-left,
+ .top-bar .top-bar-right {
+ width: auto; } }
+ @media screen and (max-width: 63.9375em) {
+ .top-bar.stacked-for-medium .top-bar-left,
+ .top-bar.stacked-for-medium .top-bar-right {
+ width: 100%; } }
+ @media screen and (max-width: 74.9375em) {
+ .top-bar.stacked-for-large .top-bar-left,
+ .top-bar.stacked-for-large .top-bar-right {
+ width: 100%; } }
+
+.top-bar-title {
+ float: left;
+ margin-right: 1rem; }
+
+.top-bar-left {
+ float: left; }
+
+.top-bar-right {
+ float: right; }
+
+.hide {
+ display: none !important; }
+
+.invisible {
+ visibility: hidden; }
+
+@media screen and (max-width: 39.9375em) {
+ .hide-for-small-only {
+ display: none !important; } }
+
+@media screen and (max-width: 0em), screen and (min-width: 40em) {
+ .show-for-small-only {
+ display: none !important; } }
+
+@media screen and (min-width: 40em) {
+ .hide-for-medium {
+ display: none !important; } }
+
+@media screen and (max-width: 39.9375em) {
+ .show-for-medium {
+ display: none !important; } }
+
+@media screen and (min-width: 40em) and (max-width: 63.9375em) {
+ .hide-for-medium-only {
+ display: none !important; } }
+
+@media screen and (max-width: 39.9375em), screen and (min-width: 64em) {
+ .show-for-medium-only {
+ display: none !important; } }
+
+@media screen and (min-width: 64em) {
+ .hide-for-large {
+ display: none !important; } }
+
+@media screen and (max-width: 63.9375em) {
+ .show-for-large {
+ display: none !important; } }
+
+@media screen and (min-width: 64em) and (max-width: 74.9375em) {
+ .hide-for-large-only {
+ display: none !important; } }
+
+@media screen and (max-width: 63.9375em), screen and (min-width: 75em) {
+ .show-for-large-only {
+ display: none !important; } }
+
+.show-for-sr,
+.show-on-focus {
+ position: absolute !important;
+ width: 1px;
+ height: 1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0); }
+
+.show-on-focus:active, .show-on-focus:focus {
+ position: static !important;
+ height: auto;
+ width: auto;
+ overflow: visible;
+ clip: auto; }
+
+.show-for-landscape,
+.hide-for-portrait {
+ display: block !important; }
+ @media screen and (orientation: landscape) {
+ .show-for-landscape,
+ .hide-for-portrait {
+ display: block !important; } }
+ @media screen and (orientation: portrait) {
+ .show-for-landscape,
+ .hide-for-portrait {
+ display: none !important; } }
+
+.hide-for-landscape,
+.show-for-portrait {
+ display: none !important; }
+ @media screen and (orientation: landscape) {
+ .hide-for-landscape,
+ .show-for-portrait {
+ display: none !important; } }
+ @media screen and (orientation: portrait) {
+ .hide-for-landscape,
+ .show-for-portrait {
+ display: block !important; } }
+
+.float-left {
+ float: left !important; }
+
+.float-right {
+ float: right !important; }
+
+.float-center {
+ display: block;
+ margin-left: auto;
+ margin-right: auto; }
+
+.clearfix::before, .clearfix::after {
+ content: ' ';
+ display: table; }
+
+.clearfix::after {
+ clear: both; }
+
+.slide-in-down.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: translateY(-100%);
+ -ms-transform: translateY(-100%);
+ transform: translateY(-100%);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden; }
+
+.slide-in-down.mui-enter.mui-enter-active {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0); }
+
+.slide-in-left.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: translateX(-100%);
+ -ms-transform: translateX(-100%);
+ transform: translateX(-100%);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden; }
+
+.slide-in-left.mui-enter.mui-enter-active {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0); }
+
+.slide-in-up.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: translateY(100%);
+ -ms-transform: translateY(100%);
+ transform: translateY(100%);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden; }
+
+.slide-in-up.mui-enter.mui-enter-active {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0); }
+
+.slide-in-right.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: translateX(100%);
+ -ms-transform: translateX(100%);
+ transform: translateX(100%);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden; }
+
+.slide-in-right.mui-enter.mui-enter-active {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0); }
+
+.slide-out-down.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden; }
+
+.slide-out-down.mui-leave.mui-leave-active {
+ -webkit-transform: translateY(100%);
+ -ms-transform: translateY(100%);
+ transform: translateY(100%); }
+
+.slide-out-right.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden; }
+
+.slide-out-right.mui-leave.mui-leave-active {
+ -webkit-transform: translateX(100%);
+ -ms-transform: translateX(100%);
+ transform: translateX(100%); }
+
+.slide-out-up.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden; }
+
+.slide-out-up.mui-leave.mui-leave-active {
+ -webkit-transform: translateY(-100%);
+ -ms-transform: translateY(-100%);
+ transform: translateY(-100%); }
+
+.slide-out-left.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden; }
+
+.slide-out-left.mui-leave.mui-leave-active {
+ -webkit-transform: translateX(-100%);
+ -ms-transform: translateX(-100%);
+ transform: translateX(-100%); }
+
+.fade-in.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ opacity: 0;
+ transition-property: opacity; }
+
+.fade-in.mui-enter.mui-enter-active {
+ opacity: 1; }
+
+.fade-out.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ opacity: 1;
+ transition-property: opacity; }
+
+.fade-out.mui-leave.mui-leave-active {
+ opacity: 0; }
+
+.hinge-in-from-top.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: perspective(2000px) rotateX(-90deg);
+ transform: perspective(2000px) rotateX(-90deg);
+ -webkit-transform-origin: top;
+ -ms-transform-origin: top;
+ transform-origin: top;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 0; }
+
+.hinge-in-from-top.mui-enter.mui-enter-active {
+ -webkit-transform: perspective(2000px) rotate(0deg);
+ transform: perspective(2000px) rotate(0deg);
+ opacity: 1; }
+
+.hinge-in-from-right.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: perspective(2000px) rotateY(-90deg);
+ transform: perspective(2000px) rotateY(-90deg);
+ -webkit-transform-origin: right;
+ -ms-transform-origin: right;
+ transform-origin: right;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 0; }
+
+.hinge-in-from-right.mui-enter.mui-enter-active {
+ -webkit-transform: perspective(2000px) rotate(0deg);
+ transform: perspective(2000px) rotate(0deg);
+ opacity: 1; }
+
+.hinge-in-from-bottom.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: perspective(2000px) rotateX(90deg);
+ transform: perspective(2000px) rotateX(90deg);
+ -webkit-transform-origin: bottom;
+ -ms-transform-origin: bottom;
+ transform-origin: bottom;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 0; }
+
+.hinge-in-from-bottom.mui-enter.mui-enter-active {
+ -webkit-transform: perspective(2000px) rotate(0deg);
+ transform: perspective(2000px) rotate(0deg);
+ opacity: 1; }
+
+.hinge-in-from-left.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: perspective(2000px) rotateY(90deg);
+ transform: perspective(2000px) rotateY(90deg);
+ -webkit-transform-origin: left;
+ -ms-transform-origin: left;
+ transform-origin: left;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 0; }
+
+.hinge-in-from-left.mui-enter.mui-enter-active {
+ -webkit-transform: perspective(2000px) rotate(0deg);
+ transform: perspective(2000px) rotate(0deg);
+ opacity: 1; }
+
+.hinge-in-from-middle-x.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: perspective(2000px) rotateX(-90deg);
+ transform: perspective(2000px) rotateX(-90deg);
+ -webkit-transform-origin: center;
+ -ms-transform-origin: center;
+ transform-origin: center;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 0; }
+
+.hinge-in-from-middle-x.mui-enter.mui-enter-active {
+ -webkit-transform: perspective(2000px) rotate(0deg);
+ transform: perspective(2000px) rotate(0deg);
+ opacity: 1; }
+
+.hinge-in-from-middle-y.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: perspective(2000px) rotateY(-90deg);
+ transform: perspective(2000px) rotateY(-90deg);
+ -webkit-transform-origin: center;
+ -ms-transform-origin: center;
+ transform-origin: center;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 0; }
+
+.hinge-in-from-middle-y.mui-enter.mui-enter-active {
+ -webkit-transform: perspective(2000px) rotate(0deg);
+ transform: perspective(2000px) rotate(0deg);
+ opacity: 1; }
+
+.hinge-out-from-top.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: perspective(2000px) rotate(0deg);
+ transform: perspective(2000px) rotate(0deg);
+ -webkit-transform-origin: top;
+ -ms-transform-origin: top;
+ transform-origin: top;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 1; }
+
+.hinge-out-from-top.mui-leave.mui-leave-active {
+ -webkit-transform: perspective(2000px) rotateX(-90deg);
+ transform: perspective(2000px) rotateX(-90deg);
+ opacity: 0; }
+
+.hinge-out-from-right.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: perspective(2000px) rotate(0deg);
+ transform: perspective(2000px) rotate(0deg);
+ -webkit-transform-origin: right;
+ -ms-transform-origin: right;
+ transform-origin: right;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 1; }
+
+.hinge-out-from-right.mui-leave.mui-leave-active {
+ -webkit-transform: perspective(2000px) rotateY(-90deg);
+ transform: perspective(2000px) rotateY(-90deg);
+ opacity: 0; }
+
+.hinge-out-from-bottom.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: perspective(2000px) rotate(0deg);
+ transform: perspective(2000px) rotate(0deg);
+ -webkit-transform-origin: bottom;
+ -ms-transform-origin: bottom;
+ transform-origin: bottom;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 1; }
+
+.hinge-out-from-bottom.mui-leave.mui-leave-active {
+ -webkit-transform: perspective(2000px) rotateX(90deg);
+ transform: perspective(2000px) rotateX(90deg);
+ opacity: 0; }
+
+.hinge-out-from-left.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: perspective(2000px) rotate(0deg);
+ transform: perspective(2000px) rotate(0deg);
+ -webkit-transform-origin: left;
+ -ms-transform-origin: left;
+ transform-origin: left;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 1; }
+
+.hinge-out-from-left.mui-leave.mui-leave-active {
+ -webkit-transform: perspective(2000px) rotateY(90deg);
+ transform: perspective(2000px) rotateY(90deg);
+ opacity: 0; }
+
+.hinge-out-from-middle-x.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: perspective(2000px) rotate(0deg);
+ transform: perspective(2000px) rotate(0deg);
+ -webkit-transform-origin: center;
+ -ms-transform-origin: center;
+ transform-origin: center;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 1; }
+
+.hinge-out-from-middle-x.mui-leave.mui-leave-active {
+ -webkit-transform: perspective(2000px) rotateX(-90deg);
+ transform: perspective(2000px) rotateX(-90deg);
+ opacity: 0; }
+
+.hinge-out-from-middle-y.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: perspective(2000px) rotate(0deg);
+ transform: perspective(2000px) rotate(0deg);
+ -webkit-transform-origin: center;
+ -ms-transform-origin: center;
+ transform-origin: center;
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 1; }
+
+.hinge-out-from-middle-y.mui-leave.mui-leave-active {
+ -webkit-transform: perspective(2000px) rotateY(-90deg);
+ transform: perspective(2000px) rotateY(-90deg);
+ opacity: 0; }
+
+.scale-in-up.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: scale(0.5);
+ -ms-transform: scale(0.5);
+ transform: scale(0.5);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 0; }
+
+.scale-in-up.mui-enter.mui-enter-active {
+ -webkit-transform: scale(1);
+ -ms-transform: scale(1);
+ transform: scale(1);
+ opacity: 1; }
+
+.scale-in-down.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: scale(1.5);
+ -ms-transform: scale(1.5);
+ transform: scale(1.5);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 0; }
+
+.scale-in-down.mui-enter.mui-enter-active {
+ -webkit-transform: scale(1);
+ -ms-transform: scale(1);
+ transform: scale(1);
+ opacity: 1; }
+
+.scale-out-up.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: scale(1);
+ -ms-transform: scale(1);
+ transform: scale(1);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 1; }
+
+.scale-out-up.mui-leave.mui-leave-active {
+ -webkit-transform: scale(1.5);
+ -ms-transform: scale(1.5);
+ transform: scale(1.5);
+ opacity: 0; }
+
+.scale-out-down.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: scale(1);
+ -ms-transform: scale(1);
+ transform: scale(1);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 1; }
+
+.scale-out-down.mui-leave.mui-leave-active {
+ -webkit-transform: scale(0.5);
+ -ms-transform: scale(0.5);
+ transform: scale(0.5);
+ opacity: 0; }
+
+.spin-in.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: rotate(-0.75turn);
+ -ms-transform: rotate(-0.75turn);
+ transform: rotate(-0.75turn);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 0; }
+
+.spin-in.mui-enter.mui-enter-active {
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1; }
+
+.spin-out.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 1; }
+
+.spin-out.mui-leave.mui-leave-active {
+ -webkit-transform: rotate(0.75turn);
+ -ms-transform: rotate(0.75turn);
+ transform: rotate(0.75turn);
+ opacity: 0; }
+
+.spin-in-ccw.mui-enter {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: rotate(0.75turn);
+ -ms-transform: rotate(0.75turn);
+ transform: rotate(0.75turn);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 0; }
+
+.spin-in-ccw.mui-enter.mui-enter-active {
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1; }
+
+.spin-out-ccw.mui-leave {
+ transition-duration: 500ms;
+ transition-timing-function: linear;
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ opacity: 1; }
+
+.spin-out-ccw.mui-leave.mui-leave-active {
+ -webkit-transform: rotate(-0.75turn);
+ -ms-transform: rotate(-0.75turn);
+ transform: rotate(-0.75turn);
+ opacity: 0; }
+
+.slow {
+ transition-duration: 750ms !important; }
+
+.fast {
+ transition-duration: 250ms !important; }
+
+.linear {
+ transition-timing-function: linear !important; }
+
+.ease {
+ transition-timing-function: ease !important; }
+
+.ease-in {
+ transition-timing-function: ease-in !important; }
+
+.ease-out {
+ transition-timing-function: ease-out !important; }
+
+.ease-in-out {
+ transition-timing-function: ease-in-out !important; }
+
+.bounce-in {
+ transition-timing-function: cubic-bezier(0.485, 0.155, 0.24, 1.245) !important; }
+
+.bounce-out {
+ transition-timing-function: cubic-bezier(0.485, 0.155, 0.515, 0.845) !important; }
+
+.bounce-in-out {
+ transition-timing-function: cubic-bezier(0.76, -0.245, 0.24, 1.245) !important; }
+
+.short-delay {
+ transition-delay: 300ms !important; }
+
+.long-delay {
+ transition-delay: 700ms !important; }
+
+.shake {
+ -webkit-animation-name: shake-7;
+ animation-name: shake-7; }
+
+@-webkit-keyframes shake-7 {
+ 0%, 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90% {
+ -webkit-transform: translateX(7%);
+ transform: translateX(7%); }
+ 5%, 15%, 25%, 35%, 45%, 55%, 65%, 75%, 85%, 95% {
+ -webkit-transform: translateX(-7%);
+ transform: translateX(-7%); } }
+
+@keyframes shake-7 {
+ 0%, 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90% {
+ -webkit-transform: translateX(7%);
+ transform: translateX(7%); }
+ 5%, 15%, 25%, 35%, 45%, 55%, 65%, 75%, 85%, 95% {
+ -webkit-transform: translateX(-7%);
+ transform: translateX(-7%); } }
+
+.spin-cw {
+ -webkit-animation-name: spin-cw-1turn;
+ animation-name: spin-cw-1turn; }
+
+@-webkit-keyframes spin-cw-1turn {
+ 0% {
+ -webkit-transform: rotate(-1turn);
+ transform: rotate(-1turn); }
+ 100% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0); } }
+
+@keyframes spin-cw-1turn {
+ 0% {
+ -webkit-transform: rotate(-1turn);
+ transform: rotate(-1turn); }
+ 100% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0); } }
+
+.spin-ccw {
+ -webkit-animation-name: spin-cw-1turn;
+ animation-name: spin-cw-1turn; }
+
+@keyframes spin-cw-1turn {
+ 0% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0); }
+ 100% {
+ -webkit-transform: rotate(1turn);
+ transform: rotate(1turn); } }
+
+.wiggle {
+ -webkit-animation-name: wiggle-7deg;
+ animation-name: wiggle-7deg; }
+
+@-webkit-keyframes wiggle-7deg {
+ 40%, 50%, 60% {
+ -webkit-transform: rotate(7deg);
+ transform: rotate(7deg); }
+ 35%, 45%, 55%, 65% {
+ -webkit-transform: rotate(-7deg);
+ transform: rotate(-7deg); }
+ 0%, 30%, 70%, 100% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0); } }
+
+@keyframes wiggle-7deg {
+ 40%, 50%, 60% {
+ -webkit-transform: rotate(7deg);
+ transform: rotate(7deg); }
+ 35%, 45%, 55%, 65% {
+ -webkit-transform: rotate(-7deg);
+ transform: rotate(-7deg); }
+ 0%, 30%, 70%, 100% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0); } }
+
+.shake,
+.spin-cw,
+.spin-ccw,
+.wiggle {
+ -webkit-animation-duration: 500ms;
+ animation-duration: 500ms; }
+
+.infinite {
+ -webkit-animation-iteration-count: infinite;
+ animation-iteration-count: infinite; }
+
+.slow {
+ -webkit-animation-duration: 750ms !important;
+ animation-duration: 750ms !important; }
+
+.fast {
+ -webkit-animation-duration: 250ms !important;
+ animation-duration: 250ms !important; }
+
+.linear {
+ -webkit-animation-timing-function: linear !important;
+ animation-timing-function: linear !important; }
+
+.ease {
+ -webkit-animation-timing-function: ease !important;
+ animation-timing-function: ease !important; }
+
+.ease-in {
+ -webkit-animation-timing-function: ease-in !important;
+ animation-timing-function: ease-in !important; }
+
+.ease-out {
+ -webkit-animation-timing-function: ease-out !important;
+ animation-timing-function: ease-out !important; }
+
+.ease-in-out {
+ -webkit-animation-timing-function: ease-in-out !important;
+ animation-timing-function: ease-in-out !important; }
+
+.bounce-in {
+ -webkit-animation-timing-function: cubic-bezier(0.485, 0.155, 0.24, 1.245) !important;
+ animation-timing-function: cubic-bezier(0.485, 0.155, 0.24, 1.245) !important; }
+
+.bounce-out {
+ -webkit-animation-timing-function: cubic-bezier(0.485, 0.155, 0.515, 0.845) !important;
+ animation-timing-function: cubic-bezier(0.485, 0.155, 0.515, 0.845) !important; }
+
+.bounce-in-out {
+ -webkit-animation-timing-function: cubic-bezier(0.76, -0.245, 0.24, 1.245) !important;
+ animation-timing-function: cubic-bezier(0.76, -0.245, 0.24, 1.245) !important; }
+
+.short-delay {
+ -webkit-animation-delay: 300ms !important;
+ animation-delay: 300ms !important; }
+
+.long-delay {
+ -webkit-animation-delay: 700ms !important;
+ animation-delay: 700ms !important; }
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index d5cac940a..87498da5b 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -1,6 +1,6 @@
class TasksController < ApplicationController
skip_before_action :require_login, only: [:welcome, :create]
- before_action :edit_or_update, only: [:edit, :update, :show]
+ before_action :edit_update_show, only: [:edit, :update, :show]
def welcome
if !session[:user_id].blank?
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 90635333a..9e699647f 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -7,20 +7,26 @@
<%= csrf_meta_tags %>
-
-
- <% if current_user %>
- <%= button_to "Log out", sessions_path, method: :delete, data: { confirm: "Are you sure you want to log out?" } %>
- <% else %>
- <%= button_to "Log in with Github", '/auth/github', method: :post %>
- <% end %>
- <% if current_user %>
- <%= button_to "Add New Task", new_task_path %>
- <% end %>
-
+
<%= yield %>
+
+ © <%= Time.now.year %> Heather Herrington
+
+