<%= link_to product.name, product_path(product.id) %>
+-
+
- Price: $<%= product.price %> +
- Number Available: <%= product.items.where(purchase_status:false).count %> +
diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000000..44f98a42bc
Binary files /dev/null and b/.DS_Store differ
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..0533f6352f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,30 @@
+# 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'
+
+.env
+/coverage
+
+# Ignore bundler config.
+/.bundle
+
+
+# Ignore all logfiles and tempfiles.
+/log/*
+/tmp/*
+!/log/.keep
+!/tmp/.keep
+
+/node_modules
+/yarn-error.log
+/coverage
+
+/coverage
+
+.byebug_history
+
+.env
+
+public/assets/**
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000000..52f7545eb5
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,76 @@
+source 'https://rubygems.org'
+
+git_source(:github) do |repo_name|
+ repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
+ "https://github.com/#{repo_name}.git"
+end
+
+gem 'awesome_print'
+gem "omniauth"
+gem "omniauth-github"
+gem 'jquery-rails'
+
+# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
+gem 'rails', '~> 5.1.4'
+# Use postgresql as the database for Active Record
+gem 'pg', '~> 0.18'
+# Use Puma as the app server
+gem 'puma', '~> 3.7'
+# Use SCSS for stylesheets
+gem 'sass-rails', '~> 5.0'
+# Use Uglifier as compressor for JavaScript assets
+gem 'uglifier', '>= 1.3.0'
+# See https://github.com/rails/execjs#readme for more supported runtimes
+# gem 'therubyracer', platforms: :ruby
+
+# Use CoffeeScript for .coffee assets and views
+# gem 'coffee-rails', '~> 4.2'
+# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
+gem 'jquery-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'
+gem 'foundation-rails', '6.4.1.2'
+
+
+# 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', platforms: [:mri, :mingw, :x64_mingw]
+ # Adds support for Capybara system testing and selenium driver
+ gem 'capybara', '~> 2.13'
+ gem 'selenium-webdriver'
+ gem 'pry-rails'
+ gem 'dotenv-rails'
+ gem 'simplecov'
+end
+
+group :development do
+ # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
+ gem 'web-console', '>= 3.3.0'
+ gem 'listen', '>= 3.0.5', '< 3.2'
+ # 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'
+end
+
+# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
+gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
+
+gem 'jquery-turbolinks'
+group :development do
+ gem 'better_errors'
+
+ gem 'binding_of_caller'
+end
+
+group :test do
+ gem 'minitest-rails'
+ gem 'minitest-reporters'
+end
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000000..9b0d888b7f
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,275 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ actioncable (5.1.4)
+ actionpack (= 5.1.4)
+ nio4r (~> 2.0)
+ websocket-driver (~> 0.6.1)
+ actionmailer (5.1.4)
+ actionpack (= 5.1.4)
+ actionview (= 5.1.4)
+ activejob (= 5.1.4)
+ mail (~> 2.5, >= 2.5.4)
+ rails-dom-testing (~> 2.0)
+ actionpack (5.1.4)
+ actionview (= 5.1.4)
+ activesupport (= 5.1.4)
+ rack (~> 2.0)
+ rack-test (>= 0.6.3)
+ rails-dom-testing (~> 2.0)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ actionview (5.1.4)
+ activesupport (= 5.1.4)
+ builder (~> 3.1)
+ erubi (~> 1.4)
+ rails-dom-testing (~> 2.0)
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
+ activejob (5.1.4)
+ activesupport (= 5.1.4)
+ globalid (>= 0.3.6)
+ activemodel (5.1.4)
+ activesupport (= 5.1.4)
+ activerecord (5.1.4)
+ activemodel (= 5.1.4)
+ activesupport (= 5.1.4)
+ arel (~> 8.0)
+ activesupport (5.1.4)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (~> 0.7)
+ minitest (~> 5.1)
+ tzinfo (~> 1.1)
+ addressable (2.5.2)
+ public_suffix (>= 2.0.2, < 4.0)
+ ansi (1.5.0)
+ arel (8.0.0)
+ awesome_print (1.8.0)
+ babel-source (5.8.35)
+ babel-transpiler (0.7.0)
+ babel-source (>= 4.0, < 6)
+ execjs (~> 2.0)
+ better_errors (2.4.0)
+ coderay (>= 1.0.0)
+ erubi (>= 1.0.0)
+ rack (>= 0.9.0)
+ bindex (0.5.0)
+ binding_of_caller (0.7.2)
+ debug_inspector (>= 0.0.1)
+ builder (3.2.3)
+ byebug (9.1.0)
+ capybara (2.15.4)
+ addressable
+ mini_mime (>= 0.1.3)
+ nokogiri (>= 1.3.3)
+ rack (>= 1.0.0)
+ rack-test (>= 0.5.4)
+ xpath (~> 2.0)
+ childprocess (0.8.0)
+ ffi (~> 1.0, >= 1.0.11)
+ coderay (1.1.2)
+ concurrent-ruby (1.0.5)
+ crass (1.0.2)
+ debug_inspector (0.0.3)
+ docile (1.1.5)
+ dotenv (2.2.1)
+ dotenv-rails (2.2.1)
+ dotenv (= 2.2.1)
+ railties (>= 3.2, < 5.2)
+ erubi (1.7.0)
+ execjs (2.7.0)
+ faraday (0.12.2)
+ multipart-post (>= 1.2, < 3)
+ ffi (1.9.18)
+ foundation-rails (6.4.1.2)
+ railties (>= 3.1.0)
+ sass (>= 3.3.0, < 3.5)
+ sprockets-es6 (>= 0.9.0)
+ globalid (0.4.0)
+ activesupport (>= 4.2.0)
+ hashie (3.5.6)
+ i18n (0.9.0)
+ concurrent-ruby (~> 1.0)
+ jbuilder (2.7.0)
+ activesupport (>= 4.2.0)
+ multi_json (>= 1.2)
+ jquery-rails (4.3.1)
+ rails-dom-testing (>= 1, < 3)
+ railties (>= 4.2.0)
+ thor (>= 0.14, < 2.0)
+ jquery-turbolinks (2.1.0)
+ railties (>= 3.1.0)
+ turbolinks
+ json (2.0.2)
+ jwt (1.5.6)
+ listen (3.1.5)
+ rb-fsevent (~> 0.9, >= 0.9.4)
+ rb-inotify (~> 0.9, >= 0.9.7)
+ ruby_dep (~> 1.2)
+ loofah (2.1.1)
+ crass (~> 1.0.2)
+ nokogiri (>= 1.5.9)
+ mail (2.6.6)
+ mime-types (>= 1.16, < 4)
+ method_source (0.9.0)
+ mime-types (3.1)
+ mime-types-data (~> 3.2015)
+ mime-types-data (3.2016.0521)
+ mini_mime (0.1.4)
+ mini_portile2 (2.3.0)
+ minitest (5.10.3)
+ minitest-rails (3.0.0)
+ minitest (~> 5.8)
+ railties (~> 5.0)
+ minitest-reporters (1.1.18)
+ ansi
+ builder
+ minitest (>= 5.0)
+ ruby-progressbar
+ multi_json (1.12.2)
+ multi_xml (0.6.0)
+ multipart-post (2.0.0)
+ nio4r (2.1.0)
+ nokogiri (1.8.1)
+ mini_portile2 (~> 2.3.0)
+ oauth2 (1.4.0)
+ faraday (>= 0.8, < 0.13)
+ jwt (~> 1.0)
+ multi_json (~> 1.3)
+ multi_xml (~> 0.5)
+ rack (>= 1.2, < 3)
+ omniauth (1.7.1)
+ hashie (>= 3.4.6, < 3.6.0)
+ rack (>= 1.6.2, < 3)
+ omniauth-github (1.3.0)
+ omniauth (~> 1.5)
+ omniauth-oauth2 (>= 1.4.0, < 2.0)
+ omniauth-oauth2 (1.4.0)
+ oauth2 (~> 1.0)
+ omniauth (~> 1.2)
+ pg (0.21.0)
+ pry (0.11.2)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ pry-rails (0.3.6)
+ pry (>= 0.10.4)
+ public_suffix (3.0.0)
+ puma (3.10.0)
+ rack (2.0.3)
+ rack-test (0.7.0)
+ rack (>= 1.0, < 3)
+ rails (5.1.4)
+ actioncable (= 5.1.4)
+ actionmailer (= 5.1.4)
+ actionpack (= 5.1.4)
+ actionview (= 5.1.4)
+ activejob (= 5.1.4)
+ activemodel (= 5.1.4)
+ activerecord (= 5.1.4)
+ activesupport (= 5.1.4)
+ bundler (>= 1.3.0)
+ railties (= 5.1.4)
+ sprockets-rails (>= 2.0.0)
+ rails-dom-testing (2.0.3)
+ activesupport (>= 4.2.0)
+ nokogiri (>= 1.6)
+ rails-html-sanitizer (1.0.3)
+ loofah (~> 2.0)
+ railties (5.1.4)
+ actionpack (= 5.1.4)
+ activesupport (= 5.1.4)
+ method_source
+ rake (>= 0.8.7)
+ thor (>= 0.18.1, < 2.0)
+ rake (12.1.0)
+ rb-fsevent (0.10.2)
+ rb-inotify (0.9.10)
+ ffi (>= 0.5.0, < 2)
+ ruby-progressbar (1.9.0)
+ ruby_dep (1.5.0)
+ rubyzip (1.2.1)
+ sass (3.4.25)
+ 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)
+ selenium-webdriver (3.6.0)
+ childprocess (~> 0.5)
+ rubyzip (~> 1.0)
+ simplecov (0.15.1)
+ docile (~> 1.1.0)
+ json (>= 1.8, < 3)
+ simplecov-html (~> 0.10.0)
+ simplecov-html (0.10.2)
+ spring (2.0.2)
+ activesupport (>= 4.2)
+ spring-watcher-listen (2.0.1)
+ listen (>= 2.7, < 4.0)
+ spring (>= 1.2, < 3.0)
+ sprockets (3.7.1)
+ 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.1)
+ actionpack (>= 4.0)
+ activesupport (>= 4.0)
+ sprockets (>= 3.0.0)
+ thor (0.20.0)
+ thread_safe (0.3.6)
+ tilt (2.0.8)
+ turbolinks (5.0.1)
+ turbolinks-source (~> 5)
+ turbolinks-source (5.0.3)
+ tzinfo (1.2.3)
+ thread_safe (~> 0.1)
+ uglifier (3.2.0)
+ execjs (>= 0.3.0, < 3)
+ web-console (3.5.1)
+ actionview (>= 5.0)
+ activemodel (>= 5.0)
+ bindex (>= 0.4.0)
+ railties (>= 5.0)
+ websocket-driver (0.6.5)
+ websocket-extensions (>= 0.1.0)
+ websocket-extensions (0.1.2)
+ xpath (2.1.0)
+ nokogiri (~> 1.3)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ awesome_print
+ better_errors
+ binding_of_caller
+ byebug
+ capybara (~> 2.13)
+ dotenv-rails
+ foundation-rails (= 6.4.1.2)
+ jbuilder (~> 2.5)
+ jquery-rails
+ jquery-turbolinks
+ listen (>= 3.0.5, < 3.2)
+ minitest-rails
+ minitest-reporters
+ omniauth
+ omniauth-github
+ pg (~> 0.18)
+ pry-rails
+ puma (~> 3.7)
+ rails (~> 5.1.4)
+ sass-rails (~> 5.0)
+ selenium-webdriver
+ simplecov
+ spring
+ spring-watcher-listen (~> 2.0.0)
+ turbolinks (~> 5)
+ tzinfo-data
+ uglifier (>= 1.3.0)
+ web-console (>= 3.3.0)
+
+BUNDLED WITH
+ 1.16.0.pre.3
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000000..e85f913914
--- /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 0000000000..b16e53d6d5
--- /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 0000000000..e69de29bb2
diff --git a/app/assets/images/PNW-logo3.png b/app/assets/images/PNW-logo3.png
new file mode 100644
index 0000000000..34ace2b988
Binary files /dev/null and b/app/assets/images/PNW-logo3.png differ
diff --git a/app/assets/images/PNWdefaultphoto.jpg b/app/assets/images/PNWdefaultphoto.jpg
new file mode 100644
index 0000000000..77172b89f3
Binary files /dev/null and b/app/assets/images/PNWdefaultphoto.jpg differ
diff --git a/app/assets/images/PNWhummingbirdpillow.jpg b/app/assets/images/PNWhummingbirdpillow.jpg
new file mode 100644
index 0000000000..22f2c55127
Binary files /dev/null and b/app/assets/images/PNWhummingbirdpillow.jpg differ
diff --git a/app/assets/images/PNWpintglasses.jpg b/app/assets/images/PNWpintglasses.jpg
new file mode 100644
index 0000000000..74c68e9a81
Binary files /dev/null and b/app/assets/images/PNWpintglasses.jpg differ
diff --git a/app/assets/images/Triad B.png b/app/assets/images/Triad B.png
new file mode 100644
index 0000000000..766dbbe8ee
Binary files /dev/null and b/app/assets/images/Triad B.png differ
diff --git a/app/assets/images/background.jpg b/app/assets/images/background.jpg
new file mode 100644
index 0000000000..61a020b54e
Binary files /dev/null and b/app/assets/images/background.jpg differ
diff --git a/app/assets/images/banner-Rainier1.jpg b/app/assets/images/banner-Rainier1.jpg
new file mode 100644
index 0000000000..d2aa597384
Binary files /dev/null and b/app/assets/images/banner-Rainier1.jpg differ
diff --git a/app/assets/images/banner-Rainier2.jpg b/app/assets/images/banner-Rainier2.jpg
new file mode 100644
index 0000000000..339a856cc1
Binary files /dev/null and b/app/assets/images/banner-Rainier2.jpg differ
diff --git a/app/assets/images/campfire-on-beach.jpg b/app/assets/images/campfire-on-beach.jpg
new file mode 100644
index 0000000000..758344cb31
Binary files /dev/null and b/app/assets/images/campfire-on-beach.jpg differ
diff --git a/app/assets/images/clothing_placeholder.png b/app/assets/images/clothing_placeholder.png
new file mode 100644
index 0000000000..6798cb2344
Binary files /dev/null and b/app/assets/images/clothing_placeholder.png differ
diff --git a/app/assets/images/hoh_boundary_waters.jpg b/app/assets/images/hoh_boundary_waters.jpg
new file mode 100644
index 0000000000..1c26f012d6
Binary files /dev/null and b/app/assets/images/hoh_boundary_waters.jpg differ
diff --git a/app/assets/images/lake.jpg b/app/assets/images/lake.jpg
new file mode 100644
index 0000000000..7ac2caa655
Binary files /dev/null and b/app/assets/images/lake.jpg differ
diff --git a/app/assets/images/mountain.jpeg b/app/assets/images/mountain.jpeg
new file mode 100644
index 0000000000..9725bb1297
Binary files /dev/null and b/app/assets/images/mountain.jpeg differ
diff --git a/app/assets/images/pendleton-1.jpg b/app/assets/images/pendleton-1.jpg
new file mode 100644
index 0000000000..8dfe324d65
Binary files /dev/null and b/app/assets/images/pendleton-1.jpg differ
diff --git a/app/assets/images/purple.jpg b/app/assets/images/purple.jpg
new file mode 100644
index 0000000000..790fe6e6b2
Binary files /dev/null and b/app/assets/images/purple.jpg differ
diff --git a/app/assets/images/shopping-cart (1).png b/app/assets/images/shopping-cart (1).png
new file mode 100644
index 0000000000..70424fdd49
Binary files /dev/null and b/app/assets/images/shopping-cart (1).png differ
diff --git a/app/assets/images/shopping-cart.png b/app/assets/images/shopping-cart.png
new file mode 100644
index 0000000000..97048101c4
Binary files /dev/null and b/app/assets/images/shopping-cart.png differ
diff --git a/app/assets/images/three.jpg b/app/assets/images/three.jpg
new file mode 100644
index 0000000000..41f7e186cf
Binary files /dev/null and b/app/assets/images/three.jpg differ
diff --git a/app/assets/images/two.jpg b/app/assets/images/two.jpg
new file mode 100644
index 0000000000..24f6457f6f
Binary files /dev/null and b/app/assets/images/two.jpg differ
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
new file mode 100644
index 0000000000..f0a4f1a839
--- /dev/null
+++ b/app/assets/javascripts/application.js
@@ -0,0 +1,20 @@
+// 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, 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 foundation
+//= require turbolinks
+//= require_tree .
+
+
+$(function(){ $(document).foundation(); });
diff --git a/app/assets/javascripts/billing_data.js b/app/assets/javascripts/billing_data.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/billing_data.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/cable.js b/app/assets/javascripts/cable.js
new file mode 100644
index 0000000000..739aa5f022
--- /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/categories.js b/app/assets/javascripts/categories.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/categories.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/channels/.keep b/app/assets/javascripts/channels/.keep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/app/assets/javascripts/items.js b/app/assets/javascripts/items.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/items.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/main_page.js b/app/assets/javascripts/main_page.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/main_page.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/orders.js b/app/assets/javascripts/orders.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/orders.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/orders_products.js b/app/assets/javascripts/orders_products.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/orders_products.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/products.js b/app/assets/javascripts/products.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/products.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/reviews.js b/app/assets/javascripts/reviews.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/reviews.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/sessions.js b/app/assets/javascripts/sessions.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/sessions.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/users.js b/app/assets/javascripts/users.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/users.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/stylesheets/_settings.scss b/app/assets/stylesheets/_settings.scss
new file mode 100644
index 0000000000..b67ff00cdc
--- /dev/null
+++ b/app/assets/stylesheets/_settings.scss
@@ -0,0 +1,863 @@
+// Foundation for Sites Settings
+// -----------------------------
+//
+// Table of Contents:
+//
+// 1. Global
+// 2. Breakpoints
+// 3. The Grid
+// 4. Base Typography
+// 5. Typography Helpers
+// 6. Abide
+// 7. Accordion
+// 8. Accordion Menu
+// 9. Badge
+// 10. Breadcrumbs
+// 11. Button
+// 12. Button Group
+// 13. Callout
+// 14. Card
+// 15. Close Button
+// 16. Drilldown
+// 17. Dropdown
+// 18. Dropdown Menu
+// 19. Flexbox Utilities
+// 20. Forms
+// 21. Label
+// 22. Media Object
+// 23. Menu
+// 24. Meter
+// 25. Off-canvas
+// 26. Orbit
+// 27. Pagination
+// 28. Progress Bar
+// 29. Prototype Arrow
+// 30. Prototype Border-Box
+// 31. Prototype Border-None
+// 32. Prototype Bordered
+// 33. Prototype Display
+// 34. Prototype Font-Styling
+// 35. Prototype List-Style-Type
+// 36. Prototype Overflow
+// 37. Prototype Position
+// 38. Prototype Rounded
+// 39. Prototype Separator
+// 40. Prototype Shadow
+// 41. Prototype Sizing
+// 42. Prototype Spacing
+// 43. Prototype Text-Decoration
+// 44. Prototype Text-Transformation
+// 45. Prototype Text-Utilities
+// 46. Responsive Embed
+// 47. Reveal
+// 48. Slider
+// 49. Switch
+// 50. Table
+// 51. Tabs
+// 52. Thumbnail
+// 53. Title Bar
+// 54. Tooltip
+// 55. Top Bar
+// 56. Xy Grid
+
+@import 'util/util';
+
+// 1. Global
+// ---------
+
+$global-font-size: 100%;
+$global-width: rem-calc(1200);
+$global-lineheight: 1.5;
+$foundation-palette: (
+ primary: #1779ba,
+ secondary: #767676,
+ success: #3adb76,
+ warning: #ffae00,
+ alert: #cc4b37,
+);
+$light-gray: #e6e6e6;
+$medium-gray: #cacaca;
+$dark-gray: #8a8a8a;
+$black: #0a0a0a;
+$white: #fefefe;
+$body-background: $white;
+$body-font-color: $black;
+$body-font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;
+$body-antialiased: true;
+$global-margin: 1rem;
+$global-padding: 1rem;
+$global-position: 1rem;
+$global-weight-normal: normal;
+$global-weight-bold: bold;
+$global-radius: 0;
+$global-menu-padding: 0.7rem 1rem;
+$global-menu-nested-margin: 1rem;
+$global-text-direction: ltr;
+$global-flexbox: true;
+$global-prototype-breakpoints: false;
+$global-color-pick-contrast-tolerance: 0;
+$print-transparent-backgrounds: true;
+
+@include add-foundation-colors;
+
+// 2. Breakpoints
+// --------------
+
+$breakpoints: (
+ small: 0,
+ medium: 640px,
+ large: 1024px,
+ xlarge: 1200px,
+ xxlarge: 1440px,
+);
+$print-breakpoint: large;
+$breakpoint-classes: (small medium large);
+
+// 3. The Grid
+// -----------
+
+$grid-row-width: $global-width;
+$grid-column-count: 12;
+$grid-column-gutter: (
+ small: 20px,
+ medium: 30px,
+);
+$grid-column-align-edge: true;
+$grid-column-alias: 'columns';
+$block-grid-max: 8;
+
+// 4. Base Typography
+// ------------------
+
+$header-font-family: $body-font-family;
+$header-font-weight: $global-weight-normal;
+$header-font-style: normal;
+$font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace;
+$header-color: inherit;
+$header-lineheight: 1.4;
+$header-margin-bottom: 0.5rem;
+$header-styles: (
+ small: (
+ 'h1': ('font-size': 24),
+ 'h2': ('font-size': 20),
+ 'h3': ('font-size': 19),
+ 'h4': ('font-size': 18),
+ 'h5': ('font-size': 17),
+ 'h6': ('font-size': 16),
+ ),
+ medium: (
+ 'h1': ('font-size': 48),
+ 'h2': ('font-size': 40),
+ 'h3': ('font-size': 31),
+ 'h4': ('font-size': 25),
+ 'h5': ('font-size': 20),
+ 'h6': ('font-size': 16),
+ ),
+);
+$header-text-rendering: optimizeLegibility;
+$small-font-size: 80%;
+$header-small-font-color: $medium-gray;
+$paragraph-lineheight: 1.6;
+$paragraph-margin-bottom: 1rem;
+$paragraph-text-rendering: optimizeLegibility;
+$code-color: $black;
+$code-font-family: $font-family-monospace;
+$code-font-weight: $global-weight-normal;
+$code-background: $light-gray;
+$code-border: 1px solid $medium-gray;
+$code-padding: rem-calc(2 5 1);
+$anchor-color: $primary-color;
+$anchor-color-hover: scale-color($anchor-color, $lightness: -14%);
+$anchor-text-decoration: none;
+$anchor-text-decoration-hover: none;
+$hr-width: $global-width;
+$hr-border: 1px solid $medium-gray;
+$hr-margin: rem-calc(20) auto;
+$list-lineheight: $paragraph-lineheight;
+$list-margin-bottom: $paragraph-margin-bottom;
+$list-style-type: disc;
+$list-style-position: outside;
+$list-side-margin: 1.25rem;
+$list-nested-side-margin: 1.25rem;
+$defnlist-margin-bottom: 1rem;
+$defnlist-term-weight: $global-weight-bold;
+$defnlist-term-margin-bottom: 0.3rem;
+$blockquote-color: $dark-gray;
+$blockquote-padding: rem-calc(9 20 0 19);
+$blockquote-border: 1px solid $medium-gray;
+$cite-font-size: rem-calc(13);
+$cite-color: $dark-gray;
+$cite-pseudo-content: '\2014 \0020';
+$keystroke-font: $font-family-monospace;
+$keystroke-color: $black;
+$keystroke-background: $light-gray;
+$keystroke-padding: rem-calc(2 4 0);
+$keystroke-radius: $global-radius;
+$abbr-underline: 1px dotted $black;
+
+// 5. Typography Helpers
+// ---------------------
+
+$lead-font-size: $global-font-size * 1.25;
+$lead-lineheight: 1.6;
+$subheader-lineheight: 1.4;
+$subheader-color: $dark-gray;
+$subheader-font-weight: $global-weight-normal;
+$subheader-margin-top: 0.2rem;
+$subheader-margin-bottom: 0.5rem;
+$stat-font-size: 2.5rem;
+
+// 6. Abide
+// --------
+
+$abide-inputs: true;
+$abide-labels: true;
+$input-background-invalid: get-color(alert);
+$form-label-color-invalid: get-color(alert);
+$input-error-color: get-color(alert);
+$input-error-font-size: rem-calc(12);
+$input-error-font-weight: $global-weight-bold;
+
+// 7. Accordion
+// ------------
+
+$accordion-background: $white;
+$accordion-plusminus: true;
+$accordion-title-font-size: rem-calc(12);
+$accordion-item-color: $primary-color;
+$accordion-item-background-hover: $light-gray;
+$accordion-item-padding: 1.25rem 1rem;
+$accordion-content-background: $white;
+$accordion-content-border: 1px solid $light-gray;
+$accordion-content-color: $body-font-color;
+$accordion-content-padding: 1rem;
+
+// 8. Accordion Menu
+// -----------------
+
+$accordionmenu-padding: $global-menu-padding;
+$accordionmenu-nested-margin: $global-menu-nested-margin;
+$accordionmenu-submenu-padding: $accordionmenu-padding;
+$accordionmenu-arrows: true;
+$accordionmenu-arrow-color: $primary-color;
+$accordionmenu-item-background: null;
+$accordionmenu-border: null;
+$accordionmenu-submenu-toggle-background: null;
+$accordion-submenu-toggle-border: $accordionmenu-border;
+$accordionmenu-submenu-toggle-width: 40px;
+$accordionmenu-submenu-toggle-height: $accordionmenu-submenu-toggle-width;
+$accordionmenu-arrow-size: 6px;
+
+// 9. Badge
+// --------
+
+$badge-background: $primary-color;
+$badge-color: $white;
+$badge-color-alt: $black;
+$badge-palette: $foundation-palette;
+$badge-padding: 0.3em;
+$badge-minwidth: 2.1em;
+$badge-font-size: 0.6rem;
+
+// 10. Breadcrumbs
+// ---------------
+
+$breadcrumbs-margin: 0 0 $global-margin 0;
+$breadcrumbs-item-font-size: rem-calc(11);
+$breadcrumbs-item-color: $primary-color;
+$breadcrumbs-item-color-current: $black;
+$breadcrumbs-item-color-disabled: $medium-gray;
+$breadcrumbs-item-margin: 0.75rem;
+$breadcrumbs-item-uppercase: true;
+$breadcrumbs-item-separator: true;
+$breadcrumbs-item-separator-item: '/';
+$breadcrumbs-item-separator-item-rtl: '\\';
+$breadcrumbs-item-separator-color: $medium-gray;
+
+// 11. Button
+// ----------
+
+$button-font-family: inherit;
+$button-padding: 0.85em 1em;
+$button-margin: 0 0 $global-margin 0;
+$button-fill: solid;
+$button-background: $primary-color;
+$button-background-hover: scale-color($button-background, $lightness: -15%);
+$button-color: $white;
+$button-color-alt: $black;
+$button-radius: $global-radius;
+$button-hollow-border-width: 1px;
+$button-sizes: (
+ tiny: 0.6rem,
+ small: 0.75rem,
+ default: 0.9rem,
+ large: 1.25rem,
+);
+$button-palette: $foundation-palette;
+$button-opacity-disabled: 0.25;
+$button-background-hover-lightness: -20%;
+$button-hollow-hover-lightness: -50%;
+$button-transition: background-color 0.25s ease-out, color 0.25s ease-out;
+
+// 12. Button Group
+// ----------------
+
+$buttongroup-margin: 1rem;
+$buttongroup-spacing: 1px;
+$buttongroup-child-selector: '.button';
+$buttongroup-expand-max: 6;
+$buttongroup-radius-on-each: true;
+
+// 13. Callout
+// -----------
+
+$callout-background: $white;
+$callout-background-fade: 85%;
+$callout-border: 1px solid rgba($black, 0.25);
+$callout-margin: 0 0 1rem 0;
+$callout-padding: 1rem;
+$callout-font-color: $body-font-color;
+$callout-font-color-alt: $body-background;
+$callout-radius: $global-radius;
+$callout-link-tint: 30%;
+
+// 14. Card
+// --------
+
+$card-background: $white;
+$card-font-color: $body-font-color;
+$card-divider-background: $light-gray;
+$card-border: 1px solid $light-gray;
+$card-shadow: none;
+$card-border-radius: $global-radius;
+$card-padding: $global-padding;
+$card-margin-bottom: $global-margin;
+
+// 15. Close Button
+// ----------------
+
+$closebutton-position: right top;
+$closebutton-offset-horizontal: (
+ small: 0.66rem,
+ medium: 1rem,
+);
+$closebutton-offset-vertical: (
+ small: 0.33em,
+ medium: 0.5rem,
+);
+$closebutton-size: (
+ small: 1.5em,
+ medium: 2em,
+);
+$closebutton-lineheight: 1;
+$closebutton-color: $dark-gray;
+$closebutton-color-hover: $black;
+
+// 16. Drilldown
+// -------------
+
+$drilldown-transition: transform 0.15s linear;
+$drilldown-arrows: true;
+$drilldown-padding: $global-menu-padding;
+$drilldown-nested-margin: 0;
+$drilldown-background: $white;
+$drilldown-submenu-padding: $drilldown-padding;
+$drilldown-submenu-background: $white;
+$drilldown-arrow-color: $primary-color;
+$drilldown-arrow-size: 6px;
+
+// 17. Dropdown
+// ------------
+
+$dropdown-padding: 1rem;
+$dropdown-background: $body-background;
+$dropdown-border: 1px solid $medium-gray;
+$dropdown-font-size: 1rem;
+$dropdown-width: 300px;
+$dropdown-radius: $global-radius;
+$dropdown-sizes: (
+ tiny: 100px,
+ small: 200px,
+ large: 400px,
+);
+
+// 18. Dropdown Menu
+// -----------------
+
+$dropdownmenu-arrows: true;
+$dropdownmenu-arrow-color: $anchor-color;
+$dropdownmenu-arrow-size: 6px;
+$dropdownmenu-arrow-padding: 1.5rem;
+$dropdownmenu-min-width: 200px;
+$dropdownmenu-background: $white;
+$dropdownmenu-submenu-background: $dropdownmenu-background;
+$dropdownmenu-padding: $global-menu-padding;
+$dropdownmenu-nested-margin: 0;
+$dropdownmenu-submenu-padding: $dropdownmenu-padding;
+$dropdownmenu-border: 1px solid $medium-gray;
+$dropdown-menu-item-color-active: get-color(primary);
+$dropdown-menu-item-background-active: transparent;
+
+// 19. Flexbox Utilities
+// ---------------------
+
+$flex-source-ordering-count: 6;
+$flexbox-responsive-breakpoints: true;
+
+// 20. Forms
+// ---------
+
+$fieldset-border: 1px solid $medium-gray;
+$fieldset-padding: rem-calc(20);
+$fieldset-margin: rem-calc(18 0);
+$legend-padding: rem-calc(0 3);
+$form-spacing: rem-calc(16);
+$helptext-color: $black;
+$helptext-font-size: rem-calc(13);
+$helptext-font-style: italic;
+$input-prefix-color: $black;
+$input-prefix-background: $light-gray;
+$input-prefix-border: 1px solid $medium-gray;
+$input-prefix-padding: 1rem;
+$form-label-color: $black;
+$form-label-font-size: rem-calc(14);
+$form-label-font-weight: $global-weight-normal;
+$form-label-line-height: 1.8;
+$select-background: $white;
+$select-triangle-color: $dark-gray;
+$select-radius: $global-radius;
+$input-color: $black;
+$input-placeholder-color: $medium-gray;
+$input-font-family: inherit;
+$input-font-size: rem-calc(16);
+$input-font-weight: $global-weight-normal;
+$input-line-height: $global-lineheight;
+$input-background: $white;
+$input-background-focus: $white;
+$input-background-disabled: $light-gray;
+$input-border: 1px solid $medium-gray;
+$input-border-focus: 1px solid $dark-gray;
+$input-padding: $form-spacing / 2;
+$input-shadow: inset 0 1px 2px rgba($black, 0.1);
+$input-shadow-focus: 0 0 5px $medium-gray;
+$input-cursor-disabled: not-allowed;
+$input-transition: box-shadow 0.5s, border-color 0.25s ease-in-out;
+$input-number-spinners: true;
+$input-radius: $global-radius;
+$form-button-radius: $global-radius;
+
+// 21. Label
+// ---------
+
+$label-background: $primary-color;
+$label-color: $white;
+$label-color-alt: $black;
+$label-palette: $foundation-palette;
+$label-font-size: 0.8rem;
+$label-padding: 0.33333rem 0.5rem;
+$label-radius: $global-radius;
+
+// 22. Media Object
+// ----------------
+
+$mediaobject-margin-bottom: $global-margin;
+$mediaobject-section-padding: $global-padding;
+$mediaobject-image-width-stacked: 100%;
+
+// 23. Menu
+// --------
+
+$menu-margin: 0;
+$menu-nested-margin: $global-menu-nested-margin;
+$menu-items-padding: $global-menu-padding;
+$menu-simple-margin: 1rem;
+$menu-item-color-active: $white;
+$menu-item-background-active: get-color(primary);
+$menu-icon-spacing: 0.25rem;
+$menu-item-background-hover: $light-gray;
+$menu-state-back-compat: true;
+$menu-centered-back-compat: true;
+
+// 24. Meter
+// ---------
+
+$meter-height: 1rem;
+$meter-radius: $global-radius;
+$meter-background: $medium-gray;
+$meter-fill-good: $success-color;
+$meter-fill-medium: $warning-color;
+$meter-fill-bad: $alert-color;
+
+// 25. Off-canvas
+// --------------
+
+$offcanvas-size: 250px;
+$offcanvas-vertical-size: 250px;
+$offcanvas-background: $light-gray;
+$offcanvas-shadow: 0 0 10px rgba($black, 0.7);
+$offcanvas-inner-shadow-size: 20px;
+$offcanvas-inner-shadow-color: rgba($black, 0.25);
+$offcanvas-overlay-zindex: 11;
+$offcanvas-push-zindex: 12;
+$offcanvas-overlap-zindex: 13;
+$offcanvas-reveal-zindex: 12;
+$offcanvas-transition-length: 0.5s;
+$offcanvas-transition-timing: ease;
+$offcanvas-fixed-reveal: true;
+$offcanvas-exit-background: rgba($white, 0.25);
+$maincontent-class: 'off-canvas-content';
+
+// 26. Orbit
+// ---------
+
+$orbit-bullet-background: $medium-gray;
+$orbit-bullet-background-active: $dark-gray;
+$orbit-bullet-diameter: 1.2rem;
+$orbit-bullet-margin: 0.1rem;
+$orbit-bullet-margin-top: 0.8rem;
+$orbit-bullet-margin-bottom: 0.8rem;
+$orbit-caption-background: rgba($black, 0.5);
+$orbit-caption-padding: 1rem;
+$orbit-control-background-hover: rgba($black, 0.5);
+$orbit-control-padding: 1rem;
+$orbit-control-zindex: 10;
+
+// 27. Pagination
+// --------------
+
+$pagination-font-size: rem-calc(14);
+$pagination-margin-bottom: $global-margin;
+$pagination-item-color: $black;
+$pagination-item-padding: rem-calc(3 10);
+$pagination-item-spacing: rem-calc(1);
+$pagination-radius: $global-radius;
+$pagination-item-background-hover: $light-gray;
+$pagination-item-background-current: $primary-color;
+$pagination-item-color-current: $white;
+$pagination-item-color-disabled: $medium-gray;
+$pagination-ellipsis-color: $black;
+$pagination-mobile-items: false;
+$pagination-mobile-current-item: false;
+$pagination-arrows: true;
+
+// 28. Progress Bar
+// ----------------
+
+$progress-height: 1rem;
+$progress-background: $medium-gray;
+$progress-margin-bottom: $global-margin;
+$progress-meter-background: $primary-color;
+$progress-radius: $global-radius;
+
+// 29. Prototype Arrow
+// -------------------
+
+$prototype-arrow-directions: (
+ down,
+ up,
+ right,
+ left
+);
+$prototype-arrow-size: 0.4375rem;
+$prototype-arrow-color: $black;
+
+// 30. Prototype Border-Box
+// ------------------------
+
+$prototype-border-box-breakpoints: $global-prototype-breakpoints;
+
+// 31. Prototype Border-None
+// -------------------------
+
+$prototype-border-none-breakpoints: $global-prototype-breakpoints;
+
+// 32. Prototype Bordered
+// ----------------------
+
+$prototype-bordered-breakpoints: $global-prototype-breakpoints;
+$prototype-border-width: rem-calc(1);
+$prototype-border-type: solid;
+$prototype-border-color: $medium-gray;
+
+// 33. Prototype Display
+// ---------------------
+
+$prototype-display-breakpoints: $global-prototype-breakpoints;
+$prototype-display: (
+ inline,
+ inline-block,
+ block,
+ table,
+ table-cell
+);
+
+// 34. Prototype Font-Styling
+// --------------------------
+
+$prototype-font-breakpoints: $global-prototype-breakpoints;
+$prototype-wide-letter-spacing: rem-calc(4);
+$prototype-font-normal: $global-weight-normal;
+$prototype-font-bold: $global-weight-bold;
+
+// 35. Prototype List-Style-Type
+// -----------------------------
+
+$prototype-list-breakpoints: $global-prototype-breakpoints;
+$prototype-style-type-unordered: (
+ disc,
+ circle,
+ square
+);
+$prototype-style-type-ordered: (
+ decimal,
+ lower-alpha,
+ lower-latin,
+ lower-roman,
+ upper-alpha,
+ upper-latin,
+ upper-roman
+);
+
+// 36. Prototype Overflow
+// ----------------------
+
+$prototype-overflow-breakpoints: $global-prototype-breakpoints;
+$prototype-overflow: (
+ visible,
+ hidden,
+ scroll
+);
+
+// 37. Prototype Position
+// ----------------------
+
+$prototype-position-breakpoints: $global-prototype-breakpoints;
+$prototype-position: (
+ static,
+ relative,
+ absolute,
+ fixed
+);
+$prototype-position-z-index: 975;
+
+// 38. Prototype Rounded
+// ---------------------
+
+$prototype-rounded-breakpoints: $global-prototype-breakpoints;
+$prototype-border-radius: rem-calc(3);
+
+// 39. Prototype Separator
+// -----------------------
+
+$prototype-separator-breakpoints: $global-prototype-breakpoints;
+$prototype-separator-align: center;
+$prototype-separator-height: rem-calc(2);
+$prototype-separator-width: 3rem;
+$prototype-separator-background: $primary-color;
+$prototype-separator-margin-top: $global-margin;
+
+// 40. Prototype Shadow
+// --------------------
+
+$prototype-shadow-breakpoints: $global-prototype-breakpoints;
+$prototype-box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),
+ 0 2px 10px 0 rgba(0,0,0,.12);
+
+// 41. Prototype Sizing
+// --------------------
+
+$prototype-sizing-breakpoints: $global-prototype-breakpoints;
+$prototype-sizing: (
+ width,
+ height
+);
+$prototype-sizes: (
+ 25: 25%,
+ 50: 50%,
+ 75: 75%,
+ 100: 100%
+);
+
+// 42. Prototype Spacing
+// ---------------------
+
+$prototype-spacing-breakpoints: $global-prototype-breakpoints;
+$prototype-spacers-count: 3;
+
+// 43. Prototype Text-Decoration
+// -----------------------------
+
+$prototype-decoration-breakpoints: $global-prototype-breakpoints;
+$prototype-text-decoration: (
+ overline,
+ underline,
+ line-through,
+);
+
+// 44. Prototype Text-Transformation
+// ---------------------------------
+
+$prototype-transformation-breakpoints: $global-prototype-breakpoints;
+$prototype-text-transformation: (
+ lowercase,
+ uppercase,
+ capitalize
+);
+
+// 45. Prototype Text-Utilities
+// ----------------------------
+
+$prototype-utilities-breakpoints: $global-prototype-breakpoints;
+$prototype-text-overflow: ellipsis;
+
+// 46. Responsive Embed
+// --------------------
+
+$responsive-embed-margin-bottom: rem-calc(16);
+$responsive-embed-ratios: (
+ default: 4 by 3,
+ widescreen: 16 by 9,
+);
+
+// 47. Reveal
+// ----------
+
+$reveal-background: $white;
+$reveal-width: 600px;
+$reveal-max-width: $global-width;
+$reveal-padding: $global-padding;
+$reveal-border: 1px solid $medium-gray;
+$reveal-radius: $global-radius;
+$reveal-zindex: 1005;
+$reveal-overlay-background: rgba($black, 0.45);
+
+// 48. Slider
+// ----------
+
+$slider-width-vertical: 0.5rem;
+$slider-transition: all 0.2s ease-in-out;
+$slider-height: 0.5rem;
+$slider-background: $light-gray;
+$slider-fill-background: $medium-gray;
+$slider-handle-height: 1.4rem;
+$slider-handle-width: 1.4rem;
+$slider-handle-background: $primary-color;
+$slider-opacity-disabled: 0.25;
+$slider-radius: $global-radius;
+
+// 49. Switch
+// ----------
+
+$switch-background: $medium-gray;
+$switch-background-active: $primary-color;
+$switch-height: 2rem;
+$switch-height-tiny: 1.5rem;
+$switch-height-small: 1.75rem;
+$switch-height-large: 2.5rem;
+$switch-radius: $global-radius;
+$switch-margin: $global-margin;
+$switch-paddle-background: $white;
+$switch-paddle-offset: 0.25rem;
+$switch-paddle-radius: $global-radius;
+$switch-paddle-transition: all 0.25s ease-out;
+
+// 50. Table
+// ---------
+
+$table-background: $white;
+$table-color-scale: 5%;
+$table-border: 1px solid smart-scale($table-background, $table-color-scale);
+$table-padding: rem-calc(8 10 10);
+$table-hover-scale: 2%;
+$table-row-hover: darken($table-background, $table-hover-scale);
+$table-row-stripe-hover: darken($table-background, $table-color-scale + $table-hover-scale);
+$table-is-striped: true;
+$table-striped-background: smart-scale($table-background, $table-color-scale);
+$table-stripe: even;
+$table-head-background: smart-scale($table-background, $table-color-scale / 2);
+$table-head-row-hover: darken($table-head-background, $table-hover-scale);
+$table-foot-background: smart-scale($table-background, $table-color-scale);
+$table-foot-row-hover: darken($table-foot-background, $table-hover-scale);
+$table-head-font-color: $body-font-color;
+$table-foot-font-color: $body-font-color;
+$show-header-for-stacked: false;
+$table-stack-breakpoint: medium;
+
+// 51. Tabs
+// --------
+
+$tab-margin: 0;
+$tab-background: $white;
+$tab-color: $primary-color;
+$tab-background-active: $light-gray;
+$tab-active-color: $primary-color;
+$tab-item-font-size: rem-calc(12);
+$tab-item-background-hover: $white;
+$tab-item-padding: 1.25rem 1.5rem;
+$tab-expand-max: 6;
+$tab-content-background: $white;
+$tab-content-border: $light-gray;
+$tab-content-color: $body-font-color;
+$tab-content-padding: 1rem;
+
+// 52. Thumbnail
+// -------------
+
+$thumbnail-border: solid 4px $white;
+$thumbnail-margin-bottom: $global-margin;
+$thumbnail-shadow: 0 0 0 1px rgba($black, 0.2);
+$thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5);
+$thumbnail-transition: box-shadow 200ms ease-out;
+$thumbnail-radius: $global-radius;
+
+// 53. Title Bar
+// -------------
+
+$titlebar-background: $black;
+$titlebar-color: $white;
+$titlebar-padding: 0.5rem;
+$titlebar-text-font-weight: bold;
+$titlebar-icon-color: $white;
+$titlebar-icon-color-hover: $medium-gray;
+$titlebar-icon-spacing: 0.25rem;
+
+// 54. Tooltip
+// -----------
+
+$has-tip-cursor: help;
+$has-tip-font-weight: $global-weight-bold;
+$has-tip-border-bottom: dotted 1px $dark-gray;
+$tooltip-background-color: $black;
+$tooltip-color: $white;
+$tooltip-padding: 0.75rem;
+$tooltip-max-width: 10rem;
+$tooltip-font-size: $small-font-size;
+$tooltip-pip-width: 0.75rem;
+$tooltip-pip-height: $tooltip-pip-width * 0.866;
+$tooltip-radius: $global-radius;
+
+// 55. Top Bar
+// -----------
+
+$topbar-padding: 0.5rem;
+$topbar-background: $light-gray;
+$topbar-submenu-background: $topbar-background;
+$topbar-title-spacing: 0.5rem 1rem 0.5rem 0;
+$topbar-input-width: 200px;
+$topbar-unstack-breakpoint: medium;
+
+// 56. Xy Grid
+// -----------
+
+$xy-grid: true;
+$grid-container: $global-width;
+$grid-columns: 12;
+$grid-margin-gutters: (
+ small: 20px,
+ medium: 30px
+);
+$grid-padding-gutters: $grid-margin-gutters;
+$grid-container-padding: $grid-padding-gutters;
+$grid-container-max: $global-width;
+$block-grid-max: 8;
+
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
new file mode 100644
index 0000000000..4304a2deab
--- /dev/null
+++ b/app/assets/stylesheets/application.scss
@@ -0,0 +1,206 @@
+/*
+ * 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, 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
+//= require foundation_and_overrides
+
+ *= require foundation_and_overrides
+
+ */
+
+body, h1, h2, h3, h4, h5, footer {
+ // font-family: 'Slabo 27px', serif;
+ font-family: 'Muli', sans-serif;
+
+}
+
+body {
+ width: 100%;
+ height: calc(100vh - 200px);
+ background-repeat: no-repeat;
+ // opacity: 0.2;
+
+ }
+
+
+//Nav--------------------------------------
+nav {
+ background: #3f6172;
+ text-transform: uppercase;
+ width: auto;
+ height: 200px;
+ font-size: 1em;
+ letter-spacing: 0.1em;
+
+}
+
+nav ul,
+nav li {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+nav li {
+ display: inline-block;
+ float: left;
+}
+
+nav li a {
+ display: block;
+ min-width: 140px;
+ height: 40px;
+ text-align: center;
+ line-height: 40px;
+ text-decoration: none;
+ color:black;
+}
+
+/*Dropdown*/
+.menu_item a:hover{
+ background: #8c4511;
+}
+
+nav li:hover ul a {
+ height: 40px;
+ line-height: 40px;
+}
+
+nav li ul li {
+ display: block;
+ float: none;
+ background: none;
+}
+
+/*Display on hover*/
+nav ul li a:hover + .hidden,
+.hidden:hover {
+ display: block;
+}
+
+/*Hides the drop down links*/
+nav li ul {
+ display: none;
+}
+
+
+
+//NAV-----ADDED---------------------------------
+
+.right {
+ margin-top: 5px;
+ float: right;
+}
+
+
+.right ul li a:hover {
+ background-color: transparent;
+ color: black;
+ border: solid 1px;
+ border-radius: 15px;
+}
+
+.left {
+ font-size: 3em;
+ height: 200px;
+}
+
+
+.left:hover
+{
+ -webkit-transform: scale(1.03);
+ -ms-transform: scale(1.03);
+ transform: scale(1.03);
+}
+
+
+.left a{
+ // width: 40%;
+ font-size: 4em;
+ text-align: center;
+ margin-left: 2%;
+ line-height: 1;
+ color:white;
+}
+
+.button {
+ color: black;
+ background: none;
+}
+
+.button:hover {
+ color: black;
+}
+
+// CHECKBOXES--------------------------------------------
+
+
+input[type="checkbox"] {
+ // display: none;
+}
+
+input[type="checkbox"]:checked ~ #menu {
+ display: block;
+}
+
+
+// PROFILE & CART------------------------------
+
+.background {
+ width: 100%;
+ height: calc(100vh - 200px);
+ background-image: image-url('purple.jpg');
+ background-repeat: no-repeat;
+}
+
+
+.top-links {
+ margin-left: 5%;
+ margin-bottom: 2%;
+}
+
+.profile-section {
+ display: inline-block;
+ margin-left: 5%;
+ margin-right: 5%;
+}
+
+.button:hover {
+ color: black;
+ background: none;
+ background-color: transparent;
+ border: solid 1px;
+ border-radius: 15px;
+}
+
+tbody:nth-child(even) {
+ background-color: white;
+ }
+
+tbody:nth-child(odd) {
+ background-color: #ebebeb;
+}
+
+.table th,
+.table td {
+ text-align: center;
+}
+
+.order-title {
+ // margin-left: 5%;
+}
+
+.totals {
+ float: right;
+ // margin-right: 5%;
+}
diff --git a/app/assets/stylesheets/billing_data.scss b/app/assets/stylesheets/billing_data.scss
new file mode 100644
index 0000000000..4060296673
--- /dev/null
+++ b/app/assets/stylesheets/billing_data.scss
@@ -0,0 +1,7 @@
+// Place all the styles related to the BillingData controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
+
+.billing-ul li{
+ // display: inline;
+}
diff --git a/app/assets/stylesheets/categories.scss b/app/assets/stylesheets/categories.scss
new file mode 100644
index 0000000000..42976cbc11
--- /dev/null
+++ b/app/assets/stylesheets/categories.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the Categories controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/foundation_and_overrides.scss b/app/assets/stylesheets/foundation_and_overrides.scss
new file mode 100644
index 0000000000..ebc38966d9
--- /dev/null
+++ b/app/assets/stylesheets/foundation_and_overrides.scss
@@ -0,0 +1,57 @@
+@charset 'utf-8';
+
+@import 'settings';
+@import 'foundation';
+
+// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package.
+@import 'motion-ui/motion-ui';
+//
+// @import 'motion-ui/motion-ui';
+
+// We include everything by default. To slim your CSS, remove components you don't use.
+
+@include foundation-global-styles;
+@include foundation-grid;
+@include foundation-typography;
+@include foundation-button;
+@include foundation-forms;
+@include foundation-visibility-classes;
+@include foundation-float-classes;
+@include foundation-accordion;
+@include foundation-accordion-menu;
+@include foundation-badge;
+@include foundation-breadcrumbs;
+@include foundation-button-group;
+@include foundation-callout;
+@include foundation-card;
+@include foundation-close-button;
+@include foundation-drilldown-menu;
+@include foundation-dropdown;
+@include foundation-dropdown-menu;
+@include foundation-responsive-embed;
+@include foundation-label;
+@include foundation-media-object;
+@include foundation-menu;
+@include foundation-menu-icon;
+@include foundation-off-canvas;
+@include foundation-orbit;
+@include foundation-pagination;
+@include foundation-progress-bar;
+@include foundation-slider;
+@include foundation-sticky;
+@include foundation-reveal;
+@include foundation-switch;
+@include foundation-table;
+@include foundation-tabs;
+@include foundation-thumbnail;
+@include foundation-title-bar;
+@include foundation-tooltip;
+@include foundation-top-bar;
+
+// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package.
+//
+@include motion-ui-transitions;
+@include motion-ui-animations;
+
+// @include motion-ui-transitions;
+// @include motion-ui-animations;
diff --git a/app/assets/stylesheets/items.scss b/app/assets/stylesheets/items.scss
new file mode 100644
index 0000000000..a3a147ad0b
--- /dev/null
+++ b/app/assets/stylesheets/items.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the Items controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/main_page.scss b/app/assets/stylesheets/main_page.scss
new file mode 100644
index 0000000000..bf3e21ace6
--- /dev/null
+++ b/app/assets/stylesheets/main_page.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the MainPage controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/order_products.scss b/app/assets/stylesheets/order_products.scss
new file mode 100644
index 0000000000..4e38cdae9b
--- /dev/null
+++ b/app/assets/stylesheets/order_products.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the OrderProducts controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/orders.scss b/app/assets/stylesheets/orders.scss
new file mode 100644
index 0000000000..741506954d
--- /dev/null
+++ b/app/assets/stylesheets/orders.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the Orders controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss
new file mode 100644
index 0000000000..9029b874df
--- /dev/null
+++ b/app/assets/stylesheets/products.scss
@@ -0,0 +1,47 @@
+// Place all the styles related to the Products controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
+
+// INDEX------------------------------------------
+section {
+ width: 95%;
+ margin-left: 2%;
+ margin-right: 2%;
+}
+
+article {
+ display: inline-block;
+ border: solid 1px;
+ border-radius: 25px;
+ width: 20%;
+ min-width: auto;
+ height: 300px;
+ text-align: center;
+ margin: 2% 2% 2% %2%;
+}
+
+article img {
+ margin-top: 5%;
+ height: 100px;
+ width: 100px;
+}
+
+// SHOW------------------------------------------------
+
+.product-details {
+ // border: solid 1px;
+ display: block;
+ width: 45%;
+ min-width: 40%;
+ margin-top: 3%;
+}
+
+
+.text {
+ width: 100 px;
+}
+
+
+.reviews{
+ margin-top: 3%;
+}
diff --git a/app/assets/stylesheets/reviews.scss b/app/assets/stylesheets/reviews.scss
new file mode 100644
index 0000000000..d1257bf340
--- /dev/null
+++ b/app/assets/stylesheets/reviews.scss
@@ -0,0 +1,17 @@
+// Place all the styles related to the Reviews controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
+
+.checkbox {
+ display: inline;
+
+}
+
+.review-form {
+ margin-top: 3%;
+ width: 50%;
+}
+
+.categories li {
+ margin-top: 3%;
+}
diff --git a/app/assets/stylesheets/sessions.scss b/app/assets/stylesheets/sessions.scss
new file mode 100644
index 0000000000..ccb1ed25b2
--- /dev/null
+++ b/app/assets/stylesheets/sessions.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the Sessions controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/users.scss b/app/assets/stylesheets/users.scss
new file mode 100644
index 0000000000..88e6b3f05a
--- /dev/null
+++ b/app/assets/stylesheets/users.scss
@@ -0,0 +1,32 @@
+// Place all the styles related to the users controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
+
+// .storename {
+// padding-top: 15px;
+// padding-bottom: 15px;
+// }
+//
+// .productinfo-container {
+// display: flex;
+// }
+//
+// .productinfo {
+// display: inline-flex;
+// }
+//
+// div h3, div ul {
+// // display: flex;
+// }
+
+li {
+ list-style-type: none;
+}
+
+
+// ===============================
+
+.table-head {
+ background-color: #3f6172;
+ color: white;
+}
diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb
new file mode 100644
index 0000000000..d672697283
--- /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 0000000000..0ff5442f47
--- /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 0000000000..1c21447d96
--- /dev/null
+++ b/app/controllers/application_controller.rb
@@ -0,0 +1,76 @@
+class ApplicationController < ActionController::Base
+ protect_from_forgery with: :exception
+ before_action :find_user
+ before_action :find_cart
+ before_action :set_session_to_cart
+
+
+ #
+ # def render_404
+ # raise ActionController::RoutingError.new('Not Found')
+ # end
+
+
+
+ private
+ def find_user
+ if session[:user_id]
+ @user = User.find_by(id: session[:user_id])
+ end
+ end
+
+
+
+ def find_cart
+ if @user #find auth_user cart
+ @pending_order = @user.find_pending_order
+ session[:pending_order_id] = @pending_order.id if @pending_order
+ if !(@pending_order) #make them one if they don't have
+ # @pending_order = Order.find_by(session_id: session[:session_id])
+ @pending_order = Order.new(session_id: session[:session_id])
+ @pending_order.user_id = @user.id
+ @pending_order.save
+ session[:pending_order_id] = @pending_order.id
+ end
+ else
+ if session[:pending_order_id] #find guest's current cart
+ @pending_order = Order.find(session[:pending_order_id])
+ else #make them one if they don't have
+ # @pending_order = new_pending_order(session[:session_id], nil)
+ @pending_order = Order.new
+ @pending_order.session_id = "guest_user"
+ # binding.pry
+ @pending_order.save
+ session[:pending_order_id] = @pending_order.id
+ end
+ end
+
+ end
+ def set_session_to_cart
+ @pending_order.session_id = session[:session_id]
+ @pending_order.save
+ end
+
+ # def not_found
+ # raise ActionController::RoutingError.new('Not Found')
+ # redirect_to root_path
+ # end
+ # this one is harder to test
+ # def render_404
+ # # DPR: supposedly this will actually render a 404 page in production
+ # raise ActionController::RoutingError.new('Not Found')
+ # end
+ # this one just gives 404 status, easier to test
+ def render_404
+ render file: "/public/404.html", status: 404
+ end
+
+
+ def new_pending_order(input_session_id, input_user_id)
+ new_order = Order.new
+ new_order.session_id = input_session_id
+ new_order.user_id = input_user_id
+ return new_order
+ end
+
+end
diff --git a/app/controllers/billing_data_controller.rb b/app/controllers/billing_data_controller.rb
new file mode 100644
index 0000000000..7756f0460b
--- /dev/null
+++ b/app/controllers/billing_data_controller.rb
@@ -0,0 +1,79 @@
+class BillingDataController < ApplicationController
+ before_action :find_billing, only: [:permission, :edit, :update, :show]
+ before_action :permission, only: [:edit, :update, :show]
+
+
+ def index
+ render render_404
+ end
+
+ def show
+ unless @billing_data
+ flash[:error] = "Billing data not found"
+ redirect_to root_path
+ end
+ end
+
+ def edit
+ unless @billing_data
+ redirect_to root_path
+ end
+ end
+
+ def update
+ if @billing_data.update_attributes billing_data_params
+ redirect_to billing_datum_path(@billing_data.id)
+ @billing_data.user = @user
+ else
+ flash[:result_text] = "Didn't save. Make sure your fields are complete!"
+ render :edit
+ end
+ end
+
+ def new
+ @user = session[:user_id]
+ @billing_data = BillingDatum.new
+
+ end
+
+ def create
+ @billing_data = BillingDatum.new billing_data_params
+ @billing_data.user = @user
+ if @billing_data.save
+ flash[:result_text] = "Does this look right?"
+ redirect_to billing_datum_path(@billing_data.id)
+ save_billing(@billing_data.id)
+ else
+ flash.now[:error] = "Could not create Billing Data"
+ render :new
+ end
+ end
+
+ private
+ def find_billing
+ @billing_data = BillingDatum.find_by(id: params[:id].to_i)
+ end
+
+ def save_billing(id)
+ @user = session[:user_id]
+ if @user
+ user = User.find_by(id: @user)
+ user.billing_datum_id = id
+ user.save
+ end
+
+ @pending_order.billing_datum_id = id
+ @pending_order.save
+ end
+
+ def billing_data_params
+ return params.require(:billing_datum).permit(:email, :mailing_address, :credit_card_name, :credit_card_number, :credit_card_cvv, :billing_zip_code, :expiration_date)
+ end
+
+ def permission
+ unless session[:user_id] == @billing_data.user_id || @pending_order.billing_datum_id == @billing_data.id
+ render render_404
+ end
+ end
+
+end
diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb
new file mode 100644
index 0000000000..37ae73d07b
--- /dev/null
+++ b/app/controllers/categories_controller.rb
@@ -0,0 +1,73 @@
+class CategoriesController < ApplicationController
+
+ def index
+ @categories = Category.order(:id)
+ @user = session[:user_id]
+ end
+
+ #show all products in a specific category
+ def show
+ @category = Category.find_by(id: params[:id])
+ unless @category
+ flash[:error] = "Category does not exist"
+ redirect_to root_path
+ end
+ end
+
+ #makes changes to a category that's already created
+ def edit
+ @category = Category.find_by(id: params[:id])
+ unless @category
+ redirect_to categories_path
+ end
+ end
+
+ def update
+ @category = Category.find_by(id: params[:id])
+ redirect_to categories_path unless @category
+
+ if @category.update_attributes category_params
+ flash[:success] = "Category edited successfully"
+ redirect_to categories_path
+ else
+ flash.now[:error] = "Category not edited successfully"
+ render :edit
+ end
+
+ end
+
+ #sign-in user can create a new category
+ def new
+ @category = Category.new
+ end
+
+ def create
+ @category = Category.new category_params
+ if @category.save
+ puts "SUCCESS"
+ flash[:success] = "Category created!"
+
+ redirect_to categories_path
+
+ else
+ puts "FAIL"
+ flash.now[:error] = "Could not create category"
+ render :new
+ end
+ end
+
+ #signed-in user can delete a category
+ def destroy
+ @category = Category.find_by(id: params[:id])
+ @category.destroy
+ flash[:status] = :success
+ flash[:result_text] = "Successfully destroyed category"
+ redirect_to categories_path
+ end
+
+ private
+
+ def category_params
+ return params.require(:category).permit(:name)
+ end
+end
diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb
new file mode 100644
index 0000000000..6e5ed150f9
--- /dev/null
+++ b/app/controllers/items_controller.rb
@@ -0,0 +1,64 @@
+class ItemsController < ApplicationController
+ def index
+ @item = Item.order(:id)
+ end
+
+
+ def show
+ @item = Item.find_by(id: params[:id])
+ puts params[:id]
+
+ # render_404 unless @item
+
+ unless @item
+ flash[:error] = "Item not found"
+ redirect_to root_path
+ end
+ end
+
+ def new
+ @item = Item.new
+ end
+
+ def create
+ # if !(Product.find_by(id: params[:id]))
+ # render_404
+ # return
+ # end
+ @item = Item.new(product_id: params[:id])
+ # binding.pry
+
+ if @item.save
+ # puts "success"
+ flash[:success] = "#{Product.find(params[:id]).name} item added successfully"
+ redirect_back(fallback_location: root_path)
+ else
+ # puts "fail"
+ # puts @item.errors.messages
+ flash.now[:error] = "Item not added to Product # #{params[:id]}"
+ redirect_to profile_path, status: 400
+ end
+ end
+
+ def destroy
+
+ if Item.where(product_id: params[:id]).length > 0
+ @item = Item.where(product_id: params[:id])
+ @item.last.destroy
+ redirect_back(fallback_location: root_path)
+
+ flash[:result_text] = "1 #{Product.find(params[:id]).name} removed from inventory!"
+
+ else
+ flash[:result_text] = "There are no more items to remove"
+ redirect_to profile_path, status: 400
+ end
+ end
+
+ private
+ # GM: This never gets called in this controller
+ # def item_params
+ # return params.require(:items).permit(:shipping_status, :purchase_status, :product_id, :order_id)
+ # end
+
+end
diff --git a/app/controllers/main_page_controller.rb b/app/controllers/main_page_controller.rb
new file mode 100644
index 0000000000..617b243dd8
--- /dev/null
+++ b/app/controllers/main_page_controller.rb
@@ -0,0 +1,4 @@
+class MainPageController < ApplicationController
+ def index
+ end
+end
diff --git a/app/controllers/order_products_controller.rb b/app/controllers/order_products_controller.rb
new file mode 100644
index 0000000000..d3777f4af6
--- /dev/null
+++ b/app/controllers/order_products_controller.rb
@@ -0,0 +1,105 @@
+class OrderProductsController < ApplicationController
+ def ship
+ find_entry
+ if !(@entry)
+ render_404
+ return
+ end
+ if @entry.items_shipped?
+ render_404
+ return
+ end
+ ship_items
+
+ end
+
+ # def create
+ # @cart_entry = OrderProduct.new(product_id: params[:id], order_id: @pending_order)
+ #
+ # if @cart_entry.save
+ # flash[:status] = :success
+ # flash[:result_text] = "Successfully added this to your cart!"
+ # redirect_to order_path(@pending_order)
+ # # redirect_to product_path(params[:id])
+ # end
+ # end
+
+ def update
+ sent_params = params
+ find_entry
+ if !@entry
+ render_404
+ return
+ end
+ old_quantity = @entry.quantity
+ sent_quantity = params[:order_product][:quantity].to_i
+ if sent_quantity == 0
+ flash[:result_text] = "Could not update #{@entry.product.name}. Make sure you are entering a number greater than 0. If you wanted to delete it, click delete from cart."
+ flash[:status] = :error
+ redirect_to cart_path, status: 400
+ return
+ end
+ @entry.quantity = sent_quantity
+ new_quantity = @entry.quantity
+ if @entry.save
+ flash[:status] = :success
+ flash[:result_text] = "Successfully updated #{@entry.product.name} from #{old_quantity} to #{new_quantity}! The params were #{sent_params} "
+ # redirect_to order_path(@pending_order)
+ redirect_to cart_path
+ else
+ flash[:result_text] = "Could not update #{@entry.product.name}. Please check errors."
+ flash[:messages] = @entry.errors
+ redirect_to cart_path
+ end
+ end
+
+ def destroy
+ find_entry
+ if !@entry
+ render_404
+ return
+ end
+ deleted_entry = "#{@entry.product.name}"
+ if @entry.destroy
+ flash[:success] = "Successfully deleted #{deleted_entry}."
+ redirect_to cart_path
+ else
+
+ end
+ end
+
+
+ private
+ def cart_entry_params
+ # params.require(:product).permit(:id, :name, :description, :price, :user)
+ end
+
+ def find_entry
+ @entry = OrderProduct.find_by(id: params[:id])
+ end
+
+ def ship_items
+ order = @entry.order
+ product = @entry.product
+ entry_items = []
+ order.items.each do |item|
+ entry_items << item if item.product_id == product.id
+ end
+ if entry_items.length > 0
+ entry_items.each do |item|
+ item.shipping_status = true
+ item.save
+ end
+ flash[:status] = :success
+
+ flash[:result_text] = "Successfully shipped entry #{@entry.id}!"
+ redirect_to order_fulfillment_path
+
+ else
+ flash[:result_text] = "There was an error with updating entry #{@entry.id}. There are no items associated with this order. Sorry."
+ flash[:status] = :error
+ redirect_to order_fulfillment_path
+
+ end
+ end
+end
diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb
new file mode 100644
index 0000000000..66ca83f626
--- /dev/null
+++ b/app/controllers/orders_controller.rb
@@ -0,0 +1,117 @@
+class OrdersController < ApplicationController
+ before_action :permission, except: [:show, :checkout]
+ before_action :view_order_permission, only: [:view]
+
+ def view
+ find_order
+ end
+
+
+ def show
+ @cart = @pending_order
+ end
+
+
+ def checkout
+ if mark_items_as_purchased
+ @cart = @pending_order
+ flash[:status] = :success
+ @pending_order.order_status = "paid"
+ @pending_order.save
+ session[:pending_order_id] = nil
+ find_cart
+ else
+ flash[:status] = :error
+ flash[:result_text] = "There was an error; you could not be checked out at this time"
+ redirect_back(fallback_location: cart_path)
+ end
+ end
+
+
+ # def add_product
+ # @cart_entry = OrderProduct.new(product_id: params[:id].to_i, order_id: @pending_order.id)
+ # if @cart_entry.save
+ # flash[:status] = :success
+ # flash[:result_text] = "Successfully added to your cart!"
+ # redirect_to order_path(@pending_order)
+ # redirect_to product_path(params[:id])
+ # else
+ # flash[:result_text] = "Could not add that product to your cart"
+ # flash[:messages] = @cart_entry.errors
+ # redirect_to root_path
+ # end
+ # end
+
+
+
+ private
+ def cart_entry_params
+ # params.require(:product).permit(:id, :name, :description, :price, :user)
+ end
+
+ def mark_items_as_purchased
+ entries = @pending_order.order_products
+ order_id = @pending_order.id
+ @items_for_purchase = []
+
+ entries.each do |entry|
+ if !(entry.valid?)
+ flash[:status] = :error
+ flash[:result_text] = "Check your cart, inventory has changed"
+ flash[:messages] = entry.errors
+ return false
+ end
+ quantity = entry.quantity
+ available_items = entry.product.available_items
+
+ quantity.times do
+ @items_for_purchase << available_items.pop
+ end
+ end
+
+ @items_for_purchase.each {|item| item.purchase(order_id)}
+
+
+ @items_for_purchase.each do |item|
+
+ if item.save
+ flash[:result_text] = "Items were saved."
+ else
+ # flash[:status] = :error
+ flash[:result_text] << "Items were not saved. Please contact web administrator. "
+ flash[:messages] = "There were errors"
+ # item.errors
+ # redirect_to cart_path
+ return
+ end
+
+ end
+ end
+
+ def find_order
+ # binding.pry
+ @order_for_view = Order.find(params[:id].to_i)
+ # binding.pry
+ end
+
+
+ def permission
+ unless @user
+ render_404
+ end
+ end
+
+ def view_order_permission
+ @order_for_view = Order.find(params[:id].to_i)
+ if @order_for_view
+ products = @order_for_view.order_products.map {|entry| entry.product}
+ # binding.pry
+ owners_of_products = []
+ products.each {|product| owners_of_products << product.user_id}
+ if !(owners_of_products.include? @user.id)
+ render_404
+ # return
+ end
+ end
+ end
+end
diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb
new file mode 100644
index 0000000000..5dc9c6a425
--- /dev/null
+++ b/app/controllers/products_controller.rb
@@ -0,0 +1,137 @@
+class ProductsController < ApplicationController
+ before_action :find_product, except: [:index, :new, :create]
+ before_action :permission, except: [:show, :index, :add_to_order]
+ before_action :owns, only: [:edit, :update]
+
+ def index
+ @products = Product.show_available
+ end
+
+ def show
+ unless @product
+ render_404
+ end
+ @current_user_is_not_product_owner = session[:user_id] != @product.user_id
+
+ @user = @product.user
+ end
+
+ def edit
+ if @product.id.nil?
+ render render_404
+ end
+ end
+
+ def update
+ unless @product
+ render render_404
+ end
+
+ @product.update_attributes product_params
+ if @product.save
+ flash[:status] = :success
+ flash[:result_text] = "Successfully updated #{@product.name}"
+ redirect_to profile_path(@user)
+ else
+ flash[:status] = :failure
+ flash[:result_text] = "Could not update #{@product.name}"
+ flash.now[:messages] = @product.errors.message
+ render :edit, status: :not_found
+ end
+ end
+
+ def new
+ @product = Product.new
+ end
+
+ def create
+ # as long as this exists: session[:user_id]
+ # product_params.user_id = session[:user_id]
+
+ @product = Product.new(product_params)
+ if @product.save
+ flash[:status] = :success
+ flash[:result_text] = "Successfully created product #{@product.id} #{@product.name}"
+ redirect_to profile_path(@user)
+ else
+ flash[:status] = :failure
+ flash[:result_text] = "Unable to create a product"
+ flash[:messages] = @product.errors.messages
+ render :new, status: :bad_request
+ end
+ end
+
+ def add_to_order
+ # binding.pry
+ @cart_entry = @pending_order.check_for_duplicates(@product.id)
+ if @cart_entry
+ @cart_entry.quantity += params[:quantity].to_i
+ else
+ @cart_entry = create_entry(params[:quantity])
+ end
+
+ if @cart_entry.save
+ flash[:status] = :success
+ flash[:result_text] = "Successfully added to your cart!"
+ # redirect_to order_path(@pending_order)
+ redirect_to product_path(@product.id)
+ else
+ flash[:result_text] = "Could not add that product to your cart"
+ flash[:messages] = @cart_entry.errors
+ redirect_to product_path(@product.id)
+ end
+ end
+
+ def change_visibility
+ if @product.visibility == false
+ @product.visibility = true
+ @product.save
+ flash[:result_text] = "Your product is now visible in browsing"
+ redirect_back(fallback_location: products_path)
+
+ else
+ # binding.pry
+ @product.visibility = false
+ @product.save
+ flash[:result_text] = "Your product is no longer visibile in browsing"
+ redirect_back(fallback_location: products_path)
+ end
+ end
+
+ private
+ def product_params
+ params.require(:product).permit(:name, :description, :product_photo, :user_id, :price, category_ids:[])
+ end
+
+ def entry_params
+ # params.require(:entry).permit(:quantity)
+ # return
+ end
+
+ def find_product
+ @product = Product.find_by(id: params[:id].to_i)
+ end
+
+
+ def permission
+ unless @user
+ render render_404
+ end
+ end
+
+ def owns
+ unless @product && @user.id == @product.user_id
+ render render_404
+ end
+ end
+
+
+ def create_entry(input_quantity)
+ entry = OrderProduct.new
+ entry.product_id = @product.id
+ entry.order_id = @pending_order.id
+ entry.quantity = input_quantity.to_i
+ return entry
+ end
+
+end
diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb
new file mode 100644
index 0000000000..839aa9726c
--- /dev/null
+++ b/app/controllers/reviews_controller.rb
@@ -0,0 +1,77 @@
+class ReviewsController < ApplicationController
+ # def index
+ # @reviews = Review.order(:id)
+ # end
+
+ # def show
+ # @review = Review.find_by(id: params[:id].to_i)
+ #
+ # unless @review
+ # flash[:error] = "Review not found"
+ # redirect_to root_path
+ # end
+ # end
+
+
+
+ # def edit
+ # @review = Review.find_by(id: params[:id].to_i)
+ # unless @review
+ # redirect_to root_path
+ # end
+ # end
+
+
+
+ # def update
+ # @review = Review.find_by(id: params[:id].to_i)
+ #
+ # if @review.update_attributes review_params
+ # redirect_to root_path
+ # else
+ # render :edit
+ # end
+ # end
+
+
+
+ def new
+ @review = Review.new
+ @product = Product.find_by(id: params[:product_id].to_i)
+ end
+
+
+
+ def create
+ @review = Review.new(review_params)
+ # puts "*********"
+ # puts "review = #{@review}"
+ # puts "review valid? = #{@review.valid?}"
+ #
+ # puts "*********"
+
+ if @review.save
+ redirect_to product_path(review_params[:product_id])
+ else
+ flash.now[:error] = "Could not create Review"
+ render :new
+ end
+ end
+
+
+
+ # def destroy
+ # @review = Review.find_by(id: params[:id].to_i)
+ # @review.destroy
+ # redirect_to root_path
+ # end
+
+
+
+ private
+
+ def review_params
+ return params.require(:review).permit(:user_id, :product_id, :text, :rating)
+ end
+
+end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
new file mode 100644
index 0000000000..e74bf6dfa6
--- /dev/null
+++ b/app/controllers/sessions_controller.rb
@@ -0,0 +1,62 @@
+class SessionsController < ApplicationController
+
+
+ def login_form
+ end
+
+ def not_logged_in
+ end
+
+ def login
+ username = params[:username]
+ if username && user = User.find_by(user: username)
+ session[:user_id] = user.id
+ flash[:status] = :success
+ flash[:result_text] = "Successfully logged in as #{@user.username}"
+ redirect_to root_path
+ else
+ user = User.new(username: username)
+ if user.save
+ session[:user_id] = @user.id
+ flash[:success] = "Successfully created user: #{@user.username}"
+ redirect_to root_path
+ else
+ flash.now[:status] = :failure
+ flash.now[:result_text] = "Could not log in"
+ flash.now[:messages] = users.errors.messages
+ render "login_form", status: bad_request
+ end
+ end
+ end
+
+ def create
+ @auth_hash = request.env['omniauth.auth']
+ # ap @auth_hash
+
+ @user = User.find_by(uid: @auth_hash['uid'], provider: @auth_hash['provider'])
+
+ if @user
+ session[:user_id] = @user.id
+ flash[:result_text] = "#{@user.username} has been logged in!"
+
+ else
+ @user = User.new(uid: @auth_hash['uid'], provider: @auth_hash['provider'], email: @auth_hash['info']['email'], username: @auth_hash['info']['nickname'])
+ @user.save
+ if @user.save
+ session[:user_id] = @user.id
+ flash[:result_text] = "#{@user.username} has been logged in!"
+ else
+ flash[:result_text] = "Unable to save user!"
+ end
+ end
+ redirect_to root_path
+ end
+
+ def logout
+ session[:user_id] = nil
+ flash[:result_text] = "Successfully logged out!"
+ session[:pending_order_id] = nil
+
+ redirect_to root_path
+ end
+end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
new file mode 100644
index 0000000000..94417b4021
--- /dev/null
+++ b/app/controllers/users_controller.rb
@@ -0,0 +1,105 @@
+class UsersController < ApplicationController
+ before_action :permission, except: [:index, :show]
+
+ # def new
+ # @user = User.new
+ # end
+
+ def index
+ @users = []
+ User.all.each do |user|
+ if user.products.length > 0
+ @users.push(user)
+ end
+ end
+ return @users
+ end
+
+ def show
+ @user = User.find_by(id: params[:id].to_i)
+ # render_404 unless @user
+
+ unless @user
+ flash[:error] = "User not found"
+ redirect_to root_path
+ end
+ end
+
+ # def create
+ # @user = User.new user_params
+ #
+ # if @user.save
+ # flash[:success] = "User added successfully"
+ # redirect_to root_path
+ # else
+ # flash.now[:error] = "User not added"
+ # render :new
+ # end
+ # end
+
+
+ # def login
+ # end
+
+ # def update
+ # @user = User.find_by(id: params[:id].to_i)
+ # redirect_to root_path
+ #
+ # unless @user
+ # redirect_to users_path
+ # end
+ # end
+
+ def profile
+ @user = @user
+ end
+
+ def order_fulfillment
+ @entries = @user.merchant_entries
+ organize_entries if @entries
+
+ end
+
+
+ # TODO if the user is to be deleted, me must then delete all of there products.
+ # def destroy
+ # @user = User.find_by(id: params[:id])
+ # @user.destroy
+ #
+ # redirect_to root_path
+ # end
+
+# ---------------------------------------
+ # def edit
+ # end
+# ---------------------------------------
+
+
+
+ private
+
+ # def user_params
+ # return params.require(:users).permit(:username, :email)
+ # end
+
+ def permission
+ if !(@user)
+ render_404
+ end
+ end
+
+ def render_404
+ render file: "/public/404.html", status: 404
+ end
+
+ def organize_entries
+ @paid_entries = @user.paid_entries
+ @shipped_entries = @user.shipped_entries
+ @canceled_entries = @user.canceled_entries
+ # @entries.each do |entry|
+ # @paid_entries << entry if entry.paid?
+ # @shipped_entries << entry if entry.shipped?
+ # @canceled_entries << entry if entry.canceled?
+ # end
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
new file mode 100644
index 0000000000..a83dad11bf
--- /dev/null
+++ b/app/helpers/application_helper.rb
@@ -0,0 +1,25 @@
+module ApplicationHelper
+ def readable_date(date)
+ ("" + date.strftime("%b %d %Y") + "").html_safe
+ end
+
+ def readable_money(money)
+ #10 => $10.00
+ #10.0 => $10.00
+ #10.00 => $10.00
+ #10.3333 => $10.33
+ if !money
+ return "$0.00"
+ end
+ money = money.to_s
+ if money[-3] == "."
+ return "$#{money}"
+ elsif money[-2..-1] == ".0"
+ return "$#{money}0"
+ elsif
+ money[-3..-1] == ".00"
+ return "$#{money}"
+ else
+ end
+ end
+end
diff --git a/app/helpers/billing_data_helper.rb b/app/helpers/billing_data_helper.rb
new file mode 100644
index 0000000000..2fbe44319c
--- /dev/null
+++ b/app/helpers/billing_data_helper.rb
@@ -0,0 +1,2 @@
+module BillingDataHelper
+end
diff --git a/app/helpers/categories_helper.rb b/app/helpers/categories_helper.rb
new file mode 100644
index 0000000000..e06f31554c
--- /dev/null
+++ b/app/helpers/categories_helper.rb
@@ -0,0 +1,2 @@
+module CategoriesHelper
+end
diff --git a/app/helpers/items_helper.rb b/app/helpers/items_helper.rb
new file mode 100644
index 0000000000..cff0c9fe21
--- /dev/null
+++ b/app/helpers/items_helper.rb
@@ -0,0 +1,2 @@
+module ItemsHelper
+end
diff --git a/app/helpers/main_page_helper.rb b/app/helpers/main_page_helper.rb
new file mode 100644
index 0000000000..4810c2f081
--- /dev/null
+++ b/app/helpers/main_page_helper.rb
@@ -0,0 +1,2 @@
+module MainPageHelper
+end
diff --git a/app/helpers/order_products_helper.rb b/app/helpers/order_products_helper.rb
new file mode 100644
index 0000000000..fb2828b523
--- /dev/null
+++ b/app/helpers/order_products_helper.rb
@@ -0,0 +1,2 @@
+module OrderProductsHelper
+end
diff --git a/app/helpers/orders_helper.rb b/app/helpers/orders_helper.rb
new file mode 100644
index 0000000000..443227fd48
--- /dev/null
+++ b/app/helpers/orders_helper.rb
@@ -0,0 +1,2 @@
+module OrdersHelper
+end
diff --git a/app/helpers/products_helper.rb b/app/helpers/products_helper.rb
new file mode 100644
index 0000000000..ab5c42b325
--- /dev/null
+++ b/app/helpers/products_helper.rb
@@ -0,0 +1,2 @@
+module ProductsHelper
+end
diff --git a/app/helpers/reviews_helper.rb b/app/helpers/reviews_helper.rb
new file mode 100644
index 0000000000..682b7b1abc
--- /dev/null
+++ b/app/helpers/reviews_helper.rb
@@ -0,0 +1,2 @@
+module ReviewsHelper
+end
diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb
new file mode 100644
index 0000000000..309f8b2eb3
--- /dev/null
+++ b/app/helpers/sessions_helper.rb
@@ -0,0 +1,2 @@
+module SessionsHelper
+end
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
new file mode 100644
index 0000000000..2310a240d7
--- /dev/null
+++ b/app/helpers/users_helper.rb
@@ -0,0 +1,2 @@
+module UsersHelper
+end
diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb
new file mode 100644
index 0000000000..a009ace51c
--- /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 0000000000..286b2239d1
--- /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 0000000000..10a4cba84d
--- /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/billing_datum.rb b/app/models/billing_datum.rb
new file mode 100644
index 0000000000..41d7344a22
--- /dev/null
+++ b/app/models/billing_datum.rb
@@ -0,0 +1,14 @@
+class BillingDatum < ApplicationRecord
+ has_many :orders
+ belongs_to :user, optional: true
+
+ validates :email, presence: true
+ validates :mailing_address, presence: true
+ validates :credit_card_name, presence: true
+ validates :credit_card_number, presence: true
+ validates :credit_card_cvv, presence: true
+ validates :billing_zip_code, presence: true
+ # validates :expiration_date, presence: true
+
+
+end
diff --git a/app/models/category.rb b/app/models/category.rb
new file mode 100644
index 0000000000..a64dfca32e
--- /dev/null
+++ b/app/models/category.rb
@@ -0,0 +1,21 @@
+class Category < ApplicationRecord
+ # add through: to associate join table
+ has_and_belongs_to_many :products, through: :categories_products
+ validates :name, presence: true
+ validates :name, uniqueness: true
+
+ # before_validation :fix_category
+
+
+ # private
+ # def fix_category
+ # if self.category
+ # self.category = self.category.downcase.singularize
+ # end
+ # end
+
+ #TODO Julia removed the below method because it is a duplicate of a method in the product class (where it belongs)
+ # def show_available
+ # Product.where(visibility: true)
+ # end
+end
diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/app/models/item.rb b/app/models/item.rb
new file mode 100644
index 0000000000..d11bc8d0c7
--- /dev/null
+++ b/app/models/item.rb
@@ -0,0 +1,30 @@
+class Item < ApplicationRecord
+ belongs_to :product
+ belongs_to :order, optional: true
+ validates :shipping_status, inclusion: {in: [true,false]}
+ validates :purchase_status, inclusion: {in: [true,false]}
+
+ def purchase(input_order_id)
+ if self.purchase_status != false
+ self.errors[:order_id] << "does not match item. This items is tied to order #{self.order_id}, you were trying to ship it for #{input_order_id}."
+ return false
+ else
+ self.order_id = input_order_id
+ self.purchase_status = true
+ return true
+ end
+ end
+
+ def ship(input_order_id)
+ if self.purchase_status != true
+ self.errors[:purchase_status] << "Cannot ship an unpurchased item. Please make sure item is purchased before shipping."
+ return false
+ elsif input_order_id != self.order_id
+ self.errors[:order_id] << "does not match item. This items is tied to order #{self.order_id}, you were trying to ship it for #{input_order_id}."
+ return false
+ else
+ self.purchase_status = true
+ return true
+ end
+ end
+end
diff --git a/app/models/order.rb b/app/models/order.rb
new file mode 100644
index 0000000000..3ff3f6c427
--- /dev/null
+++ b/app/models/order.rb
@@ -0,0 +1,97 @@
+class Order < ApplicationRecord
+ belongs_to :billing_datum, optional: true
+ has_many :order_products
+ has_many :items
+ belongs_to :user, optional: true
+ validates :session_id, presence: true
+ validates :order_status, presence: true
+ validate :has_billing_datum?
+ validate :has_valid_order_status?
+ # validate :has_valid_order_products?
+
+
+ def sub_total
+ entries = self.order_products
+ sub_total = 0
+ entries.each do |entry|
+ unit_price = entry.product.price
+ entry_cost = unit_price * entry.quantity
+ sub_total += entry_cost
+ end
+ return sub_total
+ end
+
+ def tax_amount
+ sub_total = self.sub_total
+ tax = sub_total * 0.0887
+ return tax
+ end
+
+ def taxed_total
+ tax = self.tax_amount
+ sub_total = self.sub_total
+ return sub_total + tax
+ end
+
+ def has_billing_datum?
+ if self.order_status != "pending"
+ self.errors[:billing_datum_id] << "is missing. Please entire valid billing information." if !(self.billing_datum_id)
+ end
+ end
+
+ def has_valid_order_status?
+ valid_statuses = ["pending", "paid", "shipped", "canceled"]
+ if !(valid_statuses.include? self.order_status)
+ self.errors[:order_status] << "is invalid."
+ end
+ end
+
+ def has_invalid_entries?
+ invalid_entries = []
+ order_products = self.order_products
+ order_products.each do |entry|
+ invalid_entries << entry if !(entry.valid?)
+ end
+ if invalid_entries.first != nil
+ self.errors[:entries] << "are invalid."
+ #TODO: Julia took out below line. Does not seem needed. Also, sytnax is incorrect- does not use variable entry in ternary.
+
+ invalid_entries.each {|entry| self.errors[:entries] << entry.errors}
+
+ return true #is NOT a valid order
+ else
+ return false #is a valid order
+ end
+ end
+
+ def entries_by_product
+ entries_by_product = self.order_products.group_by {|entry| entry.product_id}
+ return entries_by_product
+ end
+
+ #used in the controller method add_to_order.
+ #If there is already a productorder in the cart that has the same product_id, this method will return the product_order object. If there is no duplicate, it will return false.
+ def check_for_duplicates(input_product_id)
+ entries = self.entries_by_product
+ if entries[input_product_id]
+ return entries[input_product_id][0]
+ else
+ return false
+ end
+ end
+
+ #gets called if check_for_duplicates returns true
+ #TODO: Julia removed below method. Does not appear to be applied in any part of the project.
+ # def combine_entries(entry_id)
+ # entries = self.entries_by_product
+ # product = entry.product
+ # end
+
+ #TODO: Julia removed below method. Does not appear to be applied in any part of the project. Also repeats the logic of the above has_invalid_entries? method above
+ # def has_valid_order_products
+ # entries = self.order_products
+ # entries.each { |entry| return false if !(entry.valid?)}
+ # return true
+ # end
+
+end
diff --git a/app/models/order_product.rb b/app/models/order_product.rb
new file mode 100644
index 0000000000..32441a0f66
--- /dev/null
+++ b/app/models/order_product.rb
@@ -0,0 +1,78 @@
+class OrderProduct < ApplicationRecord
+ belongs_to :order
+ belongs_to :product
+ validates :quantity, presence: true
+ validates :quantity, numericality: { only_integer: true }
+ validates :quantity, numericality: { greater_than: 0 }
+ validate :items_available?
+
+ def items_available?
+ product = self.product
+ quantity = self.quantity
+ return false if !(product.num_available)
+ if product.num_available >= quantity
+ return true
+ else
+ self.errors[:quantity] << "is invalid. There are currently only #{product.num_available} of #{product.name}. Please update your order."
+ end
+ return false
+ end
+
+ def pending?
+ order = self.order
+ # binding.pry
+ if order.order_status == "pending"
+ return true
+ else
+ return false
+ end
+ end
+
+ def paid?
+ order = self.order
+ if order.order_status == "paid"
+ return true
+ else
+ return false
+ end
+ end
+
+ def canceled?
+ order = self.order
+ if order.order_status == "canceled"
+ return true
+ else
+ return false
+ end
+ end
+
+ def shipped?
+ order = self.order
+ if order.order_status == "shipped"
+ return true
+ else
+ return false
+ end
+ end
+
+ def subtotal
+ return (self.quantity) * (self.product.price)
+ end
+
+ def items_shipped?
+ order = self.order
+ entry_items = []
+ if order
+ order.items.each do |item|
+ entry_items << item if item.product_id == product.id
+ end
+ if entry_items
+ entry_items.each do |item|
+ return true if item.shipping_status #if item has been shipped, return true
+ end
+ end
+ return false
+ end
+ end
+
+end
diff --git a/app/models/product.rb b/app/models/product.rb
new file mode 100644
index 0000000000..41cc83b2f9
--- /dev/null
+++ b/app/models/product.rb
@@ -0,0 +1,37 @@
+class Product < ApplicationRecord
+ has_many :reviews
+ has_many :items
+ belongs_to :user
+ # add through: to associate join table
+ has_and_belongs_to_many :categories, through: :categories_products
+ validates :user_id, presence: true
+ validates :name, uniqueness: true
+ validates :name, presence: true
+ validates :price, presence: true
+ # validates :category_id, presence: true
+ validates :price, numericality: {greater_than: 0}
+ validates :visibility, inclusion: {in: [true,false]}
+
+ def num_available
+ available = available_items
+ if available
+ return available.length
+ else
+ return 0
+ end
+ end
+
+ def available_items
+ available = []
+ self.items.each do |item|
+ available << item if !(item.shipping_status) && !(item.purchase_status)
+ end
+ return available if available.first != nil
+ return false
+ end
+
+ def self.show_available
+ Product.where(visibility: true)
+ end
+
+end
diff --git a/app/models/review.rb b/app/models/review.rb
new file mode 100644
index 0000000000..1b2004b3df
--- /dev/null
+++ b/app/models/review.rb
@@ -0,0 +1,8 @@
+class Review < ApplicationRecord
+ belongs_to :user, optional: true
+ belongs_to :product
+ validates :rating, numericality: { only_integer: true, greater_than: 0, less_than: 6 }
+ validates :rating, presence: true
+
+
+end
diff --git a/app/models/user.rb b/app/models/user.rb
new file mode 100644
index 0000000000..253cefc9ec
--- /dev/null
+++ b/app/models/user.rb
@@ -0,0 +1,145 @@
+class User < ApplicationRecord
+ has_many :products
+ has_many :orders
+ has_many :reviews
+
+ belongs_to :billing_datum, optional: true
+
+ validates :username, presence: true
+ validates :username, uniqueness: true
+ validates :email, presence: true, uniqueness: true
+
+ def merchant_entries
+ products = self.products
+ merchant_entries = []
+ products.each do |product|
+ entries = OrderProduct.where(product_id: product.id)
+ entries.each { |entry| merchant_entries << entry if !(entry.pending?)}
+ end
+ return merchant_entries if merchant_entries.first != nil
+ return false
+ end
+
+ def paid_entries
+ entries = self.merchant_entries
+ paid_entries = []
+ return false if !(entries)
+ entries.each do |entry|
+ paid_entries << entry if entry.paid?
+ end
+ return paid_entries if paid_entries.first != nil
+ return false
+ end
+
+
+ def shipped_entries
+ entries = self.merchant_entries
+ shipped_entries = []
+ return false if !(entries)
+ entries.each do |entry|
+ shipped_entries << entry if entry.shipped?
+ end
+ return shipped_entries if shipped_entries.first != nil
+ return false
+ end
+
+ def canceled_entries
+ entries = self.merchant_entries
+ canceled_entries = []
+ return false if !(entries)
+ entries.each do |entry|
+ canceled_entries << entry if entry.canceled?
+ end
+ return canceled_entries if canceled_entries.first != nil
+ return false
+ end
+
+ def canceled_revenue
+ entries = canceled_entries
+ subtotal = 0
+ if entries
+ entries.each do |entry|
+ subtotal += entry.subtotal
+ end
+ end
+ return subtotal
+ end
+
+ def shipped_revenue
+ entries = shipped_entries
+ subtotal = 0
+ if entries
+ entries.each do |entry|
+ subtotal += entry.subtotal
+ end
+ end
+ return subtotal
+ end
+
+
+ def paid_revenue
+ entries = paid_entries
+ subtotal = 0
+ if entries
+ entries.each do |entry|
+ subtotal += entry.subtotal
+ end
+ end
+ return subtotal
+ end
+
+ def total_revenue
+ subtotal = 0
+ paid_amount = paid_revenue
+ shipped_amount = shipped_revenue
+ subtotal = paid_amount + shipped_amount
+ return subtotal
+ end
+
+ def find_pending_order #synonymous to cart
+ pending_orders = []
+ self.orders.each do |order|
+ if order.order_status == "pending"
+ pending_orders << order
+ end
+ end
+
+ #TODO- Question from Julia- Why would a user have multiple pending orders? If they sign in as a user and add to cart, and then logout and add some to a new cart, then sign back in?
+ if pending_orders.length > 0
+ return pending_orders.first
+ else
+ return false
+ end
+ end
+
+ #TODO-Question from Julia- I think we can remove this method. It is not referenced anywhere in the project.
+ # def has_products
+ # has_products = []
+ # User.all.each do |user|
+ # if user.products.length > 0
+ # has_products.push(user)
+ # end
+ # end
+ # return has_products
+ # end
+
+ #TODO- Question from Julia- This method is shown in two places: here and in the application model. I think we can remove it here.
+ def show_available
+ Product.where(visibility: true)
+ end
+
+ def has_past_orders?
+ past_orders = []
+ self.orders.each do |order|
+ if order.order_status == "paid" || order.order_status == "shipped" || order.order_status == "canceled"
+ past_orders << order
+ end
+ end
+ if past_orders.length >= 1
+ return true
+ else
+ return false
+ end
+ end
+
+end
diff --git a/app/views/billing_data/_form.html.erb b/app/views/billing_data/_form.html.erb
new file mode 100644
index 0000000000..59b9c41f9f
--- /dev/null
+++ b/app/views/billing_data/_form.html.erb
@@ -0,0 +1,33 @@
+Enter your Billing Data
+
+ <%= form_for @billing_data do |f| %>
+
+ <% f.hidden_field :user_id, value: @user %>
+
+ <%= f.label :email %>
+ <%= f.text_field :email%>
+
+ <%= f.label :cred_card_name %>
+ <%= f.text_field :credit_card_name %>
+
+ <%= f.label :mailing_address %>
+ <%= f.text_field :mailing_address%>
+
+ <%= f.label :credit_card_number%>
+ <%= f.text_field :credit_card_number%>
+
+ <%= f.label :credit_card_cvv%>
+ <%= f.text_field :credit_card_cvv%>
+
+ <%= f.label :billing_zip_code%>
+ <%= f.text_field :billing_zip_code%>
+
+ <%= f.label :expiration_date %>
+ <%= f.text_field :expiration_date %>
+
+ <%= f.submit "Submit Payment Information" %>
+ <%end%>
+
+
Find me in app/views/billing_data/create.html.erb
diff --git a/app/views/billing_data/destroy.html.erb b/app/views/billing_data/destroy.html.erb new file mode 100644 index 0000000000..421c69f891 --- /dev/null +++ b/app/views/billing_data/destroy.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/billing_data/destroy.html.erb
diff --git a/app/views/billing_data/edit.html.erb b/app/views/billing_data/edit.html.erb new file mode 100644 index 0000000000..f1e16d3aac --- /dev/null +++ b/app/views/billing_data/edit.html.erb @@ -0,0 +1,2 @@ + +<%= render partial: "form", local: {button_name: "Update Billing Information"} %> diff --git a/app/views/billing_data/index.html.erb b/app/views/billing_data/index.html.erb new file mode 100644 index 0000000000..092796e6f6 --- /dev/null +++ b/app/views/billing_data/index.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/billing_data/index.html.erb
diff --git a/app/views/billing_data/new.html.erb b/app/views/billing_data/new.html.erb new file mode 100644 index 0000000000..04a5c820a8 --- /dev/null +++ b/app/views/billing_data/new.html.erb @@ -0,0 +1 @@ +<%= render partial: "form", local: {button_name: "Add Billing Information"} %> diff --git a/app/views/billing_data/show.html.erb b/app/views/billing_data/show.html.erb new file mode 100644 index 0000000000..36510ee56c --- /dev/null +++ b/app/views/billing_data/show.html.erb @@ -0,0 +1,45 @@ +<%= link_to "Edit Billing Information", edit_billing_datum_path(@billing_data.id), class:"button" %> +<%= link_to "Confirm Order", checkout_path, class:"button"%> + + +| Required | +Your Info | +
|---|---|
| Email Address | +<%= @billing_data.email %> | +
| Name on Card | +<%= @billing_data.credit_card_name %> | +
| Mailing Address | +<%= @billing_data.mailing_address %> | +
| Credit Card Number | +<%= @billing_data.credit_card_number %> | +
| CVV | +<%= @billing_data.credit_card_cvv %> | +
| Billing Zipcode | +<%= @billing_data.billing_zip_code %> | +
Find me in app/views/billing_data/update.html.erb
diff --git a/app/views/categories/_form.html.erb b/app/views/categories/_form.html.erb new file mode 100644 index 0000000000..89e797aa32 --- /dev/null +++ b/app/views/categories/_form.html.erb @@ -0,0 +1,8 @@ + + + <%= form_for @category do |f| %> + <%= f.label :name %> + <%= f.text_field :name %> + + <%= f.submit "submit", class:"button"%> + <% end %> diff --git a/app/views/categories/create.html.erb b/app/views/categories/create.html.erb new file mode 100644 index 0000000000..63069b0005 --- /dev/null +++ b/app/views/categories/create.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/categories/create.html.erb
diff --git a/app/views/categories/destroy.html.erb b/app/views/categories/destroy.html.erb new file mode 100644 index 0000000000..a6ac971f4c --- /dev/null +++ b/app/views/categories/destroy.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/categories/destroy.html.erb
diff --git a/app/views/categories/edit.html.erb b/app/views/categories/edit.html.erb new file mode 100644 index 0000000000..3b8dca3af4 --- /dev/null +++ b/app/views/categories/edit.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/categories/edit.html.erb
diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb new file mode 100644 index 0000000000..b2d17b5e38 --- /dev/null +++ b/app/views/categories/index.html.erb @@ -0,0 +1,16 @@ +Find me in app/views/categories/update.html.erb
diff --git a/app/views/items/create.html.erb b/app/views/items/create.html.erb new file mode 100644 index 0000000000..8587edb798 --- /dev/null +++ b/app/views/items/create.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/items/create.html.erb
diff --git a/app/views/items/destroy.html.erb b/app/views/items/destroy.html.erb new file mode 100644 index 0000000000..73d722058f --- /dev/null +++ b/app/views/items/destroy.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/items/destroy.html.erb
diff --git a/app/views/items/edit.html.erb b/app/views/items/edit.html.erb new file mode 100644 index 0000000000..22db65db6e --- /dev/null +++ b/app/views/items/edit.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/items/edit.html.erb
diff --git a/app/views/items/index.html.erb b/app/views/items/index.html.erb new file mode 100644 index 0000000000..f2c7d9dfbc --- /dev/null +++ b/app/views/items/index.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/items/index.html.erb
diff --git a/app/views/items/new.html.erb b/app/views/items/new.html.erb new file mode 100644 index 0000000000..014c188862 --- /dev/null +++ b/app/views/items/new.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/items/new.html.erb
diff --git a/app/views/items/show.html.erb b/app/views/items/show.html.erb new file mode 100644 index 0000000000..5b60ef3f9a --- /dev/null +++ b/app/views/items/show.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/items/show.html.erb
diff --git a/app/views/items/update.html.erb b/app/views/items/update.html.erb new file mode 100644 index 0000000000..4ca8103407 --- /dev/null +++ b/app/views/items/update.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/items/update.html.erb
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb new file mode 100644 index 0000000000..140d6328cd --- /dev/null +++ b/app/views/layouts/application.html.erb @@ -0,0 +1,74 @@ + + + + + ++ Your order has been completed! The status is: <%= @pending_order.order_status %>. Your products should ship shortly! Thanks for shopping at NorthWesty! +
+ +| Item | +Quantity | +Cart Subtotal | +Shipment Status | +
|---|---|---|---|
| <%= link_to entry.product.name, product_path(entry.product.id)%> | +<%= entry.quantity %> | +<%= readable_money(entry.product.price.round(2))%> | +<%= @items_for_purchase.first.shipping_status %> | +
| + | + | <%= @cart.taxed_total%> | ++ |
Find me in app/views/orders/create.html.erb
diff --git a/app/views/orders/destroy.html.erb b/app/views/orders/destroy.html.erb new file mode 100644 index 0000000000..d14d0a3508 --- /dev/null +++ b/app/views/orders/destroy.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/orders/destroy.html.erb
diff --git a/app/views/orders/edit.html.erb b/app/views/orders/edit.html.erb new file mode 100644 index 0000000000..7de9049bee --- /dev/null +++ b/app/views/orders/edit.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/orders/edit.html.erb
diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb new file mode 100644 index 0000000000..d63a69fb54 --- /dev/null +++ b/app/views/orders/index.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/orders/index.html.erb
diff --git a/app/views/orders/new.html.erb b/app/views/orders/new.html.erb new file mode 100644 index 0000000000..1bc27609ce --- /dev/null +++ b/app/views/orders/new.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/orders/new.html.erb
diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb new file mode 100644 index 0000000000..fffef13dd6 --- /dev/null +++ b/app/views/orders/show.html.erb @@ -0,0 +1,64 @@ + +| Product | +Unit Cost | +Quantity | +Product Subtotal | +Update Quantity | +Delete Item | +
|---|---|---|---|---|---|
| <%= entry.product.name %> | +<%= readable_money(entry.product.price.round(2)) %> | +<%= entry.quantity %> | +<%=readable_money(entry.subtotal.round(2)) %> | +<%= form_for entry, url: order_product_path(entry.id), method: :patch do |f| %> + <%# f.label :quantity %> + <%= f.text_field :quantity %> + <%= f.submit "Update Quantity", class:"button"%> + <% end %> + | +<%= link_to "Delete Item", order_product_path(entry.id), method: :delete, data: {confirm: "Are you sure you want to remove #{entry.product.name} from cart?"}, class:"button" %> | + +
Find me in app/views/orders/update.html.erb
diff --git a/app/views/orders/view.html.erb b/app/views/orders/view.html.erb new file mode 100644 index 0000000000..75a3cc5f97 --- /dev/null +++ b/app/views/orders/view.html.erb @@ -0,0 +1,48 @@ +| + Name: + | ++ <%= @order_for_view.billing_datum.credit_card_name %> + | +
|---|---|
| + Email: + | ++ <%= @order_for_view.billing_datum.email %> + | +
| + Mailing Address: + | ++ <%= @order_for_view.billing_datum.mailing_address %> + | +
| + Last 4 Digits of Credit Card: + | ++ <%=@order_for_view.billing_datum.credit_card_number.last(4)%> + | +
| + Credit Card Expiration Date: + | ++ <%if @order_for_view.billing_datum.expiration_date != nil%> + <%= @order_for_view.billing_datum.expiration_date %> + <% else %> + this billing info was created before expiration date was collected + <% end %> + | +
Find me in app/views/products/create.html.erb
+ +<%= params %> +Find me in app/views/products/destroy.html.erb
diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb new file mode 100644 index 0000000000..004ea0b165 --- /dev/null +++ b/app/views/products/edit.html.erb @@ -0,0 +1,3 @@ +| Rating | +Review Summary | +
|---|---|
| Rating: <%= review.rating %> / 5 | +<%= review.text %> | +
Find me in app/views/products/update.html.erb
diff --git a/app/views/reviews/_form.html.erb b/app/views/reviews/_form.html.erb new file mode 100644 index 0000000000..e30ebe5776 --- /dev/null +++ b/app/views/reviews/_form.html.erb @@ -0,0 +1,32 @@ +Find me in app/views/reviews/create.html.erb
diff --git a/app/views/reviews/destroy.html.erb b/app/views/reviews/destroy.html.erb new file mode 100644 index 0000000000..df58c59d5c --- /dev/null +++ b/app/views/reviews/destroy.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/reviews/destroy.html.erb
diff --git a/app/views/reviews/edit.html.erb b/app/views/reviews/edit.html.erb new file mode 100644 index 0000000000..28034f5e02 --- /dev/null +++ b/app/views/reviews/edit.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/reviews/edit.html.erb
diff --git a/app/views/reviews/index.html.erb b/app/views/reviews/index.html.erb new file mode 100644 index 0000000000..d19455779d --- /dev/null +++ b/app/views/reviews/index.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/reviews/index.html.erb
diff --git a/app/views/reviews/new.html.erb b/app/views/reviews/new.html.erb new file mode 100644 index 0000000000..c25225e1f7 --- /dev/null +++ b/app/views/reviews/new.html.erb @@ -0,0 +1 @@ +<%= render partial: "form", locals: {button_name: "New Review"} %> diff --git a/app/views/reviews/show.html.erb b/app/views/reviews/show.html.erb new file mode 100644 index 0000000000..68d8d94c3b --- /dev/null +++ b/app/views/reviews/show.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/reviews/show.html.erb
diff --git a/app/views/reviews/update.html.erb b/app/views/reviews/update.html.erb new file mode 100644 index 0000000000..7d46cbed5c --- /dev/null +++ b/app/views/reviews/update.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/reviews/update.html.erb
diff --git a/app/views/users/create.html.erb b/app/views/users/create.html.erb new file mode 100644 index 0000000000..48ea02e600 --- /dev/null +++ b/app/views/users/create.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/users/create.html.erb
diff --git a/app/views/users/destroy.html.erb b/app/views/users/destroy.html.erb new file mode 100644 index 0000000000..de4bd26343 --- /dev/null +++ b/app/views/users/destroy.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/users/destroy.html.erb
diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb new file mode 100644 index 0000000000..1881fbdba0 --- /dev/null +++ b/app/views/users/edit.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/users/edit.html.erb
diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb new file mode 100644 index 0000000000..22de8bc451 --- /dev/null +++ b/app/views/users/index.html.erb @@ -0,0 +1,9 @@ + +Find me in app/views/users/new.html.erb
diff --git a/app/views/users/order_fulfillment.html.erb b/app/views/users/order_fulfillment.html.erb new file mode 100644 index 0000000000..acacc7ca43 --- /dev/null +++ b/app/views/users/order_fulfillment.html.erb @@ -0,0 +1,238 @@ +| + Paid Orders + | ++ Shipped Orders + | ++ Canceled Orders + | ++ <%= readable_money(@user.paid_revenue.round(2)) %> + | ++ <%= readable_money(@user.shipped_revenue.round(2)) %> + | ++ <%= readable_money(@user.canceled_revenue.round(2)) %> + | +
|---|
| + Paid Orders + | ++ Shipped Orders + | ++ Canceled Orders + | ++ <%= @paid_entries ? @paid_entries.length : 0 %> + | ++ <%= @shipped_entries ? @shipped_entries.length : 0%> + | ++ <%= @canceled_entries ? @canceled_entries.length : 0%> + | +
|---|
+ These items have been purchased and need to be shipped. +
+| + Order Number + | ++ Date of Order + | ++ Product Name + | ++ Quantity + | ++ Subtotal + | ++ Order Status: + | ++ Shipping Action + | + +
|---|---|---|---|---|---|---|
| + <%= link_to entry.order.id, view_order_path(entry.order.id) %> + | ++ <%= readable_date(entry.order.updated_at) %> + | ++ <%= link_to(entry.product.name, product_path(entry.product.id)) %> + | ++ <%= entry.quantity %> + | ++ <%= readable_money(entry.subtotal.round(2)) %> + | ++ <%= entry.order.order_status %> + | ++ <% if entry.items_shipped? %> + shipped + <% else %> + <%= link_to "Ship", ship_path(entry.id), method: :post, class:"button" %> + <% end %> + | +
+ No orders currently require your attention. Check back later. +
+ <% end %> ++ These items have been shipped +
+| + Order Number + | ++ Date of Order + | ++ Product Name + | ++ Quantity + | ++ Subtotal + | ++ Order Status: + | +
|---|---|---|---|---|---|
| + <%#= entry.order.id %> + <%= link_to entry.order.id, view_order_path(entry.order.id) %> + | ++ <%= readable_date(entry.order.updated_at) %> + | ++ <%= link_to(entry.product.name, product_path(entry.product.id)) %> + | ++ <%= entry.quantity %> + | ++ <%= readable_money(entry.subtotal.round(2)) %> + | ++ <%= entry.order.order_status %> + | +
+ No orders have been shipped. Check back later. +
+ <% end %> + ++ These are orders that were canceled. Yikes. +
+| + Order Number + | ++ Date of Order + | ++ Product Name + | ++ Quantity + | ++ Subtotal + | ++ Order Status: + | + +
|---|---|---|---|---|---|
| + <%#= entry.order.id %> + <%= link_to entry.order.id, order_path(entry.order.id) %> + | ++ <%= readable_date(entry.order.updated_at) %> + | ++ <%= link_to(entry.product.name, product_path(entry.product.id)) %> + | ++ <%= entry.quantity %> + | ++ <%= readable_money(entry.subtotal.round(2)) %> + | ++ <%= entry.order.order_status %> + | +
+ No orders have been canceled. Congrats! Check back later though. +
+ <% end %> ++ +
+ +| Name | +Photo | +Price | +Description | +Amount in Stock | +Edit | +Add Inventory | +Reduce Inventory | +Currently Available | +Product Visibility | +
|---|---|---|---|---|---|---|---|---|---|
| <%= link_to product.name, product_path(product.id)%> | +
| Order | +Product | +Photo | +Unit Price | +Quantity | +Order Status | +
|---|---|---|---|---|---|
+ You do not have any past orders. Get shopping! +
+ <% end%> ++ Want to contact <%=@user.username%>? Email them at <%=link_to @user.email%> +
+Find me in app/views/users/update.html.erb
diff --git a/bin/bundle b/bin/bundle new file mode 100755 index 0000000000..66e9889e8b --- /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 0000000000..5badb2fde0 --- /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 0000000000..d87d5f5781 --- /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 0000000000..78c4e861dc --- /dev/null +++ b/bin/setup @@ -0,0 +1,38 @@ +#!/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') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + + # 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 0000000000..fb2ec2ebb4 --- /dev/null +++ b/bin/spring @@ -0,0 +1,17 @@ +#!/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) + spring = lockfile.specs.detect { |spec| spec.name == "spring" } + if 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 0000000000..a8e4462f20 --- /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 0000000000..f7ba0b527b --- /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 0000000000..5f6ca0f9b2 --- /dev/null +++ b/config/application.rb @@ -0,0 +1,25 @@ +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 Betsy + class Application < Rails::Application + config.generators do |g| + # Force new test files to be generated in the minitest-spec style + g.test_framework :minitest, spec: true + + # Always use .js files, never .coffee + g.javascript_engine :js + end + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 5.1 + + # 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 0000000000..30f5120df6 --- /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 0000000000..3cba994bb2 --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: redis://localhost:6379/1 + channel_prefix: betsy_production diff --git a/config/database.yml b/config/database.yml new file mode 100644 index 0000000000..6903bb6083 --- /dev/null +++ b/config/database.yml @@ -0,0 +1,85 @@ +# PostgreSQL. Versions 9.1 and up are supported. +# +# Install the pg driver: +# gem install pg +# On OS X with Homebrew: +# gem install pg -- --with-pg-config=/usr/local/bin/pg_config +# On OS X with MacPorts: +# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config +# On Windows: +# gem install pg +# Choose the win32 build. +# Install PostgreSQL and put its /bin directory on your path. +# +# Configure Using Gemfile +# gem 'pg' +# +default: &default + adapter: postgresql + encoding: unicode + # For details on connection pooling, see Rails configuration guide + # http://guides.rubyonrails.org/configuring.html#database-pooling + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + +development: + <<: *default + database: betsy_development + + # The specified database role being used to connect to postgres. + # To create additional roles in postgres see `$ createuser --help`. + # When left blank, postgres will use the default role. This is + # the same name as the operating system user that initialized the database. + #username: betsy + + # The password associated with the postgres role (username). + #password: + + # Connect on a TCP socket. Omitted by default since the client uses a + # domain socket that doesn't need configuration. Windows does not have + # domain sockets, so uncomment these lines. + #host: localhost + + # The TCP port the server listens on. Defaults to 5432. + # If your server runs on a different port number, change accordingly. + #port: 5432 + + # Schema search path. The server defaults to $user,public + #schema_search_path: myapp,sharedapp,public + + # Minimum log levels, in increasing order: + # debug5, debug4, debug3, debug2, debug1, + # log, notice, warning, error, fatal, and panic + # Defaults to warning. + #min_messages: notice + +# 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: betsy_test + +# As with config/secrets.yml, you never want to store sensitive information, +# like your database password, in your source code. If your source code is +# ever seen by anyone, they now have access to your database. +# +# Instead, provide the password as a unix environment variable when you boot +# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database +# for a full rundown on how to provide these environment variables in a +# production deployment. +# +# On Heroku and other platform providers, you may have a full connection URL +# available as an environment variable. For example: +# +# DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase" +# +# You can use this database configuration with: +# +# production: +# url: <%= ENV['DATABASE_URL'] %> +# +production: + <<: *default + database: betsy_production + username: betsy + password: <%= ENV['BETSY_DATABASE_PASSWORD'] %> diff --git a/config/environment.rb b/config/environment.rb new file mode 100644 index 0000000000..426333bb46 --- /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 0000000000..5187e22186 --- /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=#{2.days.seconds.to_i}" + } + 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 0000000000..5721384187 --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,95 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + config.serve_static_assets = true + config.assets.compile = true + + + # 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 + + # Attempt to read encrypted secrets from `config/secrets.yml.enc`. + # Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or + # `config/secrets.yml.key`. + config.read_encrypted_secrets = 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 = "betsy_#{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 0000000000..290f033254 --- /dev/null +++ b/config/environments/test.rb @@ -0,0 +1,44 @@ +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=#{1.hour.seconds.to_i}" + } + + # 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 + + config.action_dispatch.show_exceptions = true + + # 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 0000000000..89d2efab2b --- /dev/null +++ b/config/initializers/application_controller_renderer.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# ActiveSupport::Reloader.to_prepare do +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) +# end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 0000000000..4b828e80cb --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1,14 @@ +# 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 +# Add Yarn node_modules folder to the asset load path. +Rails.application.config.assets.paths << Rails.root.join('node_modules') + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in the app/assets +# folder are already added. +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000000..59385cdf37 --- /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 0000000000..5a6a32d371 --- /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 0000000000..4a994e1e7b --- /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 0000000000..ac033bf9dc --- /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 0000000000..dc1899682b --- /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/omniauth.rb b/config/initializers/omniauth.rb new file mode 100644 index 0000000000..c653e28f42 --- /dev/null +++ b/config/initializers/omniauth.rb @@ -0,0 +1,9 @@ +Rails.application.config.middleware.use OmniAuth::Builder do + provider :github, ENV["GITHUB_CLIENT_ID"], ENV["GITHUB_CLIENT_SECRET"], scope: "user:email" +end + + +# Rails.application.config.middleware.use OmniAuth::Builder do +# provider :github, ENV["GITHUB_CLIENT_ID"], ENV["GITHUB_CLIENT_SECRET"], +# {:client_options => {:ssl => {:ca_file => ‘/usr/lib/ssl/certs/ca-certificates.crt’}}} +# end diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb new file mode 100644 index 0000000000..bbfc3961bf --- /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 0000000000..decc5a8573 --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,33 @@ +# 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. +# +# The following keys must be escaped otherwise they will not be retrieved by +# the default I18n backend: +# +# true, false, on, off, yes, no +# +# Instead, surround them with single quotes. +# +# en: +# 'true': 'foo' +# +# 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 0000000000..1e19380dcb --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,56 @@ +# 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 } +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! + +# If you are preloading your application and using Active Record, it's +# recommended that you close any connections to the database before workers +# are forked to prevent connection leakage. +# +# before_fork do +# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord) +# end + +# 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 the `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, as 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 0000000000..f2f345dda0 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,111 @@ +Rails.application.routes.draw do + root to: "main_page#index" + + resources :categories do + resources :products + end + + resources :reviews + post 'orders/add-product/:id', to: 'orders#add_product', as: 'add_product' + get '/checkout', to: 'orders#checkout', as: 'checkout' + + get '/reviews/new/:id', to: 'reviews#new', as: 'new_new_review' + get '/users/profile', to: 'users#profile', as: 'profile' + get '/order_fulfillment', to: 'users#order_fulfillment', as: 'order_fulfillment' + resources :users + resources :orders + resources :items, except: [:create, :destroy] + + post '/items/:id', to: 'items#create', as: 'create_item' + delete '/items/:id', to: 'items#destroy', as: 'destroy_item' + + + resources :billing_data + + resources :products + + post 'products/visibility/:id', to: 'products#change_visibility', as: 'change_visibility' + + get 'login', to: 'users#login', as: 'login' + get 'logout', to: 'sessions#logout', as: 'logout' + get '/auth/:provider/callback', to: 'sessions#create', as: 'auth_callback' + post 'products/:id', to: 'products#add_to_order', as: 'add_to_order' + + resources :order_products + get '/cart', to: 'orders#show', as: 'cart' + + post '/ship/:id', to: 'order_products#ship', as: 'ship' + + get '/view/:id', to: 'orders#view', as: 'view_order' + + + + # post 'order-product/:id', to: 'orderproducts#create', as: 'order_product' + + # get 'items/index' + # get 'items/show' + # get 'items/edit' + # get 'items/update' + # get 'items/new' + # get 'items/create' + # get 'items/destroy' + + # get 'main_page/index' + # get 'categories/index' + # get 'categories/show' + # get 'categories/edit' + # get 'categories/update' + # get 'categories/new' + # get 'categories/create' + # get 'categories/destroy' + + # get 'reviews/index' + # get 'reviews/show' + # get 'reviews/edit' + # get 'reviews/update' + # get 'reviews/new' + # get 'reviews/create' + # get 'reviews/destroy' + + # get 'billing_data/index' + # get 'billing_data/show' + # get 'billing_data/edit' + # get 'billing_data/update' + # get 'billing_data/new' + # get 'billing_data/create' + # get 'billing_data/destroy' + + # get 'entries/index' + # get 'entries/show' + # get 'entries/edit' + # get 'entries/update' + # get 'entries/new' + # get 'entries/create' + # get 'entries/destroy' + + # get 'orders/index' + # get 'orders/show' + # get 'orders/edit' + # get 'orders/update' + # get 'orders/new' + # get 'orders/create' + # get 'orders/destroy' + + # get 'products/index' + # get 'products/show' + # get 'products/edit' + # get 'products/update' + # get 'products/new' + # get 'products/create' + # get 'products/destroy' + + # get 'product/index' + # get 'product/show' + # get 'product/edit' + # get 'product/update' + # get 'product/new' + # get 'product/create' + # get 'product/destroy' + + # 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 0000000000..6788b5599b --- /dev/null +++ b/config/secrets.yml @@ -0,0 +1,32 @@ +# 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. + +# Shared secrets are available across all environments. + +# shared: +# api_key: a1B2c3D4e5F6 + +# Environmental secrets are only available for that specific environment. + +development: + secret_key_base: d77e7ad142b9041bfd42818492cc553fc443b983696130db61833a73371d4607e4b89961720dfbf5274343401869746af04e1980bf2ee13c6aabc2fccd9397cb + +test: + secret_key_base: 9656394f19ed89bae1bfe0926671449e62a2b462145b1139adb88af47f558138e25932a282106abe55578595092ca23fd815e49c6f69d91241b048090f4fd97f + +# Do not keep production secrets in the unencrypted secrets file. +# Instead, either read values from the environment. +# Or, use `bin/rails secrets:setup` to configure encrypted secrets +# and move the `production:` environment over there. + +production: + secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/config/spring.rb b/config/spring.rb new file mode 100644 index 0000000000..c9119b40c0 --- /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/coverage/.last_run.json b/coverage/.last_run.json new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/coverage/.last_run.json @@ -0,0 +1 @@ + diff --git a/coverage/.resultset.json b/coverage/.resultset.json new file mode 100644 index 0000000000..5519ab7b3c --- /dev/null +++ b/coverage/.resultset.json @@ -0,0 +1,2468 @@ +{ + "MiniTest": { + "coverage": { + "/Users/canaan/Desktop/betsy/app/helpers/application_helper.rb": [ + 1, + 1, + 0, + null, + null, + null, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/billing_data_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/categories_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/items_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/main_page_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/order_products_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/orders_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/products_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/reviews_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/sessions_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/users_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/application_controller.rb": [ + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 119, + 36, + null, + null, + null, + null, + null, + 1, + 121, + 38, + 38, + 38, + null, + 5, + 5, + 5, + 5, + null, + null, + 83, + 4, + null, + null, + 79, + 79, + null, + 79, + 79, + null, + null, + null, + null, + 1, + 119, + 119, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 18, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/billing_data_controller_test.rb": [ + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + null, + 1, + null, + null, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + null, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + 0, + null, + 0, + 0, + null, + null, + 0, + null, + null, + null, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + null, + 1, + 1, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/billing_data_controller.rb": [ + 1, + 1, + 1, + null, + null, + 1, + 2, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + 0, + 0, + null, + null, + null, + 1, + 1, + 1, + null, + null, + null, + 1, + 2, + 1, + 1, + 1, + 1, + 1, + null, + 0, + 0, + null, + null, + null, + 1, + 1, + 3, + null, + null, + 1, + 1, + 1, + 0, + 0, + 0, + null, + null, + 1, + 1, + null, + null, + 1, + 2, + null, + null, + 1, + 3, + 2, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/categories_controller_test.rb": [ + 1, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + 1, + 1, + 3, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + null, + null, + null, + null, + 1, + 1, + 1, + null, + 1, + null, + 1, + null, + 1, + null, + null, + null, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/categories_controller.rb": [ + 1, + null, + 1, + 1, + 1, + null, + null, + null, + 1, + 2, + 2, + 1, + 1, + null, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + null, + 1, + 1, + 1, + null, + 1, + 1, + 1, + null, + 0, + 0, + null, + null, + null, + null, + null, + 1, + 1, + null, + null, + 1, + 2, + 2, + 1, + 1, + null, + 1, + null, + null, + 1, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + null, + 1, + 3, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/items_controller_test.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + null, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + 0, + 0, + null, + null, + null, + null, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + null, + 1, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/items_controller.rb": [ + 1, + 1, + 1, + null, + null, + null, + 1, + 2, + 2, + null, + null, + null, + 2, + 1, + 1, + null, + null, + null, + 1, + 1, + null, + null, + 1, + null, + null, + null, + null, + 2, + null, + null, + 2, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + null, + null, + null, + 1, + null, + 2, + 1, + 1, + 1, + null, + 1, + null, + null, + 1, + 1, + null, + null, + null, + 1, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/main_page_controller_test.rb": [ + 1, + null, + 1, + 1, + 1, + 0, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/main_page_controller.rb": [ + 1, + 1, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/order_products_controller_test.rb": [ + 1, + null, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + null, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 1, + null, + 1, + null, + null, + null, + null, + null, + 1, + 1, + null, + null, + 1, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + null, + 1, + null, + null, + null, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + null, + 1, + null, + null, + null, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + 1, + null, + null, + null, + 1, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/order_products_controller.rb": [ + 1, + 1, + 4, + 4, + 1, + 1, + null, + 3, + 0, + 0, + null, + 3, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 4, + 4, + 4, + 1, + 1, + null, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 0, + 0, + 0, + null, + null, + null, + 1, + 4, + 4, + 2, + 2, + null, + 2, + 2, + 2, + 2, + null, + null, + null, + null, + null, + null, + 1, + 1, + null, + null, + null, + 1, + 12, + null, + null, + 1, + 3, + 3, + 3, + 3, + 2, + null, + 3, + 2, + 2, + 2, + null, + 2, + null, + 2, + 2, + null, + null, + 1, + 1, + 1, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/orders_controller_test.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 4, + 4, + 4, + null, + 1, + 1, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/orders_controller.rb": [ + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + 1, + 2, + null, + null, + null, + 1, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + null, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + null, + null, + null, + 1, + 3, + 3, + 3, + null, + 3, + 3, + 1, + 1, + 1, + 1, + null, + 2, + 2, + null, + 2, + 2, + null, + null, + null, + 4, + null, + null, + 2, + null, + 2, + 2, + null, + null, + 0, + 0, + null, + null, + 0, + null, + null, + null, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + 1, + 6, + 1, + null, + null, + null, + 1, + 2, + 2, + 4, + null, + 2, + 4, + 2, + 1, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/products_controller_test.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + null, + 1, + 3, + 3, + 3, + 3, + null, + null, + null, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + null, + 1, + 1, + null, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + null, + null, + 1, + null, + 1, + 1, + null, + null, + 1, + null, + null, + 1, + 0, + null, + 0, + 0, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/products_controller.rb": [ + 1, + 1, + 1, + 1, + null, + 1, + 2, + null, + null, + 1, + 4, + 1, + null, + 4, + null, + 3, + null, + null, + 1, + 1, + 0, + null, + null, + null, + 1, + 1, + 0, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + 0, + 0, + 0, + 0, + null, + null, + null, + 1, + 1, + null, + null, + 1, + null, + null, + null, + 5, + 4, + 1, + 1, + 1, + null, + 3, + 3, + 3, + 3, + null, + null, + null, + 1, + null, + 1, + 1, + 1, + null, + 0, + null, + null, + 1, + 0, + 0, + null, + 0, + null, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 0, + 0, + 0, + 0, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 6, + null, + null, + 1, + null, + null, + null, + null, + 1, + 13, + null, + null, + null, + 1, + 16, + 4, + null, + null, + null, + 1, + 5, + 3, + null, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + 0, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/reviews_controller_test.rb": [ + null, + 1, + null, + 1, + 1, + 1, + 2, + null, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/reviews_controller.rb": [ + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + null, + null, + null, + null, + null, + null, + 1, + 1, + null, + 0, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + null, + 1, + 2, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/sessions_controller_test.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + 1, + 1, + 1, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/sessions_controller.rb": [ + 1, + null, + null, + 1, + null, + null, + 1, + null, + null, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + null, + 0, + 0, + 0, + 0, + 0, + null, + 0, + 0, + 0, + 0, + null, + null, + null, + null, + 1, + 30, + null, + null, + 30, + null, + 30, + 29, + 29, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + 0, + null, + null, + 30, + null, + null, + 1, + 1, + 1, + 1, + null, + 1, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/users_controller_test.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + null, + null, + 1, + 1, + null, + 1, + null, + null, + 1, + 1, + 1, + null, + 1, + null, + 1, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/users_controller.rb": [ + 1, + 1, + null, + null, + null, + null, + null, + 1, + 1, + 1, + 4, + 2, + null, + null, + 1, + null, + null, + 1, + 2, + null, + null, + 2, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + null, + null, + 1, + 2, + 2, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + null, + null, + null, + null, + null, + 1, + 5, + 2, + null, + null, + null, + 1, + 2, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/billing_datum.rb": [ + 1, + 1, + 1, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/application_record.rb": [ + 1, + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/models/category.rb": [ + 1, + null, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/item.rb": [ + 1, + 1, + 1, + 1, + 1, + null, + 1, + 2, + 0, + 0, + null, + 2, + 2, + 2, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + null, + 0, + 0, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/order_product.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 8, + 8, + 8, + 8, + 5, + null, + 3, + null, + 3, + null, + null, + 1, + 27, + null, + 27, + 18, + null, + 9, + null, + null, + null, + 1, + 3, + 3, + 3, + null, + 0, + null, + null, + null, + 1, + 2, + 2, + 0, + null, + 2, + null, + null, + null, + 1, + 3, + 3, + 0, + null, + 3, + null, + null, + null, + 1, + 3, + null, + null, + 1, + 4, + 4, + 4, + 4, + 2, + null, + 4, + 4, + 2, + null, + null, + 4, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/order.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 12, + 12, + 12, + 12, + 12, + 12, + null, + 12, + null, + null, + 1, + 6, + 6, + 6, + null, + null, + 1, + 4, + 4, + 4, + null, + null, + 1, + 206, + 2, + null, + null, + null, + 1, + 206, + 206, + 0, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + null, + 0, + 0, + null, + null, + 0, + null, + 0, + null, + 0, + null, + null, + null, + 1, + 2, + 1, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/product.rb": [ + 1, + 1, + 1, + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + 1, + 21, + 21, + 14, + null, + 7, + null, + null, + null, + 1, + 23, + 23, + 69, + null, + 23, + 7, + null, + null, + 1, + 4, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/review.rb": [ + 1, + 1, + 1, + 1, + 1, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/user.rb": [ + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + 1, + 1, + null, + 1, + 15, + 15, + 15, + 27, + 54, + null, + 15, + 6, + null, + null, + 1, + 5, + 5, + 5, + 3, + 3, + null, + 3, + 0, + null, + null, + 1, + 5, + 5, + 5, + 3, + 3, + null, + 3, + 3, + null, + null, + 1, + 3, + 3, + 3, + 2, + 2, + null, + 2, + 2, + null, + null, + 1, + 2, + 2, + 2, + 0, + 0, + null, + null, + 2, + null, + null, + 1, + 4, + 4, + 4, + 0, + 0, + null, + null, + 4, + null, + null, + null, + 1, + 4, + 4, + 4, + 2, + 2, + null, + null, + 4, + null, + null, + 1, + 2, + 2, + 2, + 2, + 2, + null, + null, + 1, + 38, + 38, + 69, + 33, + null, + null, + null, + null, + 38, + 33, + null, + 5, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + null, + null + ] + }, + "timestamp": 1509130561 + } +} diff --git a/coverage/index.html b/coverage/index.html new file mode 100644 index 0000000000..578a665dfc --- /dev/null +++ b/coverage/index.html @@ -0,0 +1,15535 @@ + + + +
+ You may have mistyped the address or the page may have moved.
+If you are the application owner check the logs for more information.
+Maybe you tried to change something you didn't have access to.
+If you are the application owner check the logs for more information.
+If you are the application owner check the logs for more information.
+