From 99b83647b9a303b013ce9adf2803d78575f39073 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 31 Oct 2016 15:49:43 -0700 Subject: [PATCH 01/43] created new rails. add better_error gem to Gemfile --- .gitignore | 21 ++ Gemfile | 50 +++++ Gemfile.lock | 183 ++++++++++++++++++ Rakefile | 6 + app/assets/config/manifest.js | 3 + app/assets/images/.keep | 0 app/assets/javascripts/application.js | 16 ++ app/assets/javascripts/cable.js | 13 ++ app/assets/javascripts/channels/.keep | 0 app/assets/stylesheets/application.css | 15 ++ app/channels/application_cable/channel.rb | 4 + app/channels/application_cable/connection.rb | 4 + app/controllers/application_controller.rb | 3 + app/controllers/concerns/.keep | 0 app/helpers/application_helper.rb | 2 + app/jobs/application_job.rb | 2 + app/mailers/application_mailer.rb | 4 + app/models/application_record.rb | 3 + app/models/concerns/.keep | 0 app/views/layouts/application.html.erb | 14 ++ app/views/layouts/mailer.html.erb | 13 ++ app/views/layouts/mailer.text.erb | 1 + bin/bundle | 3 + bin/rails | 9 + bin/rake | 9 + bin/setup | 34 ++++ bin/spring | 16 ++ bin/update | 29 +++ config.ru | 5 + config/application.rb | 15 ++ config/boot.rb | 3 + config/cable.yml | 9 + config/database.yml | 25 +++ config/environment.rb | 5 + config/environments/development.rb | 54 ++++++ config/environments/production.rb | 86 ++++++++ config/environments/test.rb | 42 ++++ .../application_controller_renderer.rb | 6 + config/initializers/assets.rb | 11 ++ config/initializers/backtrace_silencers.rb | 7 + config/initializers/cookies_serializer.rb | 5 + .../initializers/filter_parameter_logging.rb | 4 + config/initializers/inflections.rb | 16 ++ config/initializers/mime_types.rb | 4 + config/initializers/new_framework_defaults.rb | 24 +++ config/initializers/session_store.rb | 3 + config/initializers/wrap_parameters.rb | 14 ++ config/locales/en.yml | 23 +++ config/puma.rb | 47 +++++ config/routes.rb | 3 + config/secrets.yml | 22 +++ config/spring.rb | 6 + 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/apple-touch-icon-precomposed.png | 0 public/apple-touch-icon.png | 0 public/favicon.ico | 0 public/robots.txt | 5 + test/controllers/.keep | 0 test/fixtures/.keep | 0 test/fixtures/files/.keep | 0 test/helpers/.keep | 0 test/integration/.keep | 0 test/mailers/.keep | 0 test/models/.keep | 0 test/test_helper.rb | 10 + tmp/.keep | 0 vendor/assets/javascripts/.keep | 0 vendor/assets/stylesheets/.keep | 0 74 files changed, 1118 insertions(+) create mode 100644 .gitignore create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 Rakefile create mode 100644 app/assets/config/manifest.js create mode 100644 app/assets/images/.keep create mode 100644 app/assets/javascripts/application.js create mode 100644 app/assets/javascripts/cable.js create mode 100644 app/assets/javascripts/channels/.keep create mode 100644 app/assets/stylesheets/application.css create mode 100644 app/channels/application_cable/channel.rb create mode 100644 app/channels/application_cable/connection.rb create mode 100644 app/controllers/application_controller.rb create mode 100644 app/controllers/concerns/.keep create mode 100644 app/helpers/application_helper.rb create mode 100644 app/jobs/application_job.rb create mode 100644 app/mailers/application_mailer.rb create mode 100644 app/models/application_record.rb create mode 100644 app/models/concerns/.keep create mode 100644 app/views/layouts/application.html.erb create mode 100644 app/views/layouts/mailer.html.erb create mode 100644 app/views/layouts/mailer.text.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 100755 bin/update create mode 100644 config.ru create mode 100644 config/application.rb create mode 100644 config/boot.rb create mode 100644 config/cable.yml 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/application_controller_renderer.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/new_framework_defaults.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/puma.rb create mode 100644 config/routes.rb create mode 100644 config/secrets.yml create mode 100644 config/spring.rb 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/apple-touch-icon-precomposed.png create mode 100644 public/apple-touch-icon.png create mode 100644 public/favicon.ico create mode 100644 public/robots.txt create mode 100644 test/controllers/.keep create mode 100644 test/fixtures/.keep create mode 100644 test/fixtures/files/.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 tmp/.keep create mode 100644 vendor/assets/javascripts/.keep create mode 100644 vendor/assets/stylesheets/.keep diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..bab620de0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# 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' + +# Ignore bundler config. +/.bundle + +# Ignore the default SQLite database. +/db/*.sqlite3 +/db/*.sqlite3-journal + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep + +# Ignore Byebug command history file. +.byebug_history diff --git a/Gemfile b/Gemfile new file mode 100644 index 000000000..b606ed5a2 --- /dev/null +++ b/Gemfile @@ -0,0 +1,50 @@ +source 'https://rubygems.org' + +gem "binding_of_caller" + +# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' +gem 'rails', '~> 5.0.0', '>= 5.0.0.1' +# Use sqlite3 as the database for Active Record +gem 'sqlite3' +# Use Puma as the app server +gem 'puma', '~> 3.0' +# 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.2' +# 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 navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks +gem 'turbolinks', '~> 5' +# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder +gem 'jbuilder', '~> 2.5' +# Use Redis adapter to run Action Cable in production +# gem 'redis', '~> 3.0' +# Use ActiveModel has_secure_password +# gem 'bcrypt', '~> 3.1.7' + +# 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', platform: :mri +end + +group :development do + # Access an IRB console on exception pages or by using <%= console %> anywhere in the code. + gem 'web-console' + gem 'listen', '~> 3.0.5' + # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring + gem 'spring' + gem 'spring-watcher-listen', '~> 2.0.0' + gem "better_errors" +end + +# Windows does not include zoneinfo files, so bundle the tzinfo-data gem +gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 000000000..4ae4c78dc --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,183 @@ +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.0.0.1) + actionpack (= 5.0.0.1) + nio4r (~> 1.2) + websocket-driver (~> 0.6.1) + actionmailer (5.0.0.1) + actionpack (= 5.0.0.1) + actionview (= 5.0.0.1) + activejob (= 5.0.0.1) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.0.0.1) + actionview (= 5.0.0.1) + activesupport (= 5.0.0.1) + rack (~> 2.0) + rack-test (~> 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.0.0.1) + activesupport (= 5.0.0.1) + builder (~> 3.1) + erubis (~> 2.7.0) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + activejob (5.0.0.1) + activesupport (= 5.0.0.1) + globalid (>= 0.3.6) + activemodel (5.0.0.1) + activesupport (= 5.0.0.1) + activerecord (5.0.0.1) + activemodel (= 5.0.0.1) + activesupport (= 5.0.0.1) + arel (~> 7.0) + activesupport (5.0.0.1) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (~> 0.7) + minitest (~> 5.1) + tzinfo (~> 1.1) + arel (7.1.4) + 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.6) + coderay (1.1.1) + coffee-rails (4.2.1) + coffee-script (>= 2.2.0) + railties (>= 4.0.0, < 5.2.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) + ffi (1.9.14) + 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) + listen (3.0.8) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + loofah (2.0.3) + nokogiri (>= 1.5.9) + mail (2.6.4) + mime-types (>= 1.16, < 4) + method_source (0.8.2) + 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) + nio4r (1.2.1) + nokogiri (1.6.8.1) + mini_portile2 (~> 2.1.0) + puma (3.6.0) + rack (2.0.1) + rack-test (0.6.3) + rack (>= 1.0) + rails (5.0.0.1) + actioncable (= 5.0.0.1) + actionmailer (= 5.0.0.1) + actionpack (= 5.0.0.1) + actionview (= 5.0.0.1) + activejob (= 5.0.0.1) + activemodel (= 5.0.0.1) + activerecord (= 5.0.0.1) + activesupport (= 5.0.0.1) + bundler (>= 1.3.0, < 2.0) + railties (= 5.0.0.1) + sprockets-rails (>= 2.0.0) + rails-dom-testing (2.0.1) + activesupport (>= 4.2.0, < 6.0) + nokogiri (~> 1.6.0) + rails-html-sanitizer (1.0.3) + loofah (~> 2.0) + railties (5.0.0.1) + actionpack (= 5.0.0.1) + activesupport (= 5.0.0.1) + method_source + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rake (11.3.0) + rb-fsevent (0.9.8) + rb-inotify (0.9.7) + ffi (>= 0.5.0) + 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) + spring (2.0.0) + activesupport (>= 4.2) + spring-watcher-listen (2.0.1) + listen (>= 2.7, < 4.0) + spring (>= 1.2, < 3.0) + 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.12) + 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.3) + execjs (>= 0.3.0, < 3) + web-console (3.4.0) + actionview (>= 5.0) + activemodel (>= 5.0) + debug_inspector + railties (>= 5.0) + websocket-driver (0.6.4) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.2) + +PLATFORMS + ruby + +DEPENDENCIES + better_errors + binding_of_caller + byebug + coffee-rails (~> 4.2) + jbuilder (~> 2.5) + jquery-rails + listen (~> 3.0.5) + puma (~> 3.0) + rails (~> 5.0.0, >= 5.0.0.1) + sass-rails (~> 5.0) + spring + spring-watcher-listen (~> 2.0.0) + sqlite3 + turbolinks (~> 5) + tzinfo-data + uglifier (>= 1.3.0) + web-console + +BUNDLED WITH + 1.13.6 diff --git a/Rakefile b/Rakefile new file mode 100644 index 000000000..e85f91391 --- /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_relative 'config/application' + +Rails.application.load_tasks diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js new file mode 100644 index 000000000..b16e53d6d --- /dev/null +++ b/app/assets/config/manifest.js @@ -0,0 +1,3 @@ +//= link_tree ../images +//= link_directory ../javascripts .js +//= link_directory ../stylesheets .css 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..b12018d09 --- /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. JavaScript code in this file should be added after the last require_* statement. +// +// 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/cable.js b/app/assets/javascripts/cable.js new file mode 100644 index 000000000..71ee1e66d --- /dev/null +++ b/app/assets/javascripts/cable.js @@ -0,0 +1,13 @@ +// Action Cable provides the framework to deal with WebSockets in Rails. +// You can generate new channels where WebSocket features live using the rails generate channel command. +// +//= require action_cable +//= require_self +//= require_tree ./channels + +(function() { + this.App || (this.App = {}); + + App.cable = ActionCable.createConsumer(); + +}).call(this); diff --git a/app/assets/javascripts/channels/.keep b/app/assets/javascripts/channels/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css new file mode 100644 index 000000000..0ebd7fe82 --- /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 other CSS/SCSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb new file mode 100644 index 000000000..d67269728 --- /dev/null +++ b/app/channels/application_cable/channel.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb new file mode 100644 index 000000000..0ff5442f4 --- /dev/null +++ b/app/channels/application_cable/connection.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Connection < ActionCable::Connection::Base + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb new file mode 100644 index 000000000..1c07694e9 --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,3 @@ +class ApplicationController < ActionController::Base + 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/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/jobs/application_job.rb b/app/jobs/application_job.rb new file mode 100644 index 000000000..a009ace51 --- /dev/null +++ b/app/jobs/application_job.rb @@ -0,0 +1,2 @@ +class ApplicationJob < ActiveJob::Base +end diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb new file mode 100644 index 000000000..286b2239d --- /dev/null +++ b/app/mailers/application_mailer.rb @@ -0,0 +1,4 @@ +class ApplicationMailer < ActionMailer::Base + default from: 'from@example.com' + layout 'mailer' +end diff --git a/app/models/application_record.rb b/app/models/application_record.rb new file mode 100644 index 000000000..10a4cba84 --- /dev/null +++ b/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end 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..3360e304d --- /dev/null +++ b/app/views/layouts/application.html.erb @@ -0,0 +1,14 @@ + + + + ApiMuncher + <%= csrf_meta_tags %> + + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> + <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> + + + + <%= yield %> + + diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb new file mode 100644 index 000000000..cbd34d2e9 --- /dev/null +++ b/app/views/layouts/mailer.html.erb @@ -0,0 +1,13 @@ + + + + + + + + + <%= yield %> + + diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb new file mode 100644 index 000000000..37f0bddbd --- /dev/null +++ b/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> 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..5badb2fde --- /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', __dir__) +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..e620b4dad --- /dev/null +++ b/bin/setup @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +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') || system!('bundle install') + + # puts "\n== Copying sample files ==" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' + # end + + puts "\n== Preparing database ==" + system! 'bin/rails db:setup' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/bin/spring b/bin/spring new file mode 100755 index 000000000..9bc076b9e --- /dev/null +++ b/bin/spring @@ -0,0 +1,16 @@ +#!/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' + + lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read) + if spring = lockfile.specs.detect { |spec| spec.name == "spring" } + Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path + gem 'spring', spring.version + require 'spring/binstub' + end +end diff --git a/bin/update b/bin/update new file mode 100755 index 000000000..a8e4462f2 --- /dev/null +++ b/bin/update @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/config.ru b/config.ru new file mode 100644 index 000000000..f7ba0b527 --- /dev/null +++ b/config.ru @@ -0,0 +1,5 @@ +# This file is used by Rack-based servers to start the application. + +require_relative 'config/environment' + +run Rails.application diff --git a/config/application.rb b/config/application.rb new file mode 100644 index 000000000..38f15dbec --- /dev/null +++ b/config/application.rb @@ -0,0 +1,15 @@ +require_relative 'boot' + +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 ApiMuncher + 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. + end +end diff --git a/config/boot.rb b/config/boot.rb new file mode 100644 index 000000000..30f5120df --- /dev/null +++ b/config/boot.rb @@ -0,0 +1,3 @@ +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) + +require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 000000000..0bbde6f74 --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,9 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: redis://localhost:6379/1 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..426333bb4 --- /dev/null +++ b/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require_relative 'application' + +# 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..6f7197045 --- /dev/null +++ b/config/environments/development.rb @@ -0,0 +1,54 @@ +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. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + if Rails.root.join('tmp/caching-dev.txt').exist? + config.action_controller.perform_caching = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => 'public, max-age=172800' + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = 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 + + # Suppress logger output for asset requests. + config.assets.quiet = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true + + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + config.file_watcher = ActiveSupport::EventedFileUpdateChecker +end diff --git a/config/environments/production.rb b/config/environments/production.rb new file mode 100644 index 000000000..2a3bd799e --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,86 @@ +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 + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = 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 + + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # 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 + + # Mount Action Cable outside main process or domain + # config.action_cable.mount_path = nil + # config.action_cable.url = 'wss://example.com/cable' + # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] + + # 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 = [ :request_id ] + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment) + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "api-muncher_#{Rails.env}" + config.action_mailer.perform_caching = false + + # 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 + + # Use a different logger for distributed setups. + # require 'syslog/logger' + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') + + if ENV["RAILS_LOG_TO_STDOUT"].present? + logger = ActiveSupport::Logger.new(STDOUT) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end + + # 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..30587ef6d --- /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 public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + '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 + config.action_mailer.perform_caching = 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 + + # 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/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb new file mode 100644 index 000000000..51639b67a --- /dev/null +++ b/config/initializers/application_controller_renderer.rb @@ -0,0 +1,6 @@ +# Be sure to restart your server when you modify this file. + +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) 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..5a6a32d37 --- /dev/null +++ b/config/initializers/cookies_serializer.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Specify a serializer for the signed and encrypted cookie jars. +# Valid options are :json, :marshal, and :hybrid. +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/new_framework_defaults.rb b/config/initializers/new_framework_defaults.rb new file mode 100644 index 000000000..0706cafd4 --- /dev/null +++ b/config/initializers/new_framework_defaults.rb @@ -0,0 +1,24 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.0 upgrade. +# +# Read the Rails 5.0 release notes for more info on each option. + +# Enable per-form CSRF tokens. Previous versions had false. +Rails.application.config.action_controller.per_form_csrf_tokens = true + +# Enable origin-checking CSRF mitigation. Previous versions had false. +Rails.application.config.action_controller.forgery_protection_origin_check = true + +# Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`. +# Previous versions had false. +ActiveSupport.to_time_preserves_timezone = true + +# Require `belongs_to` associations by default. Previous versions had false. +Rails.application.config.active_record.belongs_to_required_by_default = true + +# Do not halt callback chains when a callback returns false. Previous versions had true. +ActiveSupport.halt_callback_chains_on_return_false = false + +# Configure SSL options to enable HSTS with subdomains. Previous versions had false. +Rails.application.config.ssl_options = { hsts: { subdomains: true } } diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb new file mode 100644 index 000000000..6cc0e03e4 --- /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: '_api-muncher_session' diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb new file mode 100644 index 000000000..bbfc3961b --- /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] +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/puma.rb b/config/puma.rb new file mode 100644 index 000000000..c7f311f81 --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,47 @@ +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum, this matches the default thread size of Active Record. +# +threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests, default is 3000. +# +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. If you use this option +# you need to make sure to reconnect any threads in the `on_worker_boot` +# block. +# +# preload_app! + +# The code in the `on_worker_boot` will be called if you are using +# clustered mode by specifying a number of `workers`. After each worker +# process is booted this block will be run, if you are using `preload_app!` +# option you will want to use this block to reconnect to any threads +# or connections that may have been created at application boot, Ruby +# cannot share connections between processes. +# +# on_worker_boot do +# ActiveRecord::Base.establish_connection if defined?(ActiveRecord) +# end + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 000000000..787824f88 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,3 @@ +Rails.application.routes.draw do + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html +end diff --git a/config/secrets.yml b/config/secrets.yml new file mode 100644 index 000000000..6142f33d9 --- /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 `rails 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: c344e8f5cc547253c4b92417b9ba8dad994cf8db17e38aabbe494e83f935d7df7dee715d4f12f5f9d05613efe143a338be1ebc11a6b29d45a36e76a2e805b80f + +test: + secret_key_base: ae05c50586cc012c953c8358db16e93d9140b9326ab36f6f9a8c6c89713baa4863894870efcc958d7d56261cae40bb0497adf90e8ef7ddcabab58c28a3ff28dd + +# 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/config/spring.rb b/config/spring.rb new file mode 100644 index 000000000..c9119b40c --- /dev/null +++ b/config/spring.rb @@ -0,0 +1,6 @@ +%w( + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +).each { |path| Spring.watch(path) } diff --git a/db/seeds.rb b/db/seeds.rb new file mode 100644 index 000000000..1beea2acc --- /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 rails db:seed command (or created alongside the database with db:setup). +# +# Examples: +# +# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) +# Character.create(name: 'Luke', movie: movies.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/apple-touch-icon-precomposed.png b/public/apple-touch-icon-precomposed.png new file mode 100644 index 000000000..e69de29bb diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 000000000..e69de29bb 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/fixtures/.keep b/test/fixtures/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/files/.keep b/test/fixtures/files/.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/tmp/.keep b/tmp/.keep new file mode 100644 index 000000000..e69de29bb 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 3b6d5534292fd42fabca35391e1165ca46ce4e97 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 31 Oct 2016 16:11:16 -0700 Subject: [PATCH 02/43] add awesome_print gem and api gems --- Gemfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Gemfile b/Gemfile index b606ed5a2..9d34a21dc 100644 --- a/Gemfile +++ b/Gemfile @@ -2,6 +2,11 @@ source 'https://rubygems.org' gem "binding_of_caller" +# API GEMS +gem 'httparty' +gem 'foundation-rails' +gem 'awesome_print' + # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.0.0', '>= 5.0.0.1' # Use sqlite3 as the database for Active Record From ebac1f1af2a5878fc9be957dfbe34e7a04e44780 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 31 Oct 2016 16:41:50 -0700 Subject: [PATCH 03/43] create rs_api_wrapper.rb in lib and search method as helper --- lib/rs_api_wrapper.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 lib/rs_api_wrapper.rb diff --git a/lib/rs_api_wrapper.rb b/lib/rs_api_wrapper.rb new file mode 100644 index 000000000..05f22defa --- /dev/null +++ b/lib/rs_api_wrapper.rb @@ -0,0 +1,15 @@ +require 'httparty' + + +class Rs_Api_Wrapper + BASE_URL = "https://api.edamam.com/" + APP_ID = "f8c6af19" + APP_KEY = "3e974f32b9b7c425a0a6e4bae6e5e131" + + def self.search(term) + url = BASE_URL + "search?" + "q=#{term}" + "&app_id=#{APP_ID}" + "&app_key=#{APP_KEY}" + + response = HTTParty.get(url) + + end +end From d9380f676d98d2e828c74955f20bc81b5156d7bd Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 31 Oct 2016 16:43:29 -0700 Subject: [PATCH 04/43] created homepages controller --- app/assets/javascripts/homepages.coffee | 3 +++ app/assets/stylesheets/homepages.scss | 3 +++ app/controllers/homepages_controller.rb | 2 ++ app/helpers/homepages_helper.rb | 2 ++ test/controllers/homepages_controller_test.rb | 7 +++++++ 5 files changed, 17 insertions(+) create mode 100644 app/assets/javascripts/homepages.coffee create mode 100644 app/assets/stylesheets/homepages.scss create mode 100644 app/controllers/homepages_controller.rb create mode 100644 app/helpers/homepages_helper.rb create mode 100644 test/controllers/homepages_controller_test.rb diff --git a/app/assets/javascripts/homepages.coffee b/app/assets/javascripts/homepages.coffee new file mode 100644 index 000000000..24f83d18b --- /dev/null +++ b/app/assets/javascripts/homepages.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/homepages.scss b/app/assets/stylesheets/homepages.scss new file mode 100644 index 000000000..e42583ae8 --- /dev/null +++ b/app/assets/stylesheets/homepages.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the homepages 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/homepages_controller.rb b/app/controllers/homepages_controller.rb new file mode 100644 index 000000000..8663bd848 --- /dev/null +++ b/app/controllers/homepages_controller.rb @@ -0,0 +1,2 @@ +class HomepagesController < ApplicationController +end diff --git a/app/helpers/homepages_helper.rb b/app/helpers/homepages_helper.rb new file mode 100644 index 000000000..4bd8098f3 --- /dev/null +++ b/app/helpers/homepages_helper.rb @@ -0,0 +1,2 @@ +module HomepagesHelper +end diff --git a/test/controllers/homepages_controller_test.rb b/test/controllers/homepages_controller_test.rb new file mode 100644 index 000000000..d73f39b9c --- /dev/null +++ b/test/controllers/homepages_controller_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class HomepagesControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end From 1ecfa593678ca0aa218308edc5e721c26c2f00f7 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 31 Oct 2016 16:46:10 -0700 Subject: [PATCH 05/43] set up application.rb --- config/application.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/application.rb b/config/application.rb index 38f15dbec..608454684 100644 --- a/config/application.rb +++ b/config/application.rb @@ -11,5 +11,9 @@ 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. + + config.active_record.raise_in_transactional_callbacks = true + + config.autoload_paths << Rails.root.join('lib') end end From 5fd34e38fbc56bccd9256472f2ead3ee2918a00e Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 31 Oct 2016 22:26:20 -0700 Subject: [PATCH 06/43] complete recipe search api --- ...i_wrapper.rb => recipe_search_api_wrapper.rb} | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) rename lib/{rs_api_wrapper.rb => recipe_search_api_wrapper.rb} (51%) diff --git a/lib/rs_api_wrapper.rb b/lib/recipe_search_api_wrapper.rb similarity index 51% rename from lib/rs_api_wrapper.rb rename to lib/recipe_search_api_wrapper.rb index 05f22defa..b1bccea4a 100644 --- a/lib/rs_api_wrapper.rb +++ b/lib/recipe_search_api_wrapper.rb @@ -1,15 +1,25 @@ require 'httparty' +#require 'recipe' +require_relative './recipe' - -class Rs_Api_Wrapper +class RecipeSearchApiWrapper BASE_URL = "https://api.edamam.com/" APP_ID = "f8c6af19" APP_KEY = "3e974f32b9b7c425a0a6e4bae6e5e131" def self.search(term) url = BASE_URL + "search?" + "q=#{term}" + "&app_id=#{APP_ID}" + "&app_key=#{APP_KEY}" - response = HTTParty.get(url) + # puts response + recipes = [] + hits = response['hits'] + hits.each do |hit| + recipes << Recipe.new(hit['recipe']) + end + return recipes end + end + +RecipeSearchApiWrapper.search('pita') From d95064d8e74c20bc603fcad09f2d5e391a376db7 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 31 Oct 2016 22:26:57 -0700 Subject: [PATCH 07/43] create recipe model --- lib/recipe.rb | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 lib/recipe.rb diff --git a/lib/recipe.rb b/lib/recipe.rb new file mode 100644 index 000000000..7a21fcdcd --- /dev/null +++ b/lib/recipe.rb @@ -0,0 +1,8 @@ +class Recipe + attr_reader :uri, :label, :image + def initialize(hash) + hash.each do |k,v| + self.instance_variable_set("@#{k}", v) + end + end +end From 55028d6e04f80b3be096830bdfa2030dd8359020 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 31 Oct 2016 22:31:00 -0700 Subject: [PATCH 08/43] remove extra call to search api --- lib/recipe_search_api_wrapper.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/recipe_search_api_wrapper.rb b/lib/recipe_search_api_wrapper.rb index b1bccea4a..b7523b788 100644 --- a/lib/recipe_search_api_wrapper.rb +++ b/lib/recipe_search_api_wrapper.rb @@ -21,5 +21,3 @@ def self.search(term) end end - -RecipeSearchApiWrapper.search('pita') From 8a52dbb37aa391e87902d5d5f604fbbdec25585e Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 31 Oct 2016 23:13:17 -0700 Subject: [PATCH 09/43] completed search mvc logic, show recipe with label, image and link to details --- Gemfile.lock | 19 +++++++++++++++++++ app/controllers/homepages_controller.rb | 7 +++++++ app/views/homepages/index.html.erb | 7 +++++++ app/views/homepages/search.html.erb | 6 ++++++ config/routes.rb | 4 ++++ lib/recipe.rb | 2 +- lib/recipe_search_api_wrapper.rb | 1 - 7 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 app/views/homepages/index.html.erb create mode 100644 app/views/homepages/search.html.erb diff --git a/Gemfile.lock b/Gemfile.lock index 4ae4c78dc..6a119c8e9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -39,6 +39,11 @@ GEM minitest (~> 5.1) tzinfo (~> 1.1) arel (7.1.4) + awesome_print (1.7.0) + babel-source (5.8.35) + babel-transpiler (0.7.0) + babel-source (>= 4.0, < 6) + execjs (~> 2.0) better_errors (2.1.1) coderay (>= 1.0.0) erubis (>= 2.6.6) @@ -60,8 +65,14 @@ GEM erubis (2.7.0) execjs (2.7.0) ffi (1.9.14) + foundation-rails (6.2.4.0) + railties (>= 3.1.0) + sass (>= 3.3.0, < 3.5) + sprockets-es6 (>= 0.9.0) globalid (0.3.7) activesupport (>= 4.1.0) + httparty (0.14.0) + multi_xml (>= 0.5.2) i18n (0.7.0) jbuilder (2.6.0) activesupport (>= 3.0.0, < 5.1) @@ -84,6 +95,7 @@ GEM mini_portile2 (2.1.0) minitest (5.9.1) multi_json (1.12.1) + multi_xml (0.5.5) nio4r (1.2.1) nokogiri (1.6.8.1) mini_portile2 (~> 2.1.0) @@ -133,6 +145,10 @@ GEM sprockets (3.7.0) concurrent-ruby (~> 1.0) rack (> 1, < 3) + sprockets-es6 (0.9.2) + babel-source (>= 5.8.11) + babel-transpiler + sprockets (>= 3.0.0) sprockets-rails (3.2.0) actionpack (>= 4.0) activesupport (>= 4.0) @@ -161,10 +177,13 @@ PLATFORMS ruby DEPENDENCIES + awesome_print better_errors binding_of_caller byebug coffee-rails (~> 4.2) + foundation-rails + httparty jbuilder (~> 2.5) jquery-rails listen (~> 3.0.5) diff --git a/app/controllers/homepages_controller.rb b/app/controllers/homepages_controller.rb index 8663bd848..b2ec8ae6f 100644 --- a/app/controllers/homepages_controller.rb +++ b/app/controllers/homepages_controller.rb @@ -1,2 +1,9 @@ class HomepagesController < ApplicationController + def index + end + + def search + @term = params[:term] + @recipes = RecipeSearchApiWrapper.search(@term) + end end diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb new file mode 100644 index 000000000..57ba63daf --- /dev/null +++ b/app/views/homepages/index.html.erb @@ -0,0 +1,7 @@ +

Search Recipe

+ +<%= form_tag search_path, method: "post" do %> + <%= label_tag :term, "Search" %> + <%= text_field_tag :term %> + <%= submit_tag "Search", :class => "button" %> +<% end %> diff --git a/app/views/homepages/search.html.erb b/app/views/homepages/search.html.erb new file mode 100644 index 000000000..91042407f --- /dev/null +++ b/app/views/homepages/search.html.erb @@ -0,0 +1,6 @@ +

Search Result

+<% @recipes.each do |recipe| %> +

<%= recipe.label %>

+ <%= image_tag "#{recipe.image}", :class=>'recipe_photo' %> +

<%= link_to "Details", recipe.url %>

+<% end %> diff --git a/config/routes.rb b/config/routes.rb index 787824f88..48e7769d2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,7 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html + + root to: 'homepages#index' + + post 'search' => 'homepages#search', as: 'search' end diff --git a/lib/recipe.rb b/lib/recipe.rb index 7a21fcdcd..5e77a14c5 100644 --- a/lib/recipe.rb +++ b/lib/recipe.rb @@ -1,5 +1,5 @@ class Recipe - attr_reader :uri, :label, :image + attr_reader :uri, :label, :image, :url def initialize(hash) hash.each do |k,v| self.instance_variable_set("@#{k}", v) diff --git a/lib/recipe_search_api_wrapper.rb b/lib/recipe_search_api_wrapper.rb index b7523b788..afa2dd430 100644 --- a/lib/recipe_search_api_wrapper.rb +++ b/lib/recipe_search_api_wrapper.rb @@ -19,5 +19,4 @@ def self.search(term) end return recipes end - end From f77e1e2d1deaa823297b1d0caf9529ed2943fb0e Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Tue, 1 Nov 2016 11:17:04 -0700 Subject: [PATCH 10/43] add foundation for css --- app/assets/stylesheets/application.css | 2 + app/assets/stylesheets/foundation.css | 4194 ++++++++++++++++++++++++ 2 files changed, 4196 insertions(+) create mode 100644 app/assets/stylesheets/foundation.css diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 0ebd7fe82..5ba3617bc 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -13,3 +13,5 @@ *= require_tree . *= require_self */ +@import url('foundation.css'); +@import url('app.css'); diff --git a/app/assets/stylesheets/foundation.css b/app/assets/stylesheets/foundation.css new file mode 100644 index 000000000..66aca962d --- /dev/null +++ b/app/assets/stylesheets/foundation.css @@ -0,0 +1,4194 @@ +@charset "UTF-8"; +/** + * Foundation for Sites by ZURB + * Version 6.2.3 + * 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 { + max-width: none; + 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, +.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 { + float: none; + margin-left: auto; + margin-right: auto; } + +.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, + .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 { + float: none; + margin-left: auto; + margin-right: auto; } + .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, + .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 { + float: none; + margin-left: auto; + margin-right: auto; } + .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.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; + height: 100%; + 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%; + 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 { + 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 { + 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; } + +.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 .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 .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 .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, + table tfoot { + background: #f8f8f8; + 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 tr:hover { + background-color: #f9f9f9; } + +table.hover 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; } + +.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; } + +.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; } From 38898a55f106d342be68e4500487c0f38431a871 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Tue, 1 Nov 2016 20:51:59 -0700 Subject: [PATCH 11/43] add pagination on list show. show + 5 and -5 pages, handle empty pages. result count and last_page not ideal. can improve later --- .DS_Store | Bin 0 -> 6148 bytes Gemfile.lock | 2 ++ app/.DS_Store | Bin 0 -> 6148 bytes app/assets/.DS_Store | Bin 0 -> 6148 bytes app/controllers/homepages_controller.rb | 10 +++++++-- app/views/homepages/_pagination.html.erb | 9 ++++++++ app/views/homepages/index.html.erb | 1 + app/views/homepages/search.html.erb | 5 +++++ config/routes.rb | 1 + lib/recipe_search_api_wrapper.rb | 26 ++++++++++++++++++----- 10 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 .DS_Store create mode 100644 app/.DS_Store create mode 100644 app/assets/.DS_Store create mode 100644 app/views/homepages/_pagination.html.erb diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..93001eb5c480f67dcea3668d954a19a5df157e58 GIT binary patch literal 6148 zcmeHK-EPw`6h3ZBm+&KsgtT4e28oMl>QuxuA*50|pOH*oQ_*IAs@;99Q!-A&*wOfiAc1k{cWN;5&1}r)yv4vFmC6x zVii+!11Pu;*^5&dUm>Ng+C zERT|GFfPzvy-2dYoVDdN>rYfaPon%7zG|R@`o?_T+-+=z&1Pe<8P0chP`=Z=yI2JN z`mOEz`-j7~@8<6pA3p0<5co(byKe9|d_lp4ciJ6ismzX0!)%XYN+>Hy^A#;cX=>CX zNg2HX_sHgo^%6HIa%qdkG%b02EO}I@PjQL!qr_RGM>L?Jnn6kfn@zlwp9)KP)n;QB zDdyj!lae3DS@iS3OIGH>5tdnUMF)A&DPY@w1d}e&Y zFT@vszef+KLyv)5(4}vWK#0ups8WvJCzRVfUOkKFfj2B~6@l0+R*g>4TZVO$G%ods z*eotWJufrc!M}1|6L8}?1)KsGRssG#gh-4ngG-I-(}7G~0f1FhD??fR`~yR-0JaP+ zHKGP4v@1}%3UkE}=I$W0JK9@@ztpJRNvM(0j~Q8*8;USj4-qOliIzr}I|ZBqwgR4h ztn>N5_xJn1?c|=E0#1SdN&!*rbUST?WX{%=;P|W!kq(jAn77oZT#%XLSQYpv-at}@ ZwvY?JmcgY))WF=2fRe#wPJw@_z%SYt1i}CS literal 0 HcmV?d00001 diff --git a/Gemfile.lock b/Gemfile.lock index 6a119c8e9..9a43eb56b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -172,6 +172,7 @@ GEM websocket-driver (0.6.4) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.2) + will_paginate (3.1.5) PLATFORMS ruby @@ -197,6 +198,7 @@ DEPENDENCIES tzinfo-data uglifier (>= 1.3.0) web-console + will_paginate (~> 3.1.0) BUNDLED WITH 1.13.6 diff --git a/app/.DS_Store b/app/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0764d0cbb145f0ab05ee622f1b0d7475dbbf97dd GIT binary patch literal 6148 zcmeHK!EVz)5S?w^#->8#fYcs+LE_Lusvs(akgQM+y&(m`0Z?l<7BO z1MmlY3SYp7@B#22 zWm-5+s2m05r>VS%QW>?pZG&aNGO%e3@Y>y_ka9dRHP)KJ~eCo zdo)dxyy*3Qh^=jBXSd^ep6lKA-VVpI92Q|Q&j;b`wW=kfI5PGNDbv4p7`;s5@~nIJ zsmzKn$>Lef{mrW+8_9AY=h-M%d7g*G7_q9Ov+luS(SOuC^!xqZ^3Y!#AH#mof4E$F z?*6@_C#UC=4<8p-%j+*{8YHk`DY;|t4}68unB?VfmZdU#hjxx}>4L@}EW;C1+Su@z zuy4>hVSDhG@GWQtO!369>f0ou#QsWD2Yqn%>00kkE8Y&hNA9SV_2-IThb9<#vVIKe zQ-5xJ>It%rZk%P^cZV*KH>R>R2A)~n6ICml!GKu;?%rk$$Bx1>U>VpT26%t)p^SmS zN~793P^c>a&_S~j*nA3djBhY7SZTx?h|r-x9V*NfL+Eg{`^GOYSZUPZB+TVQn4X2X zp$OGG^83o2M4-`@mI2E^lYwnr?eh8m?B@G_GsxB~1D1jRiUHxA3{M7_k~v#jljF12 thn_=O*ss#4LQt6FSQ&g2A3&AhozDg^Fj#3s3&j2iC>m^G8Th9R{05U1xdi|K literal 0 HcmV?d00001 diff --git a/app/assets/.DS_Store b/app/assets/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7ae2a74f5eb160220263845d7d3fc01cd711fc18 GIT binary patch literal 6148 zcmeHK!EVz)5S>j!uoWS4Kx&V^RN~M>svs(akgT*EdP7PD2SBaen8e8SMzPbVgdkt| z2>1g&rC-p`fw#MpDrthm2_ZBi&A!?3Ja6``Q4ImL@grn;09|xnhj>I8(*^; zXBt3d?~&5rIMe5GrsK70N&Jfnn6+!rIcdu21Ff!~c_^O4AOEywe|`fs7ZlNe5-OI~ z+SLBIQ`@AEsJw(17-0v)u1pfHq0Y-F&6Dv` z`MWo1-q+Kvp5*<)-se?R4#Bkpowjynv(B^jUeM{Z=X=5I-~jQH&eQqa_qKQUUmTxZ zTz#5-o`3mXp1VsT+KonR~fL{?_b15gG zC?E=m0!9Jzeh3&t#>%06b)d0F0AL+yYlzLKpy39LA!FqbS76FffsU&9h@l)E`GD&} z#>%0ilj6gN;*k}fP?Q}V_YZ72snDUcqJSu{s=$`(w#@$j^7rTeRg&~X0a4(;Qb5&@ zdPiMMiTBpE$(g-2fSGBEiNurf#^3j9?C FegVzvj0pe$ literal 0 HcmV?d00001 diff --git a/app/controllers/homepages_controller.rb b/app/controllers/homepages_controller.rb index b2ec8ae6f..43c9b8f69 100644 --- a/app/controllers/homepages_controller.rb +++ b/app/controllers/homepages_controller.rb @@ -1,9 +1,15 @@ class HomepagesController < ApplicationController def index end - + def search @term = params[:term] - @recipes = RecipeSearchApiWrapper.search(@term) + @page = params[:page] || 1 + @page = @page.to_i + results = RecipeSearchApiWrapper.search(@term, @page) + @recipes = results[:recipes] + @count = results[:count] + @more = results[:more] + puts "#{} #{results[:more]}" end end diff --git a/app/views/homepages/_pagination.html.erb b/app/views/homepages/_pagination.html.erb new file mode 100644 index 000000000..90bb3aa72 --- /dev/null +++ b/app/views/homepages/_pagination.html.erb @@ -0,0 +1,9 @@ +<% last_page = @page + 3 %> +<% if @count == 0 %> +<% last_page = @page %> +<% end %> + + +<% for i in ([@page-5, 1].max)...last_page %> + <%= link_to "#{i} |", get_search_path(:page => i, :term => term) %> +<% end %> diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index 57ba63daf..b5d54919a 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -3,5 +3,6 @@ <%= form_tag search_path, method: "post" do %> <%= label_tag :term, "Search" %> <%= text_field_tag :term %> + <%= submit_tag "Search", :class => "button" %> <% end %> diff --git a/app/views/homepages/search.html.erb b/app/views/homepages/search.html.erb index 91042407f..d4d6b9f5f 100644 --- a/app/views/homepages/search.html.erb +++ b/app/views/homepages/search.html.erb @@ -4,3 +4,8 @@ <%= image_tag "#{recipe.image}", :class=>'recipe_photo' %>

<%= link_to "Details", recipe.url %>

<% end %> + +<%= render :partial => 'pagination', :locals => { + :term => @term, + :count => @count, + :more => @more } %> diff --git a/config/routes.rb b/config/routes.rb index 48e7769d2..961ff58df 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,5 +3,6 @@ root to: 'homepages#index' + get 'search' => 'homepages#search', as: 'get_search' post 'search' => 'homepages#search', as: 'search' end diff --git a/lib/recipe_search_api_wrapper.rb b/lib/recipe_search_api_wrapper.rb index afa2dd430..ba2fec05a 100644 --- a/lib/recipe_search_api_wrapper.rb +++ b/lib/recipe_search_api_wrapper.rb @@ -3,20 +3,36 @@ require_relative './recipe' class RecipeSearchApiWrapper - BASE_URL = "https://api.edamam.com/" + # scheme => https/http/ftp + # host => api.edamam.com + # path => /search + # query parameters => "q=#{term}" + "&app_id=#{APP_ID}" + BASE_URL = "https://api.edamam.com" APP_ID = "f8c6af19" APP_KEY = "3e974f32b9b7c425a0a6e4bae6e5e131" + PAGE_SIZE = 10 + + def self.search(term, page) + page ||= 1 + page = page.to_i + + from = (page - 1) * PAGE_SIZE + to = from + PAGE_SIZE + + + url = BASE_URL + "/search?" + "q=#{term}" + "&app_id=#{APP_ID}" + "&app_key=#{APP_KEY}" + "&from=#{from}&to=#{to}" - def self.search(term) - url = BASE_URL + "search?" + "q=#{term}" + "&app_id=#{APP_ID}" + "&app_key=#{APP_KEY}" response = HTTParty.get(url) - # puts response recipes = [] hits = response['hits'] hits.each do |hit| recipes << Recipe.new(hit['recipe']) end - return recipes + return { + :recipes => recipes, + :count => response['count'], + :more => response['more'], + } end end From fef24c331471c3349b37d46686e16c7ffb4fe56b Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Wed, 2 Nov 2016 10:18:28 -0700 Subject: [PATCH 12/43] comment out puts in api homepage countroller --- Gemfile.lock | 2 -- app/controllers/homepages_controller.rb | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9a43eb56b..6a119c8e9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -172,7 +172,6 @@ GEM websocket-driver (0.6.4) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.2) - will_paginate (3.1.5) PLATFORMS ruby @@ -198,7 +197,6 @@ DEPENDENCIES tzinfo-data uglifier (>= 1.3.0) web-console - will_paginate (~> 3.1.0) BUNDLED WITH 1.13.6 diff --git a/app/controllers/homepages_controller.rb b/app/controllers/homepages_controller.rb index 43c9b8f69..a232a2d77 100644 --- a/app/controllers/homepages_controller.rb +++ b/app/controllers/homepages_controller.rb @@ -10,6 +10,6 @@ def search @recipes = results[:recipes] @count = results[:count] @more = results[:more] - puts "#{} #{results[:more]}" + # puts "#{} #{results[:more]}" end end From 88a53c6138dce5729b869f119a17ee9347415f34 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Wed, 2 Nov 2016 14:26:43 -0700 Subject: [PATCH 13/43] complete show individual recipe with label, image and link to original recipe --- app/controllers/homepages_controller.rb | 5 +++++ app/views/homepages/search.html.erb | 2 +- app/views/homepages/show.html.erb | 5 +++++ config/routes.rb | 1 + lib/recipe.rb | 2 +- lib/recipe_search_api_wrapper.rb | 20 +++++++++++++++++++- 6 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 app/views/homepages/show.html.erb diff --git a/app/controllers/homepages_controller.rb b/app/controllers/homepages_controller.rb index a232a2d77..05e2e19f1 100644 --- a/app/controllers/homepages_controller.rb +++ b/app/controllers/homepages_controller.rb @@ -12,4 +12,9 @@ def search @more = results[:more] # puts "#{} #{results[:more]}" end + + def show + @recipe_id= params[:uri] + @recipe = RecipeSearchApiWrapper.find(@recipe_id) + end end diff --git a/app/views/homepages/search.html.erb b/app/views/homepages/search.html.erb index d4d6b9f5f..1b0b23563 100644 --- a/app/views/homepages/search.html.erb +++ b/app/views/homepages/search.html.erb @@ -2,7 +2,7 @@ <% @recipes.each do |recipe| %>

<%= recipe.label %>

<%= image_tag "#{recipe.image}", :class=>'recipe_photo' %> -

<%= link_to "Details", recipe.url %>

+

<%= link_to "Details", show_path(:uri => recipe.uri) %>

<% end %> <%= render :partial => 'pagination', :locals => { diff --git a/app/views/homepages/show.html.erb b/app/views/homepages/show.html.erb new file mode 100644 index 000000000..120251cd5 --- /dev/null +++ b/app/views/homepages/show.html.erb @@ -0,0 +1,5 @@ +

<%= @recipe.label %>

+<%= image_tag "#{@recipe.image}", :class=>'recipe_photo' %> +

<%= @recipe.ingredients %>

+

<%= @recipe.dietLabels %>

+

<%= link_to "Learn More", @recipe.url %>

diff --git a/config/routes.rb b/config/routes.rb index 961ff58df..89fc8614c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -5,4 +5,5 @@ get 'search' => 'homepages#search', as: 'get_search' post 'search' => 'homepages#search', as: 'search' + get 'show' => 'homepages#show', as: 'show' end diff --git a/lib/recipe.rb b/lib/recipe.rb index 5e77a14c5..9e9843832 100644 --- a/lib/recipe.rb +++ b/lib/recipe.rb @@ -1,5 +1,5 @@ class Recipe - attr_reader :uri, :label, :image, :url + attr_reader :uri, :label, :image, :url, :ingredients, :dietLabels def initialize(hash) hash.each do |k,v| self.instance_variable_set("@#{k}", v) diff --git a/lib/recipe_search_api_wrapper.rb b/lib/recipe_search_api_wrapper.rb index ba2fec05a..5e513beba 100644 --- a/lib/recipe_search_api_wrapper.rb +++ b/lib/recipe_search_api_wrapper.rb @@ -32,7 +32,25 @@ def self.search(term, page) return { :recipes => recipes, :count => response['count'], - :more => response['more'], + :more => response['more'] } end + + def self.find(r) + encoded_url = URI.encode_www_form_component(r) + url = BASE_URL + "/search?" + "&app_id=#{APP_ID}" + "&app_key=#{APP_KEY}" + "&r=#{encoded_url}" + + puts url + + response = HTTParty.get(url) + if response == nil + return nil + end + + hit = response[0] + recipe = Recipe.new(hit) + return recipe + + end + end From 4771122339e692b2092e910789038aa83a038b1b Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Wed, 2 Nov 2016 14:50:13 -0700 Subject: [PATCH 14/43] show ingredients in table --- app/controllers/homepages_controller.rb | 2 ++ app/views/homepages/show.html.erb | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/controllers/homepages_controller.rb b/app/controllers/homepages_controller.rb index 05e2e19f1..dad58347c 100644 --- a/app/controllers/homepages_controller.rb +++ b/app/controllers/homepages_controller.rb @@ -16,5 +16,7 @@ def search def show @recipe_id= params[:uri] @recipe = RecipeSearchApiWrapper.find(@recipe_id) + @ingredients = @recipe.ingredients + @dietLabels = @recipe.dietLabels end end diff --git a/app/views/homepages/show.html.erb b/app/views/homepages/show.html.erb index 120251cd5..b7973e649 100644 --- a/app/views/homepages/show.html.erb +++ b/app/views/homepages/show.html.erb @@ -1,5 +1,19 @@

<%= @recipe.label %>

<%= image_tag "#{@recipe.image}", :class=>'recipe_photo' %> -

<%= @recipe.ingredients %>

-

<%= @recipe.dietLabels %>

+ + + + + + + + +<% @ingredients.each do |row| %> + <% row.values.each do |value| %> + + <% end %> +<% end %> +
TextQuantityMeasureWeight
<%= value %>
+ +

<%= link_to "Learn More", @recipe.url %>

From a56ba22ace86c50a64121adf07366f19ef878268 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Wed, 2 Nov 2016 15:04:46 -0700 Subject: [PATCH 15/43] show diet label --- app/controllers/homepages_controller.rb | 3 +++ app/views/homepages/show.html.erb | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/controllers/homepages_controller.rb b/app/controllers/homepages_controller.rb index dad58347c..a05829317 100644 --- a/app/controllers/homepages_controller.rb +++ b/app/controllers/homepages_controller.rb @@ -17,6 +17,9 @@ def show @recipe_id= params[:uri] @recipe = RecipeSearchApiWrapper.find(@recipe_id) @ingredients = @recipe.ingredients + + + @dietLabels = @recipe.dietLabels end end diff --git a/app/views/homepages/show.html.erb b/app/views/homepages/show.html.erb index b7973e649..f621ef9b0 100644 --- a/app/views/homepages/show.html.erb +++ b/app/views/homepages/show.html.erb @@ -1,9 +1,15 @@

<%= @recipe.label %>

<%= image_tag "#{@recipe.image}", :class=>'recipe_photo' %> +<% if @dietLabels != [] %> + <% @dietLabels.each do |label| %> + <%= label %> + <% end %> +<% end %> + - + @@ -15,5 +21,5 @@ <% end %>
TextIngredients Quantity Measure Weight
- +

<%= link_to "Learn More", @recipe.url %>

From 77f33382956d571a31bb0324b9cf6fea839cf9c8 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Wed, 2 Nov 2016 15:13:34 -0700 Subject: [PATCH 16/43] add home page button --- app/views/layouts/application.html.erb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 3360e304d..7a56086e5 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -9,6 +9,7 @@ + <%= link_to "HOME", root_path %> <%= yield %> From 9eaac5892bba3d6d578191da7d665c4486c41f8e Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Wed, 2 Nov 2016 15:23:23 -0700 Subject: [PATCH 17/43] add attribution to API in footer --- app/views/layouts/application.html.erb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 7a56086e5..b938c92b9 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -12,4 +12,8 @@ <%= link_to "HOME", root_path %> <%= yield %> + +
+

Powered by

+
From 19f48cb1cf7769034aea837c964482f2de8c95f3 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Wed, 2 Nov 2016 15:31:11 -0700 Subject: [PATCH 18/43] move home link to header --- app/views/layouts/application.html.erb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index b938c92b9..58994447d 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -8,8 +8,11 @@ <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> - +
<%= link_to "HOME", root_path %> +
+ + <%= yield %> From c07e6a307962a5db9b16a19e308ed2b6ee458c9f Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Thu, 3 Nov 2016 15:04:55 -0700 Subject: [PATCH 19/43] working on limit search, add checkbox for label search, draft m(api)vc logic for diet label sample and health label sample. Does not work yet. Switch to mw_show_view to add health label to show to make manuel test easier --- app/controllers/homepages_controller.rb | 21 ++++++++++++++++----- app/views/homepages/index.html.erb | 11 ++++++++++- lib/recipe.rb | 3 ++- lib/recipe_search_api_wrapper.rb | 22 +++++++++++++++++++++- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/app/controllers/homepages_controller.rb b/app/controllers/homepages_controller.rb index a05829317..3c9da9056 100644 --- a/app/controllers/homepages_controller.rb +++ b/app/controllers/homepages_controller.rb @@ -6,20 +6,31 @@ def search @term = params[:term] @page = params[:page] || 1 @page = @page.to_i - results = RecipeSearchApiWrapper.search(@term, @page) + + @health_labels = [] + if params[:is_peanut_free] == "1" + @health_labels << "peanut-free" + end + if params[:is_gluten_free] == "1" + @health_labels << "gluten-free" + end + + @diet_labels = [] + if params[:is_high_protein] == "1" + @health_labels << "high-protein" + end + + results = RecipeSearchApiWrapper.search(@term, @page, @health_labels, @diet_labels) @recipes = results[:recipes] @count = results[:count] @more = results[:more] - # puts "#{} #{results[:more]}" + end def show @recipe_id= params[:uri] @recipe = RecipeSearchApiWrapper.find(@recipe_id) @ingredients = @recipe.ingredients - - - @dietLabels = @recipe.dietLabels end end diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index b5d54919a..17f188ab4 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -1,8 +1,17 @@

Search Recipe

<%= form_tag search_path, method: "post" do %> - <%= label_tag :term, "Search" %> + <%= label_tag "Search" %> <%= text_field_tag :term %> +

<%= label_tag "Peanut Free" %> + <%= check_box_tag :is_peanut_free %>

+ +

<%= label_tag "High Protein" %> + <%= check_box_tag :is_high_protein %>

+ +

<%= label_tag "Gluten Free" %> + <%= check_box_tag :is_gluten_free %>

+ <%= submit_tag "Search", :class => "button" %> <% end %> diff --git a/lib/recipe.rb b/lib/recipe.rb index 9e9843832..290af9cd3 100644 --- a/lib/recipe.rb +++ b/lib/recipe.rb @@ -1,5 +1,6 @@ class Recipe - attr_reader :uri, :label, :image, :url, :ingredients, :dietLabels + attr_reader :uri, :label, :image, :url, :ingredients, :dietLabels, :healthlabels + def initialize(hash) hash.each do |k,v| self.instance_variable_set("@#{k}", v) diff --git a/lib/recipe_search_api_wrapper.rb b/lib/recipe_search_api_wrapper.rb index 5e513beba..970a14b5b 100644 --- a/lib/recipe_search_api_wrapper.rb +++ b/lib/recipe_search_api_wrapper.rb @@ -12,7 +12,7 @@ class RecipeSearchApiWrapper APP_KEY = "3e974f32b9b7c425a0a6e4bae6e5e131" PAGE_SIZE = 10 - def self.search(term, page) + def self.search(term, page, health_labels, diet_labels) page ||= 1 page = page.to_i @@ -22,6 +22,14 @@ def self.search(term, page) url = BASE_URL + "/search?" + "q=#{term}" + "&app_id=#{APP_ID}" + "&app_key=#{APP_KEY}" + "&from=#{from}&to=#{to}" + health_labels.each do |health_label| + url += "&Health=#{health_label}" + end + + diet_labels.each do |diet_label| + url += "&Diet=#{diet_label}" + end + response = HTTParty.get(url) recipes = [] @@ -53,4 +61,16 @@ def self.find(r) end + # value is a boolean + def self.is_peanut_free(value) + # if true, return all results that contains "peanut free" in healthlabels hash + if value + + + # if false, return nil + else + end + + end + end From e005ec7196c8daeacd8230e500a6378ebd7530a2 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Thu, 3 Nov 2016 15:15:00 -0700 Subject: [PATCH 20/43] add show health labels on show page --- app/controllers/homepages_controller.rb | 3 ++- app/views/homepages/show.html.erb | 10 ++++++++-- lib/recipe.rb | 4 ++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/controllers/homepages_controller.rb b/app/controllers/homepages_controller.rb index 3c9da9056..939f961df 100644 --- a/app/controllers/homepages_controller.rb +++ b/app/controllers/homepages_controller.rb @@ -31,6 +31,7 @@ def show @recipe_id= params[:uri] @recipe = RecipeSearchApiWrapper.find(@recipe_id) @ingredients = @recipe.ingredients - @dietLabels = @recipe.dietLabels + @diet_labels = @recipe.dietLabels + @health_labels = @recipe.healthLabels end end diff --git a/app/views/homepages/show.html.erb b/app/views/homepages/show.html.erb index f621ef9b0..9438b1289 100644 --- a/app/views/homepages/show.html.erb +++ b/app/views/homepages/show.html.erb @@ -1,8 +1,14 @@

<%= @recipe.label %>

<%= image_tag "#{@recipe.image}", :class=>'recipe_photo' %> -<% if @dietLabels != [] %> - <% @dietLabels.each do |label| %> +<% if @diet_labels != [] %> + <% @diet_labels.each do |label| %> + <%= label %> + <% end %> +<% end %> + +<% if @health_labels != [] %> + <% @health_labels.each do |label| %> <%= label %> <% end %> <% end %> diff --git a/lib/recipe.rb b/lib/recipe.rb index 290af9cd3..74ef2e327 100644 --- a/lib/recipe.rb +++ b/lib/recipe.rb @@ -1,6 +1,6 @@ class Recipe - attr_reader :uri, :label, :image, :url, :ingredients, :dietLabels, :healthlabels - + attr_reader :uri, :label, :image, :url, :ingredients, :dietLabels, :healthLabels + def initialize(hash) hash.each do |k,v| self.instance_variable_set("@#{k}", v) From 99734b104fcbfff8cae51cf4cc7edfed73f1b60c Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Thu, 3 Nov 2016 15:19:57 -0700 Subject: [PATCH 21/43] add recipe image link to show page --- app/views/homepages/search.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/homepages/search.html.erb b/app/views/homepages/search.html.erb index 1b0b23563..a2e00ddce 100644 --- a/app/views/homepages/search.html.erb +++ b/app/views/homepages/search.html.erb @@ -1,7 +1,7 @@

Search Result

<% @recipes.each do |recipe| %>

<%= recipe.label %>

- <%= image_tag "#{recipe.image}", :class=>'recipe_photo' %> + <%= link_to image_tag(recipe.image, :class=>'recipe_photo'), show_path(:uri => recipe.uri) %>

<%= link_to "Details", show_path(:uri => recipe.uri) %>

<% end %> From 771a8eef7d465408a94d951afadc70d1421a2121 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Thu, 3 Nov 2016 15:53:27 -0700 Subject: [PATCH 22/43] handle case when no result found, hits=[] --- lib/recipe_search_api_wrapper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/recipe_search_api_wrapper.rb b/lib/recipe_search_api_wrapper.rb index 970a14b5b..56a89ee8d 100644 --- a/lib/recipe_search_api_wrapper.rb +++ b/lib/recipe_search_api_wrapper.rb @@ -23,17 +23,17 @@ def self.search(term, page, health_labels, diet_labels) url = BASE_URL + "/search?" + "q=#{term}" + "&app_id=#{APP_ID}" + "&app_key=#{APP_KEY}" + "&from=#{from}&to=#{to}" health_labels.each do |health_label| - url += "&Health=#{health_label}" + url += "&health=#{health_label}" end diet_labels.each do |diet_label| - url += "&Diet=#{diet_label}" + url += "&diet=#{diet_label}" end response = HTTParty.get(url) recipes = [] - hits = response['hits'] + hits = response['hits'] || [] hits.each do |hit| recipes << Recipe.new(hit['recipe']) end From 619605fc8cc907bd9bdb0aa743e0f6bfedbab218 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Thu, 3 Nov 2016 15:53:27 -0700 Subject: [PATCH 23/43] complete limit search by label checkbox feature. handle case when no result found, hits=[] --- lib/recipe_search_api_wrapper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/recipe_search_api_wrapper.rb b/lib/recipe_search_api_wrapper.rb index 970a14b5b..56a89ee8d 100644 --- a/lib/recipe_search_api_wrapper.rb +++ b/lib/recipe_search_api_wrapper.rb @@ -23,17 +23,17 @@ def self.search(term, page, health_labels, diet_labels) url = BASE_URL + "/search?" + "q=#{term}" + "&app_id=#{APP_ID}" + "&app_key=#{APP_KEY}" + "&from=#{from}&to=#{to}" health_labels.each do |health_label| - url += "&Health=#{health_label}" + url += "&health=#{health_label}" end diet_labels.each do |diet_label| - url += "&Diet=#{diet_label}" + url += "&diet=#{diet_label}" end response = HTTParty.get(url) recipes = [] - hits = response['hits'] + hits = response['hits'] || [] hits.each do |hit| recipes << Recipe.new(hit['recipe']) end From eb653ff5dfe37f2a97856abe05a99c9811d496fc Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Thu, 3 Nov 2016 16:53:25 -0700 Subject: [PATCH 24/43] added vcr testing gem in Gemfile --- Gemfile | 5 ++++- Gemfile.lock | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 9d34a21dc..98ad1aa3f 100644 --- a/Gemfile +++ b/Gemfile @@ -39,6 +39,10 @@ gem 'jbuilder', '~> 2.5' group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platform: :mri + gem 'dotenv-rails' + gem 'better_errors' + gem 'minitest-vcr' + gem 'webmock' end group :development do @@ -48,7 +52,6 @@ group :development do # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' - gem "better_errors" end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem diff --git a/Gemfile.lock b/Gemfile.lock index 6a119c8e9..d7e4fb98d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -38,6 +38,7 @@ GEM i18n (~> 0.7) minitest (~> 5.1) tzinfo (~> 1.1) + addressable (2.4.0) arel (7.1.4) awesome_print (1.7.0) babel-source (5.8.35) @@ -61,7 +62,13 @@ GEM execjs coffee-script-source (1.10.0) concurrent-ruby (1.0.2) + crack (0.4.3) + safe_yaml (~> 1.0.0) 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) ffi (1.9.14) @@ -71,6 +78,7 @@ GEM sprockets-es6 (>= 0.9.0) globalid (0.3.7) activesupport (>= 4.1.0) + hashdiff (0.3.0) httparty (0.14.0) multi_xml (>= 0.5.2) i18n (0.7.0) @@ -93,7 +101,13 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) mini_portile2 (2.1.0) + minispec-metadata (2.0.0) + minitest minitest (5.9.1) + minitest-vcr (1.4.0) + minispec-metadata (~> 2.0) + minitest (>= 4.7.5) + vcr (>= 2.9) multi_json (1.12.1) multi_xml (0.5.5) nio4r (1.2.1) @@ -130,6 +144,7 @@ GEM rb-fsevent (0.9.8) rb-inotify (0.9.7) ffi (>= 0.5.0) + safe_yaml (1.0.4) sass (3.4.22) sass-rails (5.0.6) railties (>= 4.0.0, < 6) @@ -164,11 +179,16 @@ GEM thread_safe (~> 0.1) uglifier (3.0.3) execjs (>= 0.3.0, < 3) + vcr (3.0.3) web-console (3.4.0) actionview (>= 5.0) activemodel (>= 5.0) debug_inspector railties (>= 5.0) + webmock (2.1.0) + addressable (>= 2.3.6) + crack (>= 0.3.2) + hashdiff websocket-driver (0.6.4) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.2) @@ -182,11 +202,13 @@ DEPENDENCIES binding_of_caller byebug coffee-rails (~> 4.2) + dotenv-rails foundation-rails httparty jbuilder (~> 2.5) jquery-rails listen (~> 3.0.5) + minitest-vcr puma (~> 3.0) rails (~> 5.0.0, >= 5.0.0.1) sass-rails (~> 5.0) @@ -197,6 +219,7 @@ DEPENDENCIES tzinfo-data uglifier (>= 1.3.0) web-console + webmock BUNDLED WITH 1.13.6 From 68e10ae17b42ab180e4fef7f2bdc37673dafd4b8 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Thu, 3 Nov 2016 16:54:36 -0700 Subject: [PATCH 25/43] add require in test_helper --- test/test_helper.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test_helper.rb b/test/test_helper.rb index 92e39b2d7..d7d10b5c2 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,3 +1,6 @@ +require 'vcr' +require 'webmock/minitest' + ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../../config/environment', __FILE__) require 'rails/test_help' From d3353a7f17fdad2677efdc4ebb79e09e4c54946a Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Thu, 3 Nov 2016 16:55:50 -0700 Subject: [PATCH 26/43] change require position in test_helper --- test/test_helper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index d7d10b5c2..67e31d3c7 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,9 +1,9 @@ -require 'vcr' -require 'webmock/minitest' - ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../../config/environment', __FILE__) require 'rails/test_help' +require 'vcr' +require 'webmock/minitest' + class ActiveSupport::TestCase # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. From 69f1eb66b7f52536e6a85b1525e5e3f9402ca3c8 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Fri, 4 Nov 2016 10:21:51 -0700 Subject: [PATCH 27/43] add column styling to search result. add back to list button on show page(need backend functionde improve). Dlete import app.css --- app/assets/stylesheets/application.css | 1 - app/views/homepages/search.html.erb | 8 +++++--- app/views/homepages/show.html.erb | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 5ba3617bc..6637a058d 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -14,4 +14,3 @@ *= require_self */ @import url('foundation.css'); -@import url('app.css'); diff --git a/app/views/homepages/search.html.erb b/app/views/homepages/search.html.erb index a2e00ddce..fd84413c1 100644 --- a/app/views/homepages/search.html.erb +++ b/app/views/homepages/search.html.erb @@ -1,8 +1,10 @@

Search Result

<% @recipes.each do |recipe| %> -

<%= recipe.label %>

- <%= link_to image_tag(recipe.image, :class=>'recipe_photo'), show_path(:uri => recipe.uri) %> -

<%= link_to "Details", show_path(:uri => recipe.uri) %>

+
+ <%= link_to image_tag(recipe.image, :class=>'recipe_photo'), show_path(:uri => recipe.uri) %> +

<%= recipe.label %>

+
+ <% end %> <%= render :partial => 'pagination', :locals => { diff --git a/app/views/homepages/show.html.erb b/app/views/homepages/show.html.erb index 9438b1289..69bd461b7 100644 --- a/app/views/homepages/show.html.erb +++ b/app/views/homepages/show.html.erb @@ -29,3 +29,4 @@

<%= link_to "Learn More", @recipe.url %>

+

<%= link_to "Back to List", search_path, :class => 'button' %>

From 0a173c6b677fbacb762366bf8d165e5802d5cd29 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Fri, 4 Nov 2016 13:18:05 -0700 Subject: [PATCH 28/43] add foundation pagination styling --- app/views/homepages/_pagination.html.erb | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/app/views/homepages/_pagination.html.erb b/app/views/homepages/_pagination.html.erb index 90bb3aa72..c6230eb2c 100644 --- a/app/views/homepages/_pagination.html.erb +++ b/app/views/homepages/_pagination.html.erb @@ -1,9 +1,14 @@ -<% last_page = @page + 3 %> -<% if @count == 0 %> -<% last_page = @page %> -<% end %> +<%# last_page = @page + 5 %> +<%# if @count == 0 %> +<%# last_page = @page %> +<%# end %> -<% for i in ([@page-5, 1].max)...last_page %> - <%= link_to "#{i} |", get_search_path(:page => i, :term => term) %> -<% end %> +<%# for i in 1..last_page %> + + + From 7734f3f28b2331fbf697f53ffc045e3c2a94a6f8 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Fri, 4 Nov 2016 15:06:15 -0700 Subject: [PATCH 29/43] setup header and go to back button on show page --- app/assets/stylesheets/application.css | 33 ++++++++++++++++++++++++ app/views/homepages/_pagination.html.erb | 9 ++++--- app/views/homepages/index.html.erb | 17 ++++++++---- app/views/homepages/search.html.erb | 2 +- app/views/homepages/show.html.erb | 9 ++++++- app/views/layouts/application.html.erb | 12 +++++---- lib/recipe_search_api_wrapper.rb | 2 +- 7 files changed, 67 insertions(+), 17 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 6637a058d..1adb8672f 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -14,3 +14,36 @@ *= require_self */ @import url('foundation.css'); + +/*===========header & footer=============*/ +.header_box{ + border-bottom: 1px solid lightgrey; + text-align: center; + opacity: 0.9; +} + +.header_text{ + font-family:"Dancing Script"; + font-weight: bold; +} + +.footer{ + text-align: right; +} + +/*===========Index Page=============*/ + +.search_bar{ + position:relative; + left: 30%; +} + +.search_button{ + width: 10%; + +} + +/*===========Search(Result) Page=============*/ + + +/*===========Show Page=============*/ diff --git a/app/views/homepages/_pagination.html.erb b/app/views/homepages/_pagination.html.erb index c6230eb2c..0cc2d5d82 100644 --- a/app/views/homepages/_pagination.html.erb +++ b/app/views/homepages/_pagination.html.erb @@ -1,14 +1,15 @@ + + <%# last_page = @page + 5 %> <%# if @count == 0 %> <%# last_page = @page %> <%# end %> - <%# for i in 1..last_page %> - + diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index 17f188ab4..2042fb08c 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -1,8 +1,15 @@ -

Search Recipe

- <%= form_tag search_path, method: "post" do %> - <%= label_tag "Search" %> - <%= text_field_tag :term %> + + + +
+ <%= submit_tag "Search", :class => "button" %> +

<%= label_tag "Peanut Free" %> <%= check_box_tag :is_peanut_free %>

@@ -13,5 +20,5 @@

<%= label_tag "Gluten Free" %> <%= check_box_tag :is_gluten_free %>

- <%= submit_tag "Search", :class => "button" %> + <% end %> diff --git a/app/views/homepages/search.html.erb b/app/views/homepages/search.html.erb index fd84413c1..e8de2244b 100644 --- a/app/views/homepages/search.html.erb +++ b/app/views/homepages/search.html.erb @@ -1,4 +1,4 @@ -

Search Result

+ <% @recipes.each do |recipe| %>
<%= link_to image_tag(recipe.image, :class=>'recipe_photo'), show_path(:uri => recipe.uri) %> diff --git a/app/views/homepages/show.html.erb b/app/views/homepages/show.html.erb index 69bd461b7..7bd6ec083 100644 --- a/app/views/homepages/show.html.erb +++ b/app/views/homepages/show.html.erb @@ -29,4 +29,11 @@

<%= link_to "Learn More", @recipe.url %>

-

<%= link_to "Back to List", search_path, :class => 'button' %>

+ + + + diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 58994447d..effb789c5 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -4,19 +4,21 @@ ApiMuncher <%= csrf_meta_tags %> - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> + -
- <%= link_to "HOME", root_path %> +
+

<%= link_to "Muncher", root_path, :class => "header_text" %>

+
- + <%= yield %> -
+

Powered by

diff --git a/lib/recipe_search_api_wrapper.rb b/lib/recipe_search_api_wrapper.rb index 56a89ee8d..7175ec88c 100644 --- a/lib/recipe_search_api_wrapper.rb +++ b/lib/recipe_search_api_wrapper.rb @@ -10,7 +10,7 @@ class RecipeSearchApiWrapper BASE_URL = "https://api.edamam.com" APP_ID = "f8c6af19" APP_KEY = "3e974f32b9b7c425a0a6e4bae6e5e131" - PAGE_SIZE = 10 + PAGE_SIZE = 9 def self.search(term, page, health_labels, diet_labels) page ||= 1 From 254a8ac6f8d7965d4a80e619dd0c3d1ce091c9c7 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Fri, 4 Nov 2016 15:54:47 -0700 Subject: [PATCH 30/43] set up attribution link in footer --- app/assets/stylesheets/application.css | 12 ++++++++++-- app/views/homepages/index.html.erb | 4 +++- app/views/homepages/search.html.erb | 2 +- app/views/layouts/application.html.erb | 4 ++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 1adb8672f..1a4359eab 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -20,6 +20,7 @@ border-bottom: 1px solid lightgrey; text-align: center; opacity: 0.9; + /*background-color: black;*/ } .header_text{ @@ -27,6 +28,10 @@ font-weight: bold; } +.body{ + background-image: url(); +} + .footer{ text-align: right; } @@ -34,13 +39,16 @@ /*===========Index Page=============*/ .search_bar{ + margin-top: 10%; position:relative; - left: 30%; + left: 20%; } .search_button{ width: 10%; - + position: relative; + top: -3.5rem; + left: 70%; } /*===========Search(Result) Page=============*/ diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index 2042fb08c..3772ee7b3 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -1,7 +1,7 @@ <%= form_tag search_path, method: "post" do %>
- + <%= yield %>
-

Powered by

+ Powered By <%= link_to image_tag("https://www.edamam.com/images/logo-site-header.png"), "https://developer.edamam.com/" %>
From b4711023e799c0d83e7e117ae98ab18108e11773 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Sun, 6 Nov 2016 22:30:05 -0800 Subject: [PATCH 31/43] completed css design and styling on index, search result and show pages --- app/assets/stylesheets/application.css | 76 +++++++++++++++++++++++--- app/views/homepages/index.html.erb | 38 +++++++------ app/views/homepages/search.html.erb | 26 +++++---- app/views/homepages/show.html.erb | 74 +++++++++++++------------ app/views/layouts/application.html.erb | 14 +++-- 5 files changed, 150 insertions(+), 78 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 1a4359eab..9ac2a7894 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -17,41 +17,99 @@ /*===========header & footer=============*/ .header_box{ - border-bottom: 1px solid lightgrey; text-align: center; - opacity: 0.9; - /*background-color: black;*/ + opacity: 0.6; + width: 100%; + border-bottom: 1px solid lightgrey; + padding-top: 1%; + padding-bottom: 1%; + background-color: white; } .header_text{ font-family:"Dancing Script"; font-weight: bold; + color: #E15554; } -.body{ - background-image: url(); +.sub_header{ + font-family:"PT Sans"; + font-weight: bold; } .footer{ text-align: right; + font-family: "PT Sans"; + font-size: 1.2rem; + color: grey; + margin-right: 3%; +} +.api_logo{ + width: 6%; + height: 4%; } - /*===========Index Page=============*/ +.home_body{ + background-color: white; + background-image: url("https://s-media-cache-ak0.pinimg.com/originals/26/ba/c3/26bac33e1f8d5105db0000cef734fec3.jpg"); + background-repeat: no-repeat; + background-size: cover; +} + +.search_label{ + font-family: "Anton"; + font-size: 3rem; + color: #E15554; + margin-left: 28%; + margin-bottom: 10%; + text-transform:uppercase; +} .search_bar{ - margin-top: 10%; + margin-top: 5%; position:relative; - left: 20%; + left: 25%; + opacity: 0.8; } .search_button{ width: 10%; position: relative; top: -3.5rem; - left: 70%; + left: 75%; + opacity: 0.8; } /*===========Search(Result) Page=============*/ +.page_body{ + background-color: white; + margin-top: 5%; +} +.recipe_box{ + box-shadow: 10px 10px 10px #888888; + background-color: white; + text-align: center; +} +.recipe_photo{ + padding-top: 5%; +} /*===========Show Page=============*/ +.recipe_title{ + font-family: "Anton"; + text-transform:uppercase; + color: #E15554; + text-align: center; +} +.show_photo{ + width: 100%; + padding-left: 30%; + padding-right: 30%; +} +.label{ + position:relative;; + left: 30%; + margin-top: 5%; + margin-bottom: 5%; +} diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index 3772ee7b3..3a2a70899 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -1,26 +1,28 @@ -<%= form_tag search_path, method: "post" do %> + + <%= form_tag search_path, method: "post" do %> - -
-

<%= label_tag "Peanut Free" %> - <%= check_box_tag :is_peanut_free %>

+
+
+ -

<%= label_tag "High Protein" %> - <%= check_box_tag :is_high_protein %>

+ -

<%= label_tag "Gluten Free" %> - <%= check_box_tag :is_gluten_free %>

-
+ + + + + + +
<% end %> diff --git a/app/views/homepages/show.html.erb b/app/views/homepages/show.html.erb index 4d1815b75..e2d2e7747 100644 --- a/app/views/homepages/show.html.erb +++ b/app/views/homepages/show.html.erb @@ -1,4 +1,4 @@ - +

<%= @recipe.label %>

<%= image_tag "#{@recipe.image}", :class=>'show_photo'%> @@ -9,11 +9,13 @@ <% end %> <% end %> - <% if @health_labels != [] %> - <% @health_labels.each do |label| %> - <%= label %> +
+ <% if @health_labels != [] %> + <% @health_labels.each do |label| %> + <%= label %> + <% end %> <% end %> - <% end %> +
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 85170754d..a98747c6f 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -23,6 +23,6 @@
- Powered By <%= link_to image_tag("https://www.edamam.com/images/logo-site-header.png", :class => "api_logo"), "https://developer.edamam.com/" %> + Powered By <%= link_to image_tag("https://www.edamam.com/images/logo-site-header.png", :class => "api_logo"), "https://developer.edamam.com/" %>
diff --git a/lib/recipe_search_api_wrapper.rb b/lib/recipe_search_api_wrapper.rb index 7175ec88c..c435b31b6 100644 --- a/lib/recipe_search_api_wrapper.rb +++ b/lib/recipe_search_api_wrapper.rb @@ -61,16 +61,4 @@ def self.find(r) end - # value is a boolean - def self.is_peanut_free(value) - # if true, return all results that contains "peanut free" in healthlabels hash - if value - - - # if false, return nil - else - end - - end - end From 04d14972614f3f6942ed34389d45da6fe72d4b93 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 7 Nov 2016 00:21:44 -0800 Subject: [PATCH 33/43] changed indentation --- app/views/homepages/index.html.erb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index bc2f07390..bee2c30f3 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -8,9 +8,9 @@ -
- <%= submit_tag "Search", :class => "button" %> -
+
+ <%= submit_tag "Search", :class => "button" %> +
From 2e9d261ed4169c91e9efd63f2b13f3d7c0a8b043 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 7 Nov 2016 01:08:55 -0800 Subject: [PATCH 34/43] Updated Gemfile for Heroku --- Gemfile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index 98ad1aa3f..ece6b9d16 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,8 @@ source 'https://rubygems.org' gem "binding_of_caller" +gem 'pg', group: :production +gem 'rails_12factor', group: :production # API GEMS gem 'httparty' @@ -9,8 +11,7 @@ gem 'awesome_print' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.0.0', '>= 5.0.0.1' -# Use sqlite3 as the database for Active Record -gem 'sqlite3' + # Use Puma as the app server gem 'puma', '~> 3.0' # Use SCSS for stylesheets @@ -43,6 +44,8 @@ group :development, :test do gem 'better_errors' gem 'minitest-vcr' gem 'webmock' + # Use sqlite3 as the database for Active Record + gem 'sqlite3' end group :development do From c475b4270408316de17444475f97a9cf0fbd33d5 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 7 Nov 2016 01:18:43 -0800 Subject: [PATCH 35/43] add APP_ID and APP_KEY into env --- .gitignore | 3 +++ Gemfile.lock | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/.gitignore b/.gitignore index bab620de0..1704bc3c4 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ # Ignore Byebug command history file. .byebug_history + +# Ignore ENV full of secrets +.env diff --git a/Gemfile.lock b/Gemfile.lock index d7e4fb98d..f554ea59e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -113,6 +113,7 @@ GEM nio4r (1.2.1) nokogiri (1.6.8.1) mini_portile2 (~> 2.1.0) + pg (0.19.0) puma (3.6.0) rack (2.0.1) rack-test (0.6.3) @@ -134,6 +135,11 @@ GEM nokogiri (~> 1.6.0) 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 (5.0.0.1) actionpack (= 5.0.0.1) activesupport (= 5.0.0.1) @@ -209,8 +215,10 @@ DEPENDENCIES jquery-rails listen (~> 3.0.5) minitest-vcr + pg puma (~> 3.0) rails (~> 5.0.0, >= 5.0.0.1) + rails_12factor sass-rails (~> 5.0) spring spring-watcher-listen (~> 2.0.0) From 8f4f4c2e693c4812efd7559bd53c8fdb9095fc51 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 7 Nov 2016 01:36:26 -0800 Subject: [PATCH 36/43] comment out squilte --- Gemfile | 2 +- Gemfile.lock | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index ece6b9d16..f3dd35163 100644 --- a/Gemfile +++ b/Gemfile @@ -45,7 +45,7 @@ group :development, :test do gem 'minitest-vcr' gem 'webmock' # Use sqlite3 as the database for Active Record - gem 'sqlite3' + # gem 'sqlite3' end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index f554ea59e..35aea5d7c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -174,7 +174,6 @@ GEM actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - sqlite3 (1.3.12) thor (0.19.1) thread_safe (0.3.5) tilt (2.0.5) @@ -222,7 +221,6 @@ DEPENDENCIES sass-rails (~> 5.0) spring spring-watcher-listen (~> 2.0.0) - sqlite3 turbolinks (~> 5) tzinfo-data uglifier (>= 1.3.0) From 850a61384e560573efc00fd02a9c8dadc7bb6eef Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 7 Nov 2016 01:48:01 -0800 Subject: [PATCH 37/43] set config.autoload_path in production --- config/environments/production.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/environments/production.rb b/config/environments/production.rb index 2a3bd799e..8190203b9 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -83,4 +83,6 @@ # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false + + config.autoload_paths << Rails.root.join('lib') end From f04a627854616c320250308518e40c0dbcc56f6a Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 7 Nov 2016 02:11:27 -0800 Subject: [PATCH 38/43] add require in controller --- app/controllers/homepages_controller.rb | 1 + config/environments/production.rb | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/homepages_controller.rb b/app/controllers/homepages_controller.rb index 8be93491c..12873de8c 100644 --- a/app/controllers/homepages_controller.rb +++ b/app/controllers/homepages_controller.rb @@ -1,3 +1,4 @@ +require 'recipe_search_api_wrapper' class HomepagesController < ApplicationController def index end diff --git a/config/environments/production.rb b/config/environments/production.rb index 8190203b9..2a3bd799e 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -83,6 +83,4 @@ # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false - - config.autoload_paths << Rails.root.join('lib') end From 716bfceccd2a7256e478017ed7c203c2d0d897bd Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 7 Nov 2016 02:14:17 -0800 Subject: [PATCH 39/43] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index afd643dd4..f12d0bf1f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +Heroku Live: https://otter-muncher.herokuapp.com/ + # Recipe API Consumer ## Learning Goals: From 16e7d44ed574c6ac45d91304f5b7ca61cba5eb59 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 7 Nov 2016 09:30:11 -0800 Subject: [PATCH 40/43] Update README.md --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index f12d0bf1f..6d815320a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,33 @@ Heroku Live: https://otter-muncher.herokuapp.com/ +# Reflection" + +- What do you understand better after doing this project? + - I learnt more about applying API to website, especially understanding on query parameters, and how this connects to our previous learning of model and database. + - completed all search, search result and show features using API + - filter search feature by health label and diet label using checkbox + - manually coded pagination feature without use gem + - Can show a 'sliding' pagination bar for previous 5 and next 5 pages to handle 1000+ results if needed. Knowing our developer account can only return a limited number of 100 recipes, I commented out this part for better user experience. + - When implement the +5 and -5 pagination bar, it is hard to stop pagination without reaching the last page because the API does not return a finite number for search result(1000 and more). + - I will try to implement pagination gem next time as it seems to handle better on the above described last page pagination situation + - change return recipe result to 9 per page for better display(which can be easily changed to any number in PAGE_SIZE in api wrapper). + - added API attribution in footer + - foundation framework: responsive, pagination, label, table, checkbox, go back button, sea otter theme design. + + +- What do you want more practice with? + - I need to practice more on: api and controller tesing, try more complex foundation grid(e.g. 5 recipes in a row), try pagination gem, and try Google Auth next time. + - Did not attempt Google OAuth and save favorite feature this time due to time constrain. I did briefly think about how to implement these features. + - Google OAuth: will be similar to Github OAuth. will be nice to go through it if has the opportunity. + - Save favorites: create user and favorites model. model relation: User has many favorites. I can save and access user & favorites by sessions[user_id]. + + - under construction: testing on API and controller. I will update and merge my testing branch later. + + +- What is something you saw done differently? +My deskmate Jessica did great job on making the search bar available across pages, which definitely increases user experience. She also implemented api pigination gem for pages which I did not try this time. Her website also has very nice details like hover on recipe will change the recipe background color, etc. + + # Recipe API Consumer ## Learning Goals: From bd5da5081e31b4f634f8f6674f1e48ccaf8569a5 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 7 Nov 2016 09:30:30 -0800 Subject: [PATCH 41/43] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6d815320a..5329799ff 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Heroku Live: https://otter-muncher.herokuapp.com/ -# Reflection" +# Reflection - What do you understand better after doing this project? - I learnt more about applying API to website, especially understanding on query parameters, and how this connects to our previous learning of model and database. From 8661a113e4b5af4bfbdf70f2b5fce3f8de2c9178 Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 7 Nov 2016 09:31:04 -0800 Subject: [PATCH 42/43] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5329799ff..5cf21dea4 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Heroku Live: https://otter-muncher.herokuapp.com/ - What do you want more practice with? - - I need to practice more on: api and controller tesing, try more complex foundation grid(e.g. 5 recipes in a row), try pagination gem, and try Google Auth next time. + - I need to practice more on: API and controller tesing, try more complex foundation grid(e.g. 5 recipes in a row), try pagination gem, and try Google Auth next time. - Did not attempt Google OAuth and save favorite feature this time due to time constrain. I did briefly think about how to implement these features. - Google OAuth: will be similar to Github OAuth. will be nice to go through it if has the opportunity. - Save favorites: create user and favorites model. model relation: User has many favorites. I can save and access user & favorites by sessions[user_id]. From bad512bdca38b444dd9e8f80d556ced00fcd3d5e Mon Sep 17 00:00:00 2001 From: Maya Wang Date: Mon, 7 Nov 2016 09:31:54 -0800 Subject: [PATCH 43/43] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5cf21dea4..581f5cb99 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Heroku Live: https://otter-muncher.herokuapp.com/ # Reflection - What do you understand better after doing this project? - - I learnt more about applying API to website, especially understanding on query parameters, and how this connects to our previous learning of model and database. + - I learnt more about applying API to website, especially understanding on query parameters, and how this connects to our previous learning of model and database: - completed all search, search result and show features using API - filter search feature by health label and diet label using checkbox - manually coded pagination feature without use gem @@ -16,8 +16,8 @@ Heroku Live: https://otter-muncher.herokuapp.com/ - What do you want more practice with? - - I need to practice more on: API and controller tesing, try more complex foundation grid(e.g. 5 recipes in a row), try pagination gem, and try Google Auth next time. - - Did not attempt Google OAuth and save favorite feature this time due to time constrain. I did briefly think about how to implement these features. + - I need to practice more on: API and controller tesing, try more complex foundation grid(e.g. 5 recipes in a row), try pagination gem, and try Google Auth next time: + - I did not attempt Google OAuth and save favorite feature this time due to time constrain. I did briefly think about how to implement these features. - Google OAuth: will be similar to Github OAuth. will be nice to go through it if has the opportunity. - Save favorites: create user and favorites model. model relation: User has many favorites. I can save and access user & favorites by sessions[user_id].