From 759e51d3cf11604ea86b31276970f977a7f6dc94 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Tue, 30 Apr 2019 14:31:33 -0700 Subject: [PATCH 001/260] Created rails project. Initial commit. --- .gitignore | 27 ++ .ruby-version | 1 + Gemfile | 81 +++++ Gemfile.lock | 279 ++++++++++++++++++ Guardfile | 9 + Rakefile | 6 + app/assets/config/manifest.js | 3 + app/assets/images/.keep | 0 app/assets/javascripts/application.js | 19 ++ app/assets/javascripts/cable.js | 13 + app/assets/javascripts/channels/.keep | 0 app/assets/stylesheets/application.scss | 17 ++ app/channels/application_cable/channel.rb | 4 + app/channels/application_cable/connection.rb | 4 + app/controllers/application_controller.rb | 2 + app/controllers/concerns/.keep | 0 app/helpers/application_helper.rb | 2 + app/jobs/application_job.rb | 2 + app/mailers/application_mailer.rb | 4 + app/models/application_record.rb | 3 + app/models/concerns/.keep | 0 app/views/layouts/application.html.erb | 15 + app/views/layouts/mailer.html.erb | 13 + app/views/layouts/mailer.text.erb | 1 + bin/bundle | 3 + bin/rails | 9 + bin/rake | 9 + bin/setup | 36 +++ bin/spring | 17 ++ bin/update | 31 ++ bin/yarn | 11 + config.ru | 5 + config/application.rb | 25 ++ config/boot.rb | 4 + config/cable.yml | 10 + config/credentials.yml.enc | 1 + config/database.yml | 85 ++++++ config/environment.rb | 5 + config/environments/development.rb | 61 ++++ config/environments/production.rb | 94 ++++++ config/environments/test.rb | 46 +++ config/initializers/action_view.rb | 1 + .../application_controller_renderer.rb | 8 + config/initializers/assets.rb | 14 + config/initializers/backtrace_silencers.rb | 7 + .../initializers/content_security_policy.rb | 25 ++ config/initializers/cookies_serializer.rb | 5 + .../initializers/filter_parameter_logging.rb | 4 + config/initializers/inflections.rb | 16 + config/initializers/mime_types.rb | 4 + config/initializers/wrap_parameters.rb | 14 + config/locales/en.yml | 33 +++ config/puma.rb | 34 +++ config/routes.rb | 3 + config/spring.rb | 6 + config/storage.yml | 34 +++ db/seeds.rb | 7 + lib/assets/.keep | 0 lib/tasks/.keep | 0 log/.keep | 0 package.json | 5 + public/404.html | 67 +++++ public/422.html | 67 +++++ public/500.html | 66 +++++ public/apple-touch-icon-precomposed.png | 0 public/apple-touch-icon.png | 0 public/favicon.ico | 0 public/robots.txt | 1 + storage/.keep | 0 test/application_system_test_case.rb | 5 + test/controllers/.keep | 0 test/fixtures/.keep | 0 test/fixtures/files/.keep | 0 test/helpers/.keep | 0 test/integration/.keep | 0 test/mailers/.keep | 0 test/models/.keep | 0 test/system/.keep | 0 test/test_helper.rb | 24 ++ tmp/.keep | 0 vendor/.keep | 0 81 files changed, 1407 insertions(+) create mode 100644 .gitignore create mode 100644 .ruby-version create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 Guardfile create mode 100644 Rakefile create mode 100644 app/assets/config/manifest.js create mode 100644 app/assets/images/.keep create mode 100644 app/assets/javascripts/application.js create mode 100644 app/assets/javascripts/cable.js create mode 100644 app/assets/javascripts/channels/.keep create mode 100644 app/assets/stylesheets/application.scss create mode 100644 app/channels/application_cable/channel.rb create mode 100644 app/channels/application_cable/connection.rb create mode 100644 app/controllers/application_controller.rb create mode 100644 app/controllers/concerns/.keep create mode 100644 app/helpers/application_helper.rb create mode 100644 app/jobs/application_job.rb create mode 100644 app/mailers/application_mailer.rb create mode 100644 app/models/application_record.rb create mode 100644 app/models/concerns/.keep create mode 100644 app/views/layouts/application.html.erb create mode 100644 app/views/layouts/mailer.html.erb create mode 100644 app/views/layouts/mailer.text.erb create mode 100755 bin/bundle create mode 100755 bin/rails create mode 100755 bin/rake create mode 100755 bin/setup create mode 100755 bin/spring create mode 100755 bin/update create mode 100755 bin/yarn create mode 100644 config.ru create mode 100644 config/application.rb create mode 100644 config/boot.rb create mode 100644 config/cable.yml create mode 100644 config/credentials.yml.enc create mode 100644 config/database.yml create mode 100644 config/environment.rb create mode 100644 config/environments/development.rb create mode 100644 config/environments/production.rb create mode 100644 config/environments/test.rb create mode 100644 config/initializers/action_view.rb create mode 100644 config/initializers/application_controller_renderer.rb create mode 100644 config/initializers/assets.rb create mode 100644 config/initializers/backtrace_silencers.rb create mode 100644 config/initializers/content_security_policy.rb create mode 100644 config/initializers/cookies_serializer.rb create mode 100644 config/initializers/filter_parameter_logging.rb create mode 100644 config/initializers/inflections.rb create mode 100644 config/initializers/mime_types.rb create mode 100644 config/initializers/wrap_parameters.rb create mode 100644 config/locales/en.yml create mode 100644 config/puma.rb create mode 100644 config/routes.rb create mode 100644 config/spring.rb create mode 100644 config/storage.yml create mode 100644 db/seeds.rb create mode 100644 lib/assets/.keep create mode 100644 lib/tasks/.keep create mode 100644 log/.keep create mode 100644 package.json create mode 100644 public/404.html create mode 100644 public/422.html create mode 100644 public/500.html create mode 100644 public/apple-touch-icon-precomposed.png create mode 100644 public/apple-touch-icon.png create mode 100644 public/favicon.ico create mode 100644 public/robots.txt create mode 100644 storage/.keep create mode 100644 test/application_system_test_case.rb create mode 100644 test/controllers/.keep create mode 100644 test/fixtures/.keep create mode 100644 test/fixtures/files/.keep create mode 100644 test/helpers/.keep create mode 100644 test/integration/.keep create mode 100644 test/mailers/.keep create mode 100644 test/models/.keep create mode 100644 test/system/.keep create mode 100644 test/test_helper.rb create mode 100644 tmp/.keep create mode 100644 vendor/.keep diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..18b43c9cd2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# See https://help.github.com/articles/ignoring-files for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile '~/.gitignore_global' + +# Ignore bundler config. +/.bundle + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep + +# Ignore uploaded files in development +/storage/* +!/storage/.keep + +/node_modules +/yarn-error.log + +/public/assets +.byebug_history + +# Ignore master key for decrypting credentials and more. +/config/master.key diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000000..25c81fe399 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +ruby-2.5.1 \ No newline at end of file diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000000..80be142348 --- /dev/null +++ b/Gemfile @@ -0,0 +1,81 @@ +source 'https://rubygems.org' +git_source(:github) { |repo| "https://github.com/#{repo}.git" } + +ruby '2.5.1' + +# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' +gem 'rails', '~> 5.2.3' +# Use postgresql as the database for Active Record +gem 'pg', '>= 0.18', '< 2.0' +# Use Puma as the app server +gem 'puma', '~> 3.11' +# 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 'mini_racer', 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 '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', '~> 4.0' +# Use ActiveModel has_secure_password +# gem 'bcrypt', '~> 3.1.7' + +# Use ActiveStorage variant +# gem 'mini_magick', '~> 4.8' + +# Use Capistrano for deployment +# gem 'capistrano-rails', group: :development + +# Reduces boot times through caching; required in config/boot.rb +gem 'bootsnap', '>= 1.1.0', require: false + +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] +end + +group :development do + # Access an interactive console on exception pages or by calling '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 + +group :test do + # Adds support for Capybara system testing and selenium driver + gem 'capybara', '>= 2.15' + gem 'selenium-webdriver' + # Easy installation and use of chromedriver to run system tests with Chrome + gem 'chromedriver-helper' +end + +# Windows does not include zoneinfo files, so bundle the tzinfo-data gem +gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] + +gem 'jquery-rails' +gem 'jquery-turbolinks' +gem 'bootstrap', '~> 4.1.3' +group :development, :test do + gem 'pry-rails' +end + +group :development do + gem 'better_errors' + gem 'binding_of_caller' + gem 'guard' + gem 'guard-minitest' +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..1cad6cf580 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,279 @@ +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.2.3) + actionpack (= 5.2.3) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (5.2.3) + actionpack (= 5.2.3) + actionview (= 5.2.3) + activejob (= 5.2.3) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.2.3) + actionview (= 5.2.3) + activesupport (= 5.2.3) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.2.3) + activesupport (= 5.2.3) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.2.3) + activesupport (= 5.2.3) + globalid (>= 0.3.6) + activemodel (5.2.3) + activesupport (= 5.2.3) + activerecord (5.2.3) + activemodel (= 5.2.3) + activesupport (= 5.2.3) + arel (>= 9.0) + activestorage (5.2.3) + actionpack (= 5.2.3) + activerecord (= 5.2.3) + marcel (~> 0.3.1) + activesupport (5.2.3) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.6.0) + public_suffix (>= 2.0.2, < 4.0) + ansi (1.5.0) + archive-zip (0.12.0) + io-like (~> 0.3.0) + arel (9.0.0) + autoprefixer-rails (9.5.1) + execjs + better_errors (2.5.1) + coderay (>= 1.0.0) + erubi (>= 1.0.0) + rack (>= 0.9.0) + bindex (0.7.0) + binding_of_caller (0.8.0) + debug_inspector (>= 0.0.1) + bootsnap (1.4.4) + msgpack (~> 1.0) + bootstrap (4.1.3) + autoprefixer-rails (>= 6.0.3) + popper_js (>= 1.12.9, < 2) + sass (>= 3.5.2) + builder (3.2.3) + byebug (11.0.1) + capybara (3.18.0) + addressable + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (~> 1.2) + xpath (~> 3.2) + childprocess (1.0.1) + rake (< 13.0) + chromedriver-helper (2.1.1) + archive-zip (~> 0.10) + nokogiri (~> 1.8) + coderay (1.1.2) + concurrent-ruby (1.1.5) + crass (1.0.4) + debug_inspector (0.0.3) + erubi (1.8.0) + execjs (2.7.0) + ffi (1.10.0) + formatador (0.2.5) + globalid (0.4.2) + activesupport (>= 4.2.0) + guard (2.15.0) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (>= 1.0.12, < 2.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.9.12) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-compat (1.2.1) + guard-minitest (2.4.6) + guard-compat (~> 1.2) + minitest (>= 3.0) + i18n (1.6.0) + concurrent-ruby (~> 1.0) + io-like (0.3.0) + jbuilder (2.8.0) + activesupport (>= 4.2.0) + multi_json (>= 1.2) + jquery-rails (4.3.3) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + jquery-turbolinks (2.1.0) + railties (>= 3.1.0) + turbolinks + listen (3.1.5) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + ruby_dep (~> 1.2) + loofah (2.2.3) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + lumberjack (1.0.13) + mail (2.7.1) + mini_mime (>= 0.1.1) + marcel (0.3.3) + mimemagic (~> 0.3.2) + method_source (0.9.2) + mimemagic (0.3.3) + mini_mime (1.0.1) + mini_portile2 (2.4.0) + minitest (5.11.3) + minitest-rails (3.0.0) + minitest (~> 5.8) + railties (~> 5.0) + minitest-reporters (1.3.6) + ansi + builder + minitest (>= 5.0) + ruby-progressbar + msgpack (1.2.10) + multi_json (1.13.1) + nenv (0.3.0) + nio4r (2.3.1) + nokogiri (1.10.3) + mini_portile2 (~> 2.4.0) + notiffany (0.1.1) + nenv (~> 0.1) + shellany (~> 0.0) + pg (1.1.4) + popper_js (1.14.5) + pry (0.12.2) + coderay (~> 1.1.0) + method_source (~> 0.9.0) + pry-rails (0.3.9) + pry (>= 0.10.4) + public_suffix (3.0.3) + puma (3.12.1) + rack (2.0.7) + rack-test (1.1.0) + rack (>= 1.0, < 3) + rails (5.2.3) + actioncable (= 5.2.3) + actionmailer (= 5.2.3) + actionpack (= 5.2.3) + actionview (= 5.2.3) + activejob (= 5.2.3) + activemodel (= 5.2.3) + activerecord (= 5.2.3) + activestorage (= 5.2.3) + activesupport (= 5.2.3) + bundler (>= 1.3.0) + railties (= 5.2.3) + sprockets-rails (>= 2.0.0) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.0.4) + loofah (~> 2.2, >= 2.2.2) + railties (5.2.3) + actionpack (= 5.2.3) + activesupport (= 5.2.3) + method_source + rake (>= 0.8.7) + thor (>= 0.19.0, < 2.0) + rake (12.3.2) + rb-fsevent (0.10.3) + rb-inotify (0.10.0) + ffi (~> 1.0) + regexp_parser (1.4.0) + ruby-progressbar (1.10.0) + ruby_dep (1.5.0) + rubyzip (1.2.2) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sass-rails (5.0.7) + 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.142.0) + childprocess (>= 0.5, < 2.0) + rubyzip (~> 1.2, >= 1.2.2) + shellany (0.0.1) + 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.2) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + thor (0.20.3) + thread_safe (0.3.6) + tilt (2.0.9) + turbolinks (5.2.0) + turbolinks-source (~> 5.2) + turbolinks-source (5.2.0) + tzinfo (1.2.5) + thread_safe (~> 0.1) + uglifier (4.1.20) + execjs (>= 0.3.0, < 3) + web-console (3.7.0) + actionview (>= 5.0) + activemodel (>= 5.0) + bindex (>= 0.4.0) + railties (>= 5.0) + websocket-driver (0.7.0) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.3) + xpath (3.2.0) + nokogiri (~> 1.8) + +PLATFORMS + ruby + +DEPENDENCIES + better_errors + binding_of_caller + bootsnap (>= 1.1.0) + bootstrap (~> 4.1.3) + byebug + capybara (>= 2.15) + chromedriver-helper + guard + guard-minitest + jbuilder (~> 2.5) + jquery-rails + jquery-turbolinks + listen (>= 3.0.5, < 3.2) + minitest-rails + minitest-reporters + pg (>= 0.18, < 2.0) + pry-rails + puma (~> 3.11) + rails (~> 5.2.3) + sass-rails (~> 5.0) + selenium-webdriver + spring + spring-watcher-listen (~> 2.0.0) + turbolinks (~> 5) + tzinfo-data + uglifier (>= 1.3.0) + web-console (>= 3.3.0) + +RUBY VERSION + ruby 2.5.1p57 + +BUNDLED WITH + 1.17.3 diff --git a/Guardfile b/Guardfile new file mode 100644 index 0000000000..e34f706f4a --- /dev/null +++ b/Guardfile @@ -0,0 +1,9 @@ +guard :minitest, autorun: false, spring: true do + watch(%r{^app/(.+).rb$}) { |m| "test/#{m[1]}_test.rb" } + watch(%r{^app/controllers/application_controller.rb$}) { 'test/controllers' } + watch(%r{^app/controllers/(.+)_controller.rb$}) { |m| "test/integration/#{m[1]}_test.rb" } + watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" } + watch(%r{^lib/(.+).rb$}) { |m| "test/lib/#{m[1]}_test.rb" } + watch(%r{^test/.+_test.rb$}) + watch(%r{^test/test_helper.rb$}) { 'test' } +end 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/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 0000000000..b0ef35b723 --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,19 @@ +// 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 jquery3 + //= require popper + //= require bootstrap-sprockets + +// +//= require rails-ujs +//= require activestorage +//= require turbolinks +//= require_tree . 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/channels/.keep b/app/assets/javascripts/channels/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss new file mode 100644 index 0000000000..b4d20f5641 --- /dev/null +++ b/app/assets/stylesheets/application.scss @@ -0,0 +1,17 @@ +/* + * 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. + * + */ +/* Custom bootstrap variables must be set or imported *before* bootstrap. */ +@import "bootstrap"; +/* Import scss content */ +@import "**/*"; 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..09705d12ab --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,2 @@ +class ApplicationController < ActionController::Base +end diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb new file mode 100644 index 0000000000..de6be7945c --- /dev/null +++ b/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb new file mode 100644 index 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/concerns/.keep b/app/models/concerns/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb new file mode 100644 index 0000000000..f18f1b6820 --- /dev/null +++ b/app/views/layouts/application.html.erb @@ -0,0 +1,15 @@ + + + + Betsy + <%= csrf_meta_tags %> + <%= csp_meta_tag %> + + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> + <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> + + + + <%= yield %> + + diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb new file mode 100644 index 0000000000..cbd34d2e9d --- /dev/null +++ b/app/views/layouts/mailer.html.erb @@ -0,0 +1,13 @@ + + + + + + + + + <%= yield %> + + diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb new file mode 100644 index 0000000000..37f0bddbd7 --- /dev/null +++ b/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/bin/bundle b/bin/bundle new file mode 100755 index 0000000000..f19acf5b5c --- /dev/null +++ b/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +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..94fd4d7977 --- /dev/null +++ b/bin/setup @@ -0,0 +1,36 @@ +#!/usr/bin/env ruby +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +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..58bfaed518 --- /dev/null +++ b/bin/update @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +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') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + 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/bin/yarn b/bin/yarn new file mode 100755 index 0000000000..460dd565b4 --- /dev/null +++ b/bin/yarn @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +APP_ROOT = File.expand_path('..', __dir__) +Dir.chdir(APP_ROOT) do + begin + exec "yarnpkg", *ARGV + rescue Errno::ENOENT + $stderr.puts "Yarn executable was not detected in the system." + $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" + exit 1 + end +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..5c09a3eefc --- /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.2 + + # Settings in config/environments/* take precedence over those specified here. + # Application configuration can go into files in config/initializers + # -- all .rb files in that directory are automatically loaded after loading + # the framework and any gems in your application. + end +end diff --git a/config/boot.rb b/config/boot.rb new file mode 100644 index 0000000000..b9e460cef3 --- /dev/null +++ b/config/boot.rb @@ -0,0 +1,4 @@ +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) + +require 'bundler/setup' # Set up gems listed in the Gemfile. +require 'bootsnap/setup' # Speed up boot time by caching expensive operations. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 0000000000..dd2a324c68 --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: betsy_production diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc new file mode 100644 index 0000000000..63c3c0b8a0 --- /dev/null +++ b/config/credentials.yml.enc @@ -0,0 +1 @@ +t/ENtHcwKeNjhJ4c1sF1wh0YxxTpaQbEsx7D2RbAhewDXRh+fFBUuagfgvVH3eQSsoPw+1LBfc+DdW/lv1D7Dx8DUdxQUGC0kaM2M6guq+3lJBq0egytiNngzdkkHkOsobamXWh3UmnxBGUhqKvT7PkNHxC2V8EI7t1QQgHYmRFgrDQULhsNKyKrEO6hSw+zHH8ZC/nShU0hCVGZGX2cWlxctjEBPKYaUpf0Loe8y06adxNa7XNta76LgrYktNeTnd0P8+hr0PJd9T8HuOybXbA9e42N6ePRR0Ufzq0s7JVR0bF3VKK+kHwqLv0Fi0YtlhCQyQWZ1/8NHhUGGlLFq0eKlXpQzP+I4l6gbfdx7Tbwoq5tcy1L5Nw8anXIITZ0pPnK1O7xRxcQ7Umi1REpRu9SRsnUDk5uDt2R--EbAv1Tcaewb/wts1--tDZAxADMR7aK+QVURKNRCQ== \ No newline at end of file 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..1311e3e4ef --- /dev/null +++ b/config/environments/development.rb @@ -0,0 +1,61 @@ +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. + # Run rails dev:cache to toggle caching. + 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.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # 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 + + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + + # 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..5f6f3058c6 --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,94 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = 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 + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # 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..0a38fd3ce9 --- /dev/null +++ b/config/environments/test.rb @@ -0,0 +1,46 @@ +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.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 + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + + # Store uploaded files on the local file system in a temporary directory + config.active_storage.service = :test + + 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/action_view.rb b/config/initializers/action_view.rb new file mode 100644 index 0000000000..142d382f87 --- /dev/null +++ b/config/initializers/action_view.rb @@ -0,0 +1 @@ +Rails.application.config.action_view.form_with_generates_remote_forms = false 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/content_security_policy.rb b/config/initializers/content_security_policy.rb new file mode 100644 index 0000000000..d3bcaa5ec8 --- /dev/null +++ b/config/initializers/content_security_policy.rb @@ -0,0 +1,25 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy +# For further information see the following documentation +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + +# Rails.application.config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https + +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end + +# If you are using UJS then enable automatic nonce generation +# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } + +# Report CSP violations to a specified URI +# For further information see the following documentation: +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only +# Rails.application.config.content_security_policy_report_only = true 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/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..a5eccf816b --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,34 @@ +# 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. +# +# preload_app! + +# 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..787824f888 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,3 @@ +Rails.application.routes.draw do + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html +end diff --git a/config/spring.rb b/config/spring.rb new file mode 100644 index 0000000000..9fa7863f99 --- /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/config/storage.yml b/config/storage.yml new file mode 100644 index 0000000000..d32f76e8fb --- /dev/null +++ b/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket + +# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/db/seeds.rb b/db/seeds.rb new file mode 100644 index 0000000000..1beea2accd --- /dev/null +++ b/db/seeds.rb @@ -0,0 +1,7 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). +# +# Examples: +# +# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) +# Character.create(name: 'Luke', movie: movies.first) diff --git a/lib/assets/.keep b/lib/assets/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/tasks/.keep b/lib/tasks/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/log/.keep b/log/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/package.json b/package.json new file mode 100644 index 0000000000..f874acf437 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "name": "betsy", + "private": true, + "dependencies": {} +} diff --git a/public/404.html b/public/404.html new file mode 100644 index 0000000000..2be3af26fc --- /dev/null +++ b/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/422.html b/public/422.html new file mode 100644 index 0000000000..c08eac0d1d --- /dev/null +++ b/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/500.html b/public/500.html new file mode 100644 index 0000000000..78a030af22 --- /dev/null +++ b/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/apple-touch-icon-precomposed.png b/public/apple-touch-icon-precomposed.png new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000000..37b576a4a0 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1 @@ +# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file diff --git a/storage/.keep b/storage/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb new file mode 100644 index 0000000000..d19212abd5 --- /dev/null +++ b/test/application_system_test_case.rb @@ -0,0 +1,5 @@ +require "test_helper" + +class ApplicationSystemTestCase < ActionDispatch::SystemTestCase + driven_by :selenium, using: :chrome, screen_size: [1400, 1400] +end diff --git a/test/controllers/.keep b/test/controllers/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/fixtures/.keep b/test/fixtures/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/fixtures/files/.keep b/test/fixtures/files/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/helpers/.keep b/test/helpers/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/integration/.keep b/test/integration/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/mailers/.keep b/test/mailers/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/models/.keep b/test/models/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/system/.keep b/test/system/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000000..2b5172a7d6 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,24 @@ +ENV["RAILS_ENV"] = "test" +require File.expand_path("../../config/environment", __FILE__) +require "rails/test_help" +require "minitest/rails"require "minitest/reporters" # for Colorized output +# For colorful output! +Minitest::Reporters.use!( + Minitest::Reporters::SpecReporter.new, + ENV, + Minitest.backtrace_filter +) + + +# To add Capybara feature tests add `gem "minitest-rails-capybara"` +# to the test group in the Gemfile and uncomment the following: +# require "minitest/rails/capybara" + +# Uncomment for awesome colorful output +# require "minitest/pride" + +class ActiveSupport::TestCase + # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. + fixtures :all + # Add more helper methods to be used by all tests here... +end diff --git a/tmp/.keep b/tmp/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/vendor/.keep b/vendor/.keep new file mode 100644 index 0000000000..e69de29bb2 From d40d54588fcc2a26f964b659985ba6c89fb89312 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Wed, 1 May 2019 15:20:27 -0700 Subject: [PATCH 002/260] Generated models, created join table for CategoryProduct, and added foreign keys. --- README.md | 4 + app/models/category.rb | 2 + app/models/item.rb | 2 + app/models/merchant.rb | 2 + app/models/order.rb | 2 + app/models/product.rb | 2 + app/models/review.rb | 2 + db/migrate/20190501212559_create_products.rb | 14 +++ db/migrate/20190501212702_create_reviews.rb | 10 +++ db/migrate/20190501212809_create_merchants.rb | 12 +++ db/migrate/20190501213002_create_orders.rb | 14 +++ .../20190501213018_create_categories.rb | 9 ++ db/migrate/20190501213315_create_items.rb | 9 ++ ...5033_create_category_product_join_table.rb | 8 ++ ...20190501215635_add_product_id_to_review.rb | 5 ++ ...190501215709_add_merchant_id_to_product.rb | 5 ++ ...729_add_product_id_and_order_id_to_item.rb | 6 ++ db/schema.rb | 87 +++++++++++++++++++ test/fixtures/categories.yml | 7 ++ test/fixtures/items.yml | 7 ++ test/fixtures/merchants.yml | 13 +++ test/fixtures/orders.yml | 17 ++++ test/fixtures/products.yml | 17 ++++ test/fixtures/reviews.yml | 9 ++ test/models/category_test.rb | 9 ++ test/models/item_test.rb | 9 ++ test/models/merchant_test.rb | 9 ++ test/models/order_test.rb | 9 ++ test/models/product_test.rb | 9 ++ test/models/review_test.rb | 9 ++ 30 files changed, 319 insertions(+) create mode 100644 app/models/category.rb create mode 100644 app/models/item.rb create mode 100644 app/models/merchant.rb create mode 100644 app/models/order.rb create mode 100644 app/models/product.rb create mode 100644 app/models/review.rb create mode 100644 db/migrate/20190501212559_create_products.rb create mode 100644 db/migrate/20190501212702_create_reviews.rb create mode 100644 db/migrate/20190501212809_create_merchants.rb create mode 100644 db/migrate/20190501213002_create_orders.rb create mode 100644 db/migrate/20190501213018_create_categories.rb create mode 100644 db/migrate/20190501213315_create_items.rb create mode 100644 db/migrate/20190501215033_create_category_product_join_table.rb create mode 100644 db/migrate/20190501215635_add_product_id_to_review.rb create mode 100644 db/migrate/20190501215709_add_merchant_id_to_product.rb create mode 100644 db/migrate/20190501215729_add_product_id_and_order_id_to_item.rb create mode 100644 db/schema.rb create mode 100644 test/fixtures/categories.yml create mode 100644 test/fixtures/items.yml create mode 100644 test/fixtures/merchants.yml create mode 100644 test/fixtures/orders.yml create mode 100644 test/fixtures/products.yml create mode 100644 test/fixtures/reviews.yml create mode 100644 test/models/category_test.rb create mode 100644 test/models/item_test.rb create mode 100644 test/models/merchant_test.rb create mode 100644 test/models/order_test.rb create mode 100644 test/models/product_test.rb create mode 100644 test/models/review_test.rb diff --git a/README.md b/README.md index 6db044f03d..8833ef16d2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +https://intangibly.herokuapp.com/ +https://git.heroku.com/intangibly.git +https://trello.com/b/A38BQTVC/intagibelles + # bEtsy ## At a Glance diff --git a/app/models/category.rb b/app/models/category.rb new file mode 100644 index 0000000000..54cb6aee3f --- /dev/null +++ b/app/models/category.rb @@ -0,0 +1,2 @@ +class Category < ApplicationRecord +end diff --git a/app/models/item.rb b/app/models/item.rb new file mode 100644 index 0000000000..809e23f848 --- /dev/null +++ b/app/models/item.rb @@ -0,0 +1,2 @@ +class Item < ApplicationRecord +end diff --git a/app/models/merchant.rb b/app/models/merchant.rb new file mode 100644 index 0000000000..0440407160 --- /dev/null +++ b/app/models/merchant.rb @@ -0,0 +1,2 @@ +class Merchant < ApplicationRecord +end diff --git a/app/models/order.rb b/app/models/order.rb new file mode 100644 index 0000000000..10281b3450 --- /dev/null +++ b/app/models/order.rb @@ -0,0 +1,2 @@ +class Order < ApplicationRecord +end diff --git a/app/models/product.rb b/app/models/product.rb new file mode 100644 index 0000000000..35a85acab3 --- /dev/null +++ b/app/models/product.rb @@ -0,0 +1,2 @@ +class Product < ApplicationRecord +end diff --git a/app/models/review.rb b/app/models/review.rb new file mode 100644 index 0000000000..b2ca4935ed --- /dev/null +++ b/app/models/review.rb @@ -0,0 +1,2 @@ +class Review < ApplicationRecord +end diff --git a/db/migrate/20190501212559_create_products.rb b/db/migrate/20190501212559_create_products.rb new file mode 100644 index 0000000000..b0a8375270 --- /dev/null +++ b/db/migrate/20190501212559_create_products.rb @@ -0,0 +1,14 @@ +class CreateProducts < ActiveRecord::Migration[5.2] + def change + create_table :products do |t| + t.string :name + t.integer :price + t.string :description + t.string :photo_url + t.integer :stock + t.boolean :active, default: true + + t.timestamps + end + end +end diff --git a/db/migrate/20190501212702_create_reviews.rb b/db/migrate/20190501212702_create_reviews.rb new file mode 100644 index 0000000000..8248e3c6b3 --- /dev/null +++ b/db/migrate/20190501212702_create_reviews.rb @@ -0,0 +1,10 @@ +class CreateReviews < ActiveRecord::Migration[5.2] + def change + create_table :reviews do |t| + t.integer :rating + t.string :comment + + t.timestamps + end + end +end diff --git a/db/migrate/20190501212809_create_merchants.rb b/db/migrate/20190501212809_create_merchants.rb new file mode 100644 index 0000000000..7fb9e6f08e --- /dev/null +++ b/db/migrate/20190501212809_create_merchants.rb @@ -0,0 +1,12 @@ +class CreateMerchants < ActiveRecord::Migration[5.2] + def change + create_table :merchants do |t| + t.string :username + t.string :email + t.string :uid + t.string :provider + + t.timestamps + end + end +end diff --git a/db/migrate/20190501213002_create_orders.rb b/db/migrate/20190501213002_create_orders.rb new file mode 100644 index 0000000000..f97f32c72f --- /dev/null +++ b/db/migrate/20190501213002_create_orders.rb @@ -0,0 +1,14 @@ +class CreateOrders < ActiveRecord::Migration[5.2] + def change + create_table :orders do |t| + t.string :status + t.string :shopper_name + t.string :shopper_email + t.string :shopper_address + t.string :cc_four + t.string :cc_exp + + t.timestamps + end + end +end diff --git a/db/migrate/20190501213018_create_categories.rb b/db/migrate/20190501213018_create_categories.rb new file mode 100644 index 0000000000..6ccc3914a0 --- /dev/null +++ b/db/migrate/20190501213018_create_categories.rb @@ -0,0 +1,9 @@ +class CreateCategories < ActiveRecord::Migration[5.2] + def change + create_table :categories do |t| + t.string :name + + t.timestamps + end + end +end diff --git a/db/migrate/20190501213315_create_items.rb b/db/migrate/20190501213315_create_items.rb new file mode 100644 index 0000000000..1afce83ebd --- /dev/null +++ b/db/migrate/20190501213315_create_items.rb @@ -0,0 +1,9 @@ +class CreateItems < ActiveRecord::Migration[5.2] + def change + create_table :items do |t| + t.integer :quantity + + t.timestamps + end + end +end diff --git a/db/migrate/20190501215033_create_category_product_join_table.rb b/db/migrate/20190501215033_create_category_product_join_table.rb new file mode 100644 index 0000000000..83d3bce4d8 --- /dev/null +++ b/db/migrate/20190501215033_create_category_product_join_table.rb @@ -0,0 +1,8 @@ +class CreateCategoryProductJoinTable < ActiveRecord::Migration[5.2] + def change + create_table :categories_products do |t| + t.belongs_to :product, index: true + t.belongs_to :category, index: true + end + end +end diff --git a/db/migrate/20190501215635_add_product_id_to_review.rb b/db/migrate/20190501215635_add_product_id_to_review.rb new file mode 100644 index 0000000000..0cd70141a4 --- /dev/null +++ b/db/migrate/20190501215635_add_product_id_to_review.rb @@ -0,0 +1,5 @@ +class AddProductIdToReview < ActiveRecord::Migration[5.2] + def change + add_reference :reviews, :product, foreign_key: true + end +end diff --git a/db/migrate/20190501215709_add_merchant_id_to_product.rb b/db/migrate/20190501215709_add_merchant_id_to_product.rb new file mode 100644 index 0000000000..77257b8727 --- /dev/null +++ b/db/migrate/20190501215709_add_merchant_id_to_product.rb @@ -0,0 +1,5 @@ +class AddMerchantIdToProduct < ActiveRecord::Migration[5.2] + def change + add_reference :products, :merchant, foreign_key: true + end +end diff --git a/db/migrate/20190501215729_add_product_id_and_order_id_to_item.rb b/db/migrate/20190501215729_add_product_id_and_order_id_to_item.rb new file mode 100644 index 0000000000..b50f9836d3 --- /dev/null +++ b/db/migrate/20190501215729_add_product_id_and_order_id_to_item.rb @@ -0,0 +1,6 @@ +class AddProductIdAndOrderIdToItem < ActiveRecord::Migration[5.2] + def change + add_reference :items, :product, foreign_key: true + add_reference :items, :order, foreign_key: true + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000000..1c7035b4bd --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,87 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 2019_05_01_215729) do + + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "categories", force: :cascade do |t| + t.string "name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "categories_products", force: :cascade do |t| + t.bigint "product_id" + t.bigint "category_id" + t.index ["category_id"], name: "index_categories_products_on_category_id" + t.index ["product_id"], name: "index_categories_products_on_product_id" + end + + create_table "items", force: :cascade do |t| + t.integer "quantity" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "product_id" + t.bigint "order_id" + t.index ["order_id"], name: "index_items_on_order_id" + t.index ["product_id"], name: "index_items_on_product_id" + end + + create_table "merchants", force: :cascade do |t| + t.string "username" + t.string "email" + t.string "uid" + t.string "provider" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "orders", force: :cascade do |t| + t.string "status" + t.string "shopper_name" + t.string "shopper_email" + t.string "shopper_address" + t.string "cc_four" + t.string "cc_exp" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "products", force: :cascade do |t| + t.string "name" + t.integer "price" + t.string "description" + t.string "photo_url" + t.integer "stock" + t.boolean "active", default: true + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "merchant_id" + t.index ["merchant_id"], name: "index_products_on_merchant_id" + end + + create_table "reviews", force: :cascade do |t| + t.integer "rating" + t.string "comment" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "product_id" + t.index ["product_id"], name: "index_reviews_on_product_id" + end + + add_foreign_key "items", "orders" + add_foreign_key "items", "products" + add_foreign_key "products", "merchants" + add_foreign_key "reviews", "products" +end diff --git a/test/fixtures/categories.yml b/test/fixtures/categories.yml new file mode 100644 index 0000000000..56066c68af --- /dev/null +++ b/test/fixtures/categories.yml @@ -0,0 +1,7 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + +two: + name: MyString diff --git a/test/fixtures/items.yml b/test/fixtures/items.yml new file mode 100644 index 0000000000..6609c00aa6 --- /dev/null +++ b/test/fixtures/items.yml @@ -0,0 +1,7 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + quantity: 1 + +two: + quantity: 1 diff --git a/test/fixtures/merchants.yml b/test/fixtures/merchants.yml new file mode 100644 index 0000000000..ae2ce03be8 --- /dev/null +++ b/test/fixtures/merchants.yml @@ -0,0 +1,13 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + username: MyString + email: MyString + uid: MyString + provider: MyString + +two: + username: MyString + email: MyString + uid: MyString + provider: MyString diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml new file mode 100644 index 0000000000..3efee21c66 --- /dev/null +++ b/test/fixtures/orders.yml @@ -0,0 +1,17 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + status: MyString + shopper_name: MyString + shopper_email: MyString + shopper_address: MyString + cc_four: MyString + cc_exp: MyString + +two: + status: MyString + shopper_name: MyString + shopper_email: MyString + shopper_address: MyString + cc_four: MyString + cc_exp: MyString diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml new file mode 100644 index 0000000000..c5365da831 --- /dev/null +++ b/test/fixtures/products.yml @@ -0,0 +1,17 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + price: 1 + description: MyString + photo_url: MyString + stock: 1 + active: false + +two: + name: MyString + price: 1 + description: MyString + photo_url: MyString + stock: 1 + active: false diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml new file mode 100644 index 0000000000..9c5cbbf36f --- /dev/null +++ b/test/fixtures/reviews.yml @@ -0,0 +1,9 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + rating: 1 + comment: MyString + +two: + rating: 1 + comment: MyString diff --git a/test/models/category_test.rb b/test/models/category_test.rb new file mode 100644 index 0000000000..781320ad8e --- /dev/null +++ b/test/models/category_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe Category do + let(:category) { Category.new } + + it "must be valid" do + value(category).must_be :valid? + end +end diff --git a/test/models/item_test.rb b/test/models/item_test.rb new file mode 100644 index 0000000000..9573bd9313 --- /dev/null +++ b/test/models/item_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe Item do + let(:item) { Item.new } + + it "must be valid" do + value(item).must_be :valid? + end +end diff --git a/test/models/merchant_test.rb b/test/models/merchant_test.rb new file mode 100644 index 0000000000..1cc99d985f --- /dev/null +++ b/test/models/merchant_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe Merchant do + let(:merchant) { Merchant.new } + + it "must be valid" do + value(merchant).must_be :valid? + end +end diff --git a/test/models/order_test.rb b/test/models/order_test.rb new file mode 100644 index 0000000000..df80f10fb6 --- /dev/null +++ b/test/models/order_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe Order do + let(:order) { Order.new } + + it "must be valid" do + value(order).must_be :valid? + end +end diff --git a/test/models/product_test.rb b/test/models/product_test.rb new file mode 100644 index 0000000000..a618b0a156 --- /dev/null +++ b/test/models/product_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe Product do + let(:product) { Product.new } + + it "must be valid" do + value(product).must_be :valid? + end +end diff --git a/test/models/review_test.rb b/test/models/review_test.rb new file mode 100644 index 0000000000..ce8378a033 --- /dev/null +++ b/test/models/review_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe Review do + let(:review) { Review.new } + + it "must be valid" do + value(review).must_be :valid? + end +end From baaa447dff2ff3a578c3daf203aaabc4ecccc106 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 15:22:13 -0700 Subject: [PATCH 003/260] testing shared branch --- db/test.rb | 1 + 1 file changed, 1 insertion(+) create mode 100644 db/test.rb diff --git a/db/test.rb b/db/test.rb new file mode 100644 index 0000000000..fdc03cdcdf --- /dev/null +++ b/db/test.rb @@ -0,0 +1 @@ +"this is a test." \ No newline at end of file From 0ddbda2e19fd824cac512f820446cea2c408f034 Mon Sep 17 00:00:00 2001 From: Cloudy Lopez Date: Wed, 1 May 2019 15:33:11 -0700 Subject: [PATCH 004/260] created seed generator and data files for merchant and product --- db/merchant_data.csv | 6 ++++++ db/merchant_generate_seeds.rb | 22 ++++++++++++++++++++++ db/products_data.csv | 21 +++++++++++++++++++++ db/products_generate_seeds.rb | 19 +++++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 db/merchant_data.csv create mode 100644 db/merchant_generate_seeds.rb create mode 100644 db/products_data.csv create mode 100644 db/products_generate_seeds.rb diff --git a/db/merchant_data.csv b/db/merchant_data.csv new file mode 100644 index 0000000000..2bd5a19afe --- /dev/null +++ b/db/merchant_data.csv @@ -0,0 +1,6 @@ +username,email,uid,provider +Farfetch'd,markus@upton.net,82039,github +Alakazam,barbera@bergnaum.info,90254,github +Caterpie,dominique@luettgenbruen.co,15965,github +Machop,mayeohara@skiles.info,81462,github +Nidorina,altha@grant.name,93644,github diff --git a/db/merchant_generate_seeds.rb b/db/merchant_generate_seeds.rb new file mode 100644 index 0000000000..e73d80cfee --- /dev/null +++ b/db/merchant_generate_seeds.rb @@ -0,0 +1,22 @@ +require "faker" +require "csv" + +# we already provide a filled out media_seeds.csv file, but feel free to +# run this script in order to replace it and generate a new one +# run using the command: +# $ ruby db/generate_seeds.rb +# if satisfied with this new media_seeds.csv file, recreate the db with: +# $ rails db:reset +# doesn't currently check for if titles are unique against each other + +CSV.open("merchant_data.csv", "w", :write_headers => true, + :headers => ["username", "email", "uid", "provider"]) do |csv| + 5.times do + username = Faker::Games::Pokemon.unique.name + email = Faker::Internet.unique.email + uid = Faker::Number.unique.number(5) + provider = "github" + + csv << [username, email, uid, provider] + end +end diff --git a/db/products_data.csv b/db/products_data.csv new file mode 100644 index 0000000000..80cb336517 --- /dev/null +++ b/db/products_data.csv @@ -0,0 +1,21 @@ +name,price,description,photo_url,stock +high fives,3990,They’ve got as much sex appeal as a road accident.,https://placekitten.com/g/200/300,9 +cup of sunshine,4277,"But Mr. Dent, the plans have been available in the local planning office for the last nine months.",https://placekitten.com/g/200/300,5 +bucket of sunshine,2089,Don’t Panic,https://placekitten.com/g/200/300,4 +sleep revival,4799,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://placekitten.com/g/200/300,3 +relaxation,3361,there’s an infinite number of monkeys outside who want to talk to us about this script for Hamlet they’ve worked out.,https://placekitten.com/g/200/300,9 +energy,1131,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://placekitten.com/g/200/300,15 +a good hair day,637,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://placekitten.com/g/200/300,8 +pause time,1758,42,https://placekitten.com/g/200/300,9 +freshly showered,4963,Parts of the inside of her head screamed at other parts of the inside of her head.,https://placekitten.com/g/200/300,5 +teleport into bed,3216,if you’ve never been through a matter transference beam before you’ve probably lost some salt and protein. The beer you had should have cushioned your system a bit.,https://placekitten.com/g/200/300,12 +ada starter kit,2397,"Whatever your tastes, Magrathea can cater for you. We are not proud.",https://placekitten.com/g/200/300,5 +ada best seller pack,4517,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://placekitten.com/g/200/300,11 +cup of rainbows,4282,"It’s only half completed, I’m afraid – we haven’t even finished burying the artificial dinosaur skeletons in the crust yet.",https://placekitten.com/g/200/300,1 +puppy play pack,2803,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://placekitten.com/g/200/300,1 +kitten cuddles,4928,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://placekitten.com/g/200/300,14 +giggle party,3250,"It seemed to me that any civilization that had so far lost its head as to need to include a set of detailed instructions for use in a packet of toothpicks, was no longer a civilization in which I could live and stay sane.",https://placekitten.com/g/200/300,1 +bestfriend time,2332,"According to the legends, the Magratheans lived most of their lives underground.",https://placekitten.com/g/200/300,10 +juicy secret,1170,"Evolution? they said to themselves, Who needs it?",https://placekitten.com/g/200/300,3 +inside joke moment,4141,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://placekitten.com/g/200/300,12 +bondfire time,2976,42,https://placekitten.com/g/200/300,8 diff --git a/db/products_generate_seeds.rb b/db/products_generate_seeds.rb new file mode 100644 index 0000000000..8b020ef49a --- /dev/null +++ b/db/products_generate_seeds.rb @@ -0,0 +1,19 @@ +require "faker" +require "csv" + +CSV.open("products_data.csv", "w", :write_headers => true, + :headers => ["name", "price", "description", "photo_url", "stock"]) do |csv| + intangibles = [ + "high fives", "cup of sunshine", "bucket of sunshine", "sleep revival", "relaxation", "energy", "a good hair day", "pause time", "freshly showered", "teleport into bed", "ada starter kit", "ada best seller pack", "cup of rainbows", "puppy play pack", "kitten cuddles", "giggle party", "bestfriend time", "juicy secret", "inside joke moment", "bondfire time" + ] + 20.times do |i| + + name = intangibles[i] + price = rand(500..5000) + description = Faker::Movies::HitchhikersGuideToTheGalaxy.quote + photo_url = "https://placekitten.com/g/200/300" + stock = rand(1..15) + + csv << [name, price, description, photo_url, stock] + end +end From 9b225fff4e6dbd0cf1996ce3be2727ae1e7719aa Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 15:33:55 -0700 Subject: [PATCH 005/260] removed test file --- db/test.rb | 1 - 1 file changed, 1 deletion(-) delete mode 100644 db/test.rb diff --git a/db/test.rb b/db/test.rb deleted file mode 100644 index fdc03cdcdf..0000000000 --- a/db/test.rb +++ /dev/null @@ -1 +0,0 @@ -"this is a test." \ No newline at end of file From fb723de899e680921759b9b3bb4ee28f773ba4ed Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Wed, 1 May 2019 15:36:26 -0700 Subject: [PATCH 006/260] Added relationships to each model. --- app/models/category.rb | 1 + app/models/item.rb | 2 ++ app/models/merchant.rb | 1 + app/models/order.rb | 1 + app/models/product.rb | 4 ++++ app/models/review.rb | 1 + 6 files changed, 10 insertions(+) diff --git a/app/models/category.rb b/app/models/category.rb index 54cb6aee3f..f3218758f1 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,2 +1,3 @@ class Category < ApplicationRecord + has_and_belongs_to_many :products end diff --git a/app/models/item.rb b/app/models/item.rb index 809e23f848..ef4625bcd4 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -1,2 +1,4 @@ class Item < ApplicationRecord + belongs_to :order + belongs_to :product end diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 0440407160..07aacc445d 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -1,2 +1,3 @@ class Merchant < ApplicationRecord + has_many :products end diff --git a/app/models/order.rb b/app/models/order.rb index 10281b3450..7abfa6be57 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,2 +1,3 @@ class Order < ApplicationRecord + has_many :items end diff --git a/app/models/product.rb b/app/models/product.rb index 35a85acab3..f59060e863 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,2 +1,6 @@ class Product < ApplicationRecord + belongs_to :merchant + has_and_belongs_to_many :categories + has_many :reviews + has_many :items end diff --git a/app/models/review.rb b/app/models/review.rb index b2ca4935ed..949d4ccddb 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -1,2 +1,3 @@ class Review < ApplicationRecord + belongs_to :product end From 083a1a66a6038bc0a717547000bb9b4398d8e9af Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Wed, 1 May 2019 15:55:01 -0700 Subject: [PATCH 007/260] Added validations to all models. Need to check on validating quantities syntax. --- app/models/category.rb | 2 ++ app/models/item.rb | 3 +++ app/models/merchant.rb | 5 +++++ app/models/product.rb | 4 ++++ app/models/review.rb | 3 +++ 5 files changed, 17 insertions(+) diff --git a/app/models/category.rb b/app/models/category.rb index f3218758f1..f8fdb0c9c1 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,3 +1,5 @@ class Category < ApplicationRecord has_and_belongs_to_many :products + + validates :name, presence: true, uniqueness: true end diff --git a/app/models/item.rb b/app/models/item.rb index ef4625bcd4..140fa35a21 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -1,4 +1,7 @@ class Item < ApplicationRecord belongs_to :order belongs_to :product + + validates :quantity, presence: true + validates_numericality_of :quantity, greater_than: 0 end diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 07aacc445d..8285669117 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -1,3 +1,8 @@ class Merchant < ApplicationRecord has_many :products + + validates :username, presence: true, uniqueness: true + validates :email, presence: true, uniqueness: true + validates :uid, presence: true + validates :provider, presence: true end diff --git a/app/models/product.rb b/app/models/product.rb index f59060e863..f73c5ab3d3 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -3,4 +3,8 @@ class Product < ApplicationRecord has_and_belongs_to_many :categories has_many :reviews has_many :items + + validates :name, presence: true, uniqueness: true + validates :price, presence: true + validates_numericality_of :price, greater_than: 0 end diff --git a/app/models/review.rb b/app/models/review.rb index 949d4ccddb..f25b33fbff 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -1,3 +1,6 @@ class Review < ApplicationRecord belongs_to :product + + validates :rating, presence: true + validates_inclusion_of :rating, :in => [1, 2, 3, 4, 5] end From 7c899779e42016e068bfb89aa5bf904b7768a0ed Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 15:58:44 -0700 Subject: [PATCH 008/260] inprogress of seeding db --- Gemfile | 4 ++++ Gemfile.lock | 2 ++ db/merchant_generate_seeds.rb | 3 +-- db/seeds.rb | 11 +++++++++++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index 80be142348..04cfa9b68c 100644 --- a/Gemfile +++ b/Gemfile @@ -79,3 +79,7 @@ group :test do gem 'minitest-rails' gem 'minitest-reporters' end + + + +gem 'csv' \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index 1cad6cf580..2e754159d4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -81,6 +81,7 @@ GEM coderay (1.1.2) concurrent-ruby (1.1.5) crass (1.0.4) + csv (3.1.1) debug_inspector (0.0.3) erubi (1.8.0) execjs (2.7.0) @@ -251,6 +252,7 @@ DEPENDENCIES byebug capybara (>= 2.15) chromedriver-helper + csv guard guard-minitest jbuilder (~> 2.5) diff --git a/db/merchant_generate_seeds.rb b/db/merchant_generate_seeds.rb index e73d80cfee..c56ff2cb0c 100644 --- a/db/merchant_generate_seeds.rb +++ b/db/merchant_generate_seeds.rb @@ -16,7 +16,6 @@ email = Faker::Internet.unique.email uid = Faker::Number.unique.number(5) provider = "github" - - csv << [username, email, uid, provider] + csv << [username, email, uid, provider] end end diff --git a/db/seeds.rb b/db/seeds.rb index 1beea2accd..f6d95ce29c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -5,3 +5,14 @@ # # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) # Character.create(name: 'Luke', movie: movies.first) +require "csv" +failed_to_save = [] +CSV.open("db/merchant_data.csv", headers: true).each_with_index do |line, i| + merchant = Merchant.new( + username: line["username"], + email: line["email"], + uid: line["uid"], + provider: line["provider"], + ) + merchant.save ? (puts "#{i + 1} merchant ") : failed_to_save << merchant +end From f37db5c1188d0a536842b57c61b1e54eb38fadec Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 16:15:50 -0700 Subject: [PATCH 009/260] products and merchants able to seed --- db/merchant_generate_seeds.rb | 14 +++++++------- db/seeds.rb | 12 +++++++++++- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/db/merchant_generate_seeds.rb b/db/merchant_generate_seeds.rb index c56ff2cb0c..3e610875d3 100644 --- a/db/merchant_generate_seeds.rb +++ b/db/merchant_generate_seeds.rb @@ -11,11 +11,11 @@ CSV.open("merchant_data.csv", "w", :write_headers => true, :headers => ["username", "email", "uid", "provider"]) do |csv| - 5.times do - username = Faker::Games::Pokemon.unique.name - email = Faker::Internet.unique.email - uid = Faker::Number.unique.number(5) - provider = "github" - csv << [username, email, uid, provider] - end + 5.times do + username = Faker::Games::Pokemon.unique.name + email = Faker::Internet.unique.email + uid = Faker::Number.unique.number(5) + provider = "github" + csv << [username, email, uid, provider] + end end diff --git a/db/seeds.rb b/db/seeds.rb index f6d95ce29c..57c2ee2366 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -14,5 +14,15 @@ uid: line["uid"], provider: line["provider"], ) - merchant.save ? (puts "#{i + 1} merchant ") : failed_to_save << merchant + merchant.save ? (puts "#{i + 1} merchant ") : failed_to_save << merchant +end + +CSV.open("db/products_data.csv", headers: true).each_with_index do |line, i| + merchant = Merchant.find(rand(1..Merchant.count)) + product = merchant.products.create(name: line["name"], + price: line["price"], + description: line["description"], + photo_url: line["photo_url"], + stock: line["stock"]) + product.valid? ? (puts "#{i + 1} product") : failed_to_save << product end From 0189543111d56a05356dc8d7e421321aeb33974f Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Wed, 1 May 2019 16:46:19 -0700 Subject: [PATCH 010/260] Initial set up for OAUTH --- .gitignore | 1 + Gemfile | 6 +++++- Gemfile.lock | 28 ++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 18b43c9cd2..be342dfab7 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ # Ignore master key for decrypting credentials and more. /config/master.key +.env diff --git a/Gemfile b/Gemfile index 04cfa9b68c..5f1cce2d5c 100644 --- a/Gemfile +++ b/Gemfile @@ -73,6 +73,7 @@ group :development do gem 'binding_of_caller' gem 'guard' gem 'guard-minitest' + gem 'dotenv-rails' end group :test do @@ -82,4 +83,7 @@ end -gem 'csv' \ No newline at end of file +gem 'csv' + +gem "omniauth" +gem "omniauth-github" \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index 2e754159d4..d24da0a647 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -83,8 +83,14 @@ GEM crass (1.0.4) csv (3.1.1) debug_inspector (0.0.3) + dotenv (2.7.2) + dotenv-rails (2.7.2) + dotenv (= 2.7.2) + railties (>= 3.2, < 6.1) erubi (1.8.0) execjs (2.7.0) + faraday (0.15.4) + multipart-post (>= 1.2, < 3) ffi (1.10.0) formatador (0.2.5) globalid (0.4.2) @@ -102,6 +108,7 @@ GEM guard-minitest (2.4.6) guard-compat (~> 1.2) minitest (>= 3.0) + hashie (3.6.0) i18n (1.6.0) concurrent-ruby (~> 1.0) io-like (0.3.0) @@ -115,6 +122,7 @@ GEM jquery-turbolinks (2.1.0) railties (>= 3.1.0) turbolinks + jwt (2.1.0) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -142,6 +150,8 @@ GEM ruby-progressbar msgpack (1.2.10) multi_json (1.13.1) + multi_xml (0.6.0) + multipart-post (2.0.0) nenv (0.3.0) nio4r (2.3.1) nokogiri (1.10.3) @@ -149,6 +159,21 @@ GEM notiffany (0.1.1) nenv (~> 0.1) shellany (~> 0.0) + oauth2 (1.4.1) + faraday (>= 0.8, < 0.16.0) + jwt (>= 1.0, < 3.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + omniauth (1.9.0) + hashie (>= 3.4.6, < 3.7.0) + rack (>= 1.6.2, < 3) + omniauth-github (1.3.0) + omniauth (~> 1.5) + omniauth-oauth2 (>= 1.4.0, < 2.0) + omniauth-oauth2 (1.6.0) + oauth2 (~> 1.1) + omniauth (~> 1.9) pg (1.1.4) popper_js (1.14.5) pry (0.12.2) @@ -253,6 +278,7 @@ DEPENDENCIES capybara (>= 2.15) chromedriver-helper csv + dotenv-rails guard guard-minitest jbuilder (~> 2.5) @@ -261,6 +287,8 @@ DEPENDENCIES listen (>= 3.0.5, < 3.2) minitest-rails minitest-reporters + omniauth + omniauth-github pg (>= 0.18, < 2.0) pry-rails puma (~> 3.11) From 17a9a3f5d9b2c0ff572d96c50ab21f1adf5ec745 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 16:47:44 -0700 Subject: [PATCH 011/260] fixtures look good --- test/fixtures/categories.yml | 4 ++-- test/fixtures/items.yml | 8 ++++++-- test/fixtures/merchants.yml | 16 ++++++++-------- test/fixtures/orders.yml | 24 ++++++++++++------------ test/fixtures/products.yml | 26 ++++++++++++++------------ test/fixtures/reviews.yml | 10 ++++++---- test/test_helper.rb | 4 ++-- 7 files changed, 50 insertions(+), 42 deletions(-) diff --git a/test/fixtures/categories.yml b/test/fixtures/categories.yml index 56066c68af..265b1f51c1 100644 --- a/test/fixtures/categories.yml +++ b/test/fixtures/categories.yml @@ -1,7 +1,7 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html one: - name: MyString + name: majestic two: - name: MyString + name: happiness diff --git a/test/fixtures/items.yml b/test/fixtures/items.yml index 6609c00aa6..8df94ece20 100644 --- a/test/fixtures/items.yml +++ b/test/fixtures/items.yml @@ -1,7 +1,11 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html one: - quantity: 1 + quantity: 5 + order: orders(:one) + product: products(:one) two: - quantity: 1 + quantity: 3 + order: orders(:one) + product: products(:two) diff --git a/test/fixtures/merchants.yml b/test/fixtures/merchants.yml index ae2ce03be8..f42e33ceba 100644 --- a/test/fixtures/merchants.yml +++ b/test/fixtures/merchants.yml @@ -1,13 +1,13 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html one: - username: MyString - email: MyString - uid: MyString - provider: MyString + username: pickchu + email: pickhu@yahoo.com + uid: 2342 + provider: github two: - username: MyString - email: MyString - uid: MyString - provider: MyString + username: lemonlulu + email: lululumen@yahoo.com + uid: 5435 + provider: github diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index 3efee21c66..641cd21c09 100644 --- a/test/fixtures/orders.yml +++ b/test/fixtures/orders.yml @@ -1,17 +1,17 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html one: - status: MyString - shopper_name: MyString - shopper_email: MyString - shopper_address: MyString - cc_four: MyString - cc_exp: MyString + status: completed + shopper_name: susie + shopper_email: dalmation@susy.org + shopper_address: 4455 mailing address + cc_four: 3434 + cc_exp: 03022020 two: - status: MyString - shopper_name: MyString - shopper_email: MyString - shopper_address: MyString - cc_four: MyString - cc_exp: MyString + status: completed + shopper_name: miranda + shopper_email: panda@hooo.com + shopper_address: 43244 tryagain address + cc_four: 2534 + cc_exp: 09092020 diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index c5365da831..66b4a0b337 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -1,17 +1,19 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html one: - name: MyString - price: 1 - description: MyString - photo_url: MyString - stock: 1 - active: false + name: bucket of rain + price: 1087 + description: just like it sounds you sad person + photo_url: https://notonmyblock.com + stock: 8 + active: true + merchant: merchants(:one) two: - name: MyString - price: 1 - description: MyString - photo_url: MyString - stock: 1 - active: false + name: sushine and rainbows + price: 1722 + description: nice stuff wooowza + photo_url: https://yeahforsure.org + stock: 7 + active: true + merchant: merchants(:one) diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml index 9c5cbbf36f..057cb575ef 100644 --- a/test/fixtures/reviews.yml +++ b/test/fixtures/reviews.yml @@ -1,9 +1,11 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html one: - rating: 1 - comment: MyString + rating: 4 + comment: impressive liked it a lot it was supppper good + product: products(:one) two: - rating: 1 - comment: MyString + rating: 2 + comment: not so awesome sad face + product: products(:one) diff --git a/test/test_helper.rb b/test/test_helper.rb index 2b5172a7d6..3f7dc7d3ed 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,7 +1,8 @@ ENV["RAILS_ENV"] = "test" require File.expand_path("../../config/environment", __FILE__) require "rails/test_help" -require "minitest/rails"require "minitest/reporters" # for Colorized output +require "minitest/rails" +require "minitest/reporters" # for Colorized output # For colorful output! Minitest::Reporters.use!( Minitest::Reporters::SpecReporter.new, @@ -9,7 +10,6 @@ Minitest.backtrace_filter ) - # To add Capybara feature tests add `gem "minitest-rails-capybara"` # to the test group in the Gemfile and uncomment the following: # require "minitest/rails/capybara" From d945e5c9420a9a8173ebd8a463b27d800f0591ec Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 16:54:27 -0700 Subject: [PATCH 012/260] added valid test to merchant --- test/fixtures/products.yml | 2 +- test/models/merchant_test.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index 66b4a0b337..0961a5c584 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -16,4 +16,4 @@ two: photo_url: https://yeahforsure.org stock: 7 active: true - merchant: merchants(:one) + merchant: merchants(:one) diff --git a/test/models/merchant_test.rb b/test/models/merchant_test.rb index 1cc99d985f..76dd583dea 100644 --- a/test/models/merchant_test.rb +++ b/test/models/merchant_test.rb @@ -1,9 +1,9 @@ require "test_helper" describe Merchant do - let(:merchant) { Merchant.new } + let(:merchant){merchants(:one)} it "must be valid" do - value(merchant).must_be :valid? + expect(merchant.valid?).must_equal true end end From f8eafa2cac46e2ada5026d676731ae5697f4be59 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 16:55:28 -0700 Subject: [PATCH 013/260] fixed fixture --- test/fixtures/products.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index 66b4a0b337..0961a5c584 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -16,4 +16,4 @@ two: photo_url: https://yeahforsure.org stock: 7 active: true - merchant: merchants(:one) + merchant: merchants(:one) From 530b698473b9faf436e9163dc40dad9a59c5d960 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Wed, 1 May 2019 17:13:34 -0700 Subject: [PATCH 014/260] Generated all controllers and known crud actions needed. --- .env | 2 ++ app/assets/javascripts/categories.js | 2 ++ app/assets/javascripts/items.js | 2 ++ app/assets/javascripts/merchants.js | 2 ++ app/assets/javascripts/orders.js | 2 ++ app/assets/javascripts/products.js | 2 ++ app/assets/javascripts/reviews.js | 2 ++ app/assets/stylesheets/categories.scss | 3 ++ app/assets/stylesheets/items.scss | 3 ++ app/assets/stylesheets/merchants.scss | 3 ++ app/assets/stylesheets/orders.scss | 3 ++ app/assets/stylesheets/products.scss | 3 ++ app/assets/stylesheets/reviews.scss | 3 ++ app/controllers/categories_controller.rb | 10 ++++++ app/controllers/items_controller.rb | 10 ++++++ app/controllers/merchants_controller.rb | 10 ++++++ app/controllers/orders_controller.rb | 2 ++ app/controllers/products_controller.rb | 19 +++++++++++ app/controllers/reviews_controller.rb | 4 +++ app/helpers/categories_helper.rb | 2 ++ app/helpers/items_helper.rb | 2 ++ app/helpers/merchants_helper.rb | 2 ++ app/helpers/orders_helper.rb | 2 ++ app/helpers/products_helper.rb | 2 ++ app/helpers/reviews_helper.rb | 2 ++ app/views/categories/create.html.erb | 2 ++ app/views/categories/index.html.erb | 2 ++ app/views/categories/new.html.erb | 2 ++ app/views/items/create.html.erb | 2 ++ app/views/items/delete.html.erb | 2 ++ app/views/items/update.html.erb | 2 ++ app/views/merchants/create.html.erb | 2 ++ app/views/merchants/delete.html.erb | 2 ++ app/views/merchants/show.html.erb | 2 ++ app/views/products/create.html.erb | 2 ++ app/views/products/edit.html.erb | 2 ++ app/views/products/index.html.erb | 2 ++ app/views/products/new.html.erb | 2 ++ app/views/products/show.html.erb | 2 ++ app/views/products/update.html.erb | 2 ++ app/views/reviews/create.html.erb | 2 ++ config/routes.rb | 16 +++++++++ .../controllers/categories_controller_test.rb | 19 +++++++++++ test/controllers/items_controller_test.rb | 19 +++++++++++ test/controllers/merchants_controller_test.rb | 19 +++++++++++ test/controllers/orders_controller_test.rb | 7 ++++ test/controllers/products_controller_test.rb | 34 +++++++++++++++++++ test/controllers/reviews_controller_test.rb | 9 +++++ 48 files changed, 254 insertions(+) create mode 100644 .env create mode 100644 app/assets/javascripts/categories.js create mode 100644 app/assets/javascripts/items.js create mode 100644 app/assets/javascripts/merchants.js create mode 100644 app/assets/javascripts/orders.js create mode 100644 app/assets/javascripts/products.js create mode 100644 app/assets/javascripts/reviews.js create mode 100644 app/assets/stylesheets/categories.scss create mode 100644 app/assets/stylesheets/items.scss create mode 100644 app/assets/stylesheets/merchants.scss create mode 100644 app/assets/stylesheets/orders.scss create mode 100644 app/assets/stylesheets/products.scss create mode 100644 app/assets/stylesheets/reviews.scss create mode 100644 app/controllers/categories_controller.rb create mode 100644 app/controllers/items_controller.rb create mode 100644 app/controllers/merchants_controller.rb create mode 100644 app/controllers/orders_controller.rb create mode 100644 app/controllers/products_controller.rb create mode 100644 app/controllers/reviews_controller.rb create mode 100644 app/helpers/categories_helper.rb create mode 100644 app/helpers/items_helper.rb create mode 100644 app/helpers/merchants_helper.rb create mode 100644 app/helpers/orders_helper.rb create mode 100644 app/helpers/products_helper.rb create mode 100644 app/helpers/reviews_helper.rb create mode 100644 app/views/categories/create.html.erb create mode 100644 app/views/categories/index.html.erb create mode 100644 app/views/categories/new.html.erb create mode 100644 app/views/items/create.html.erb create mode 100644 app/views/items/delete.html.erb create mode 100644 app/views/items/update.html.erb create mode 100644 app/views/merchants/create.html.erb create mode 100644 app/views/merchants/delete.html.erb create mode 100644 app/views/merchants/show.html.erb create mode 100644 app/views/products/create.html.erb create mode 100644 app/views/products/edit.html.erb create mode 100644 app/views/products/index.html.erb create mode 100644 app/views/products/new.html.erb create mode 100644 app/views/products/show.html.erb create mode 100644 app/views/products/update.html.erb create mode 100644 app/views/reviews/create.html.erb create mode 100644 test/controllers/categories_controller_test.rb create mode 100644 test/controllers/items_controller_test.rb create mode 100644 test/controllers/merchants_controller_test.rb create mode 100644 test/controllers/orders_controller_test.rb create mode 100644 test/controllers/products_controller_test.rb create mode 100644 test/controllers/reviews_controller_test.rb diff --git a/.env b/.env new file mode 100644 index 0000000000..55771652bc --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +GITHUB_CLIENT_ID: 3c49067b5430afe2f192 +GITHUB_CLIENT_SECRET: 739c1767ae23ed4d4ef085e7509483d5702dac73 \ No newline at end of file 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/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/merchants.js b/app/assets/javascripts/merchants.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/merchants.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/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/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/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/merchants.scss b/app/assets/stylesheets/merchants.scss new file mode 100644 index 0000000000..f4c164d600 --- /dev/null +++ b/app/assets/stylesheets/merchants.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Merchants 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..bff386e55a --- /dev/null +++ b/app/assets/stylesheets/products.scss @@ -0,0 +1,3 @@ +// 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/ diff --git a/app/assets/stylesheets/reviews.scss b/app/assets/stylesheets/reviews.scss new file mode 100644 index 0000000000..11bbb12cd5 --- /dev/null +++ b/app/assets/stylesheets/reviews.scss @@ -0,0 +1,3 @@ +// 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/ diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb new file mode 100644 index 0000000000..f4da35f056 --- /dev/null +++ b/app/controllers/categories_controller.rb @@ -0,0 +1,10 @@ +class CategoriesController < ApplicationController + def new + end + + def create + end + + def index + end +end diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb new file mode 100644 index 0000000000..b71ad7e6b6 --- /dev/null +++ b/app/controllers/items_controller.rb @@ -0,0 +1,10 @@ +class ItemsController < ApplicationController + def create + end + + def update + end + + def delete + end +end diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb new file mode 100644 index 0000000000..64f9bb7f83 --- /dev/null +++ b/app/controllers/merchants_controller.rb @@ -0,0 +1,10 @@ +class MerchantsController < ApplicationController + def create + end + + def show + end + + def delete + end +end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb new file mode 100644 index 0000000000..8a0e3659ae --- /dev/null +++ b/app/controllers/orders_controller.rb @@ -0,0 +1,2 @@ +class OrdersController < ApplicationController +end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb new file mode 100644 index 0000000000..616cc46ce5 --- /dev/null +++ b/app/controllers/products_controller.rb @@ -0,0 +1,19 @@ +class ProductsController < ApplicationController + def new + end + + def create + end + + def index + end + + def show + end + + def edit + end + + def update + end +end diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb new file mode 100644 index 0000000000..8a899b6208 --- /dev/null +++ b/app/controllers/reviews_controller.rb @@ -0,0 +1,4 @@ +class ReviewsController < ApplicationController + def create + end +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/merchants_helper.rb b/app/helpers/merchants_helper.rb new file mode 100644 index 0000000000..5337747b0f --- /dev/null +++ b/app/helpers/merchants_helper.rb @@ -0,0 +1,2 @@ +module MerchantsHelper +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/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 @@ +

Categories#create

+

Find me in app/views/categories/create.html.erb

diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb new file mode 100644 index 0000000000..a5d0d54736 --- /dev/null +++ b/app/views/categories/index.html.erb @@ -0,0 +1,2 @@ +

Categories#index

+

Find me in app/views/categories/index.html.erb

diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb new file mode 100644 index 0000000000..7e5c27307e --- /dev/null +++ b/app/views/categories/new.html.erb @@ -0,0 +1,2 @@ +

Categories#new

+

Find me in app/views/categories/new.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 @@ +

Items#create

+

Find me in app/views/items/create.html.erb

diff --git a/app/views/items/delete.html.erb b/app/views/items/delete.html.erb new file mode 100644 index 0000000000..403a4aa6ef --- /dev/null +++ b/app/views/items/delete.html.erb @@ -0,0 +1,2 @@ +

Items#delete

+

Find me in app/views/items/delete.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 @@ +

Items#update

+

Find me in app/views/items/update.html.erb

diff --git a/app/views/merchants/create.html.erb b/app/views/merchants/create.html.erb new file mode 100644 index 0000000000..1762feece0 --- /dev/null +++ b/app/views/merchants/create.html.erb @@ -0,0 +1,2 @@ +

Merchants#create

+

Find me in app/views/merchants/create.html.erb

diff --git a/app/views/merchants/delete.html.erb b/app/views/merchants/delete.html.erb new file mode 100644 index 0000000000..ba4a05e513 --- /dev/null +++ b/app/views/merchants/delete.html.erb @@ -0,0 +1,2 @@ +

Merchants#delete

+

Find me in app/views/merchants/delete.html.erb

diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb new file mode 100644 index 0000000000..cbb0f02bfe --- /dev/null +++ b/app/views/merchants/show.html.erb @@ -0,0 +1,2 @@ +

Merchants#show

+

Find me in app/views/merchants/show.html.erb

diff --git a/app/views/products/create.html.erb b/app/views/products/create.html.erb new file mode 100644 index 0000000000..d546021001 --- /dev/null +++ b/app/views/products/create.html.erb @@ -0,0 +1,2 @@ +

Products#create

+

Find me in app/views/products/create.html.erb

diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb new file mode 100644 index 0000000000..279b066f30 --- /dev/null +++ b/app/views/products/edit.html.erb @@ -0,0 +1,2 @@ +

Products#edit

+

Find me in app/views/products/edit.html.erb

diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb new file mode 100644 index 0000000000..f8eeb82674 --- /dev/null +++ b/app/views/products/index.html.erb @@ -0,0 +1,2 @@ +

Products#index

+

Find me in app/views/products/index.html.erb

diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb new file mode 100644 index 0000000000..a14e0d91b6 --- /dev/null +++ b/app/views/products/new.html.erb @@ -0,0 +1,2 @@ +

Products#new

+

Find me in app/views/products/new.html.erb

diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb new file mode 100644 index 0000000000..5f44ec44d2 --- /dev/null +++ b/app/views/products/show.html.erb @@ -0,0 +1,2 @@ +

Products#show

+

Find me in app/views/products/show.html.erb

diff --git a/app/views/products/update.html.erb b/app/views/products/update.html.erb new file mode 100644 index 0000000000..039889ac02 --- /dev/null +++ b/app/views/products/update.html.erb @@ -0,0 +1,2 @@ +

Products#update

+

Find me in app/views/products/update.html.erb

diff --git a/app/views/reviews/create.html.erb b/app/views/reviews/create.html.erb new file mode 100644 index 0000000000..44bf11c2ed --- /dev/null +++ b/app/views/reviews/create.html.erb @@ -0,0 +1,2 @@ +

Reviews#create

+

Find me in app/views/reviews/create.html.erb

diff --git a/config/routes.rb b/config/routes.rb index 787824f888..f9eaf4acb2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,19 @@ Rails.application.routes.draw do + get 'categories/new' + get 'categories/create' + get 'categories/index' + get 'products/new' + get 'products/create' + get 'products/index' + get 'products/show' + get 'products/edit' + get 'products/update' + get 'items/create' + get 'items/update' + get 'items/delete' + get 'merchants/create' + get 'merchants/show' + get 'merchants/delete' + get 'reviews/create' # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end diff --git a/test/controllers/categories_controller_test.rb b/test/controllers/categories_controller_test.rb new file mode 100644 index 0000000000..12fbe92175 --- /dev/null +++ b/test/controllers/categories_controller_test.rb @@ -0,0 +1,19 @@ +require "test_helper" + +describe CategoriesController do + it "should get new" do + get categories_new_url + value(response).must_be :success? + end + + it "should get create" do + get categories_create_url + value(response).must_be :success? + end + + it "should get index" do + get categories_index_url + value(response).must_be :success? + end + +end diff --git a/test/controllers/items_controller_test.rb b/test/controllers/items_controller_test.rb new file mode 100644 index 0000000000..af9e62f08c --- /dev/null +++ b/test/controllers/items_controller_test.rb @@ -0,0 +1,19 @@ +require "test_helper" + +describe ItemsController do + it "should get create" do + get items_create_url + value(response).must_be :success? + end + + it "should get update" do + get items_update_url + value(response).must_be :success? + end + + it "should get delete" do + get items_delete_url + value(response).must_be :success? + end + +end diff --git a/test/controllers/merchants_controller_test.rb b/test/controllers/merchants_controller_test.rb new file mode 100644 index 0000000000..233f656bf2 --- /dev/null +++ b/test/controllers/merchants_controller_test.rb @@ -0,0 +1,19 @@ +require "test_helper" + +describe MerchantsController do + it "should get create" do + get merchants_create_url + value(response).must_be :success? + end + + it "should get show" do + get merchants_show_url + value(response).must_be :success? + end + + it "should get delete" do + get merchants_delete_url + value(response).must_be :success? + end + +end diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb new file mode 100644 index 0000000000..68784595f3 --- /dev/null +++ b/test/controllers/orders_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +describe OrdersController do + # it "must be a real test" do + # flunk "Need real tests" + # end +end diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb new file mode 100644 index 0000000000..e8b99e3c29 --- /dev/null +++ b/test/controllers/products_controller_test.rb @@ -0,0 +1,34 @@ +require "test_helper" + +describe ProductsController do + it "should get new" do + get products_new_url + value(response).must_be :success? + end + + it "should get create" do + get products_create_url + value(response).must_be :success? + end + + it "should get index" do + get products_index_url + value(response).must_be :success? + end + + it "should get show" do + get products_show_url + value(response).must_be :success? + end + + it "should get edit" do + get products_edit_url + value(response).must_be :success? + end + + it "should get update" do + get products_update_url + value(response).must_be :success? + end + +end diff --git a/test/controllers/reviews_controller_test.rb b/test/controllers/reviews_controller_test.rb new file mode 100644 index 0000000000..ec5a16b90e --- /dev/null +++ b/test/controllers/reviews_controller_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe ReviewsController do + it "should get create" do + get reviews_create_url + value(response).must_be :success? + end + +end From d554bdb47ae2f9cf965e460b8b8d77ed3ba13e44 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Wed, 1 May 2019 17:34:19 -0700 Subject: [PATCH 015/260] Added OAuth login and logout actions and routes. --- app/controllers/merchants_controller.rb | 35 ++++++++++++++++++++++--- config/routes.rb | 27 ++++++++----------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 64f9bb7f83..388b3aeb1b 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -1,10 +1,39 @@ class MerchantsController < ApplicationController - def create + def show end - def show + def create + auth_hash = request.env["omniauth.auth"] + + merchant = Merchant.find_by(uid: auth_hash[:uid], provider: "github") + if merchant + # merchant was found in the database + flash[:success] = "Logged in as returning merchant #{merchant.name}" + else + # merchant doesn't match anything in the DB + # Attempt to create a new merchant + merchant = Merchant.build_from_github(auth_hash) + + if merchant.save + flash[:success] = "Logged in as new merchant #{merchant.name}" + else + # Couldn't save the merchant for some reason. If we + # hit this it probably means there's a bug with the + # way we've configured GitHub. Our strategy will + # be to display error messages to make future + # debugging easier. + flash[:error] = "Could not create new merchant account: #{merchant.errors.messages}" + return redirect_to root_path + end + end + # If we get here, we have a valid merchant instance + session[:merchant_id] = merchant.id + return redirect_to root_path end - def delete + def destroy + session[:merchant_id] = nil + flash[:success] = "Successfully logged out!" + redirect_to root_path end end diff --git a/config/routes.rb b/config/routes.rb index f9eaf4acb2..c29f52d502 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,19 +1,14 @@ Rails.application.routes.draw do - get 'categories/new' - get 'categories/create' - get 'categories/index' - get 'products/new' - get 'products/create' - get 'products/index' - get 'products/show' - get 'products/edit' - get 'products/update' - get 'items/create' - get 'items/update' - get 'items/delete' - get 'merchants/create' - get 'merchants/show' - get 'merchants/delete' - get 'reviews/create' + resources :categories, only: [:new, :create, :index] + resources :products, except: [:delete] + resources :items, only: [:create, :update, :delete] + resources :merchants, only: [:create, :show, :delete] + resources :reviews, only: [:create] + resources :orders # UPDATE THIS AFTER WE DECIDE WHAT WE NEED/DON'T + + get "/auth/github", as: "github_login" + get "/auth/:provider/callback", to: "users#create" + delete "/logout", to: "users#destroy", as: “logout” + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end From 9f5f4b508accbf8cd58aaeb878827f0c567397c2 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 20:40:06 -0700 Subject: [PATCH 016/260] add scaffolding --- test/models/merchant_test.rb | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/test/models/merchant_test.rb b/test/models/merchant_test.rb index 76dd583dea..5d6568bf14 100644 --- a/test/models/merchant_test.rb +++ b/test/models/merchant_test.rb @@ -1,9 +1,34 @@ require "test_helper" describe Merchant do - let(:merchant){merchants(:one)} + let(:merchant) { merchants(:one) } it "must be valid" do expect(merchant.valid?).must_equal true end + + # validates :username, presence: true, uniqueness: true + # validates :email, presence: true, uniqueness: true + # validates :uid, presence: true + # validates :provider, presence: true + + describe "validations" do + it "will not be valid if missing username" do + end + + it "will not be valid if username is not unique" do + end + + it "will not be valid if missing email" do + end + + it "will not be valid if email is not unique" do + end + + it "will not be valid if missing uid" do + end + + it "will not be valid if missing provider" do + end + end end From a109277cf3aa658f4d8c96cd090a5465dc4c6f6f Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 20:59:52 -0700 Subject: [PATCH 017/260] completed model for merchant --- test/models/merchant_test.rb | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/test/models/merchant_test.rb b/test/models/merchant_test.rb index 5d6568bf14..21e7b113c1 100644 --- a/test/models/merchant_test.rb +++ b/test/models/merchant_test.rb @@ -7,28 +7,41 @@ expect(merchant.valid?).must_equal true end - # validates :username, presence: true, uniqueness: true - # validates :email, presence: true, uniqueness: true - # validates :uid, presence: true - # validates :provider, presence: true - describe "validations" do it "will not be valid if missing username" do + merchant.username = nil + expect(merchant.valid?).must_equal false end it "will not be valid if username is not unique" do + merchant_dup = Merchant.new(username: merchant.username, + email: "duplicate@adda.com", + uid: "4527", + provider: "github") + expect(merchant_dup.valid?).must_equal false end it "will not be valid if missing email" do + merchant.email = nil + expect(merchant.valid?).must_equal false end it "will not be valid if email is not unique" do + merchant_dup = Merchant.new(username: "gilfoyle", + email: merchant.email, + uid: "4527", + provider: "github") + expect(merchant_dup.valid?).must_equal false end it "will not be valid if missing uid" do + merchant.uid = nil + expect(merchant.valid?).must_equal false end - + it "will not be valid if missing provider" do + merchant.provider = nil + expect(merchant.valid?).must_equal false end end end From d676d4484779e89adf2d05f0f54ed067a6726db5 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 20:59:52 -0700 Subject: [PATCH 018/260] completed validation testing for merchant model --- test/models/merchant_test.rb | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/test/models/merchant_test.rb b/test/models/merchant_test.rb index 5d6568bf14..21e7b113c1 100644 --- a/test/models/merchant_test.rb +++ b/test/models/merchant_test.rb @@ -7,28 +7,41 @@ expect(merchant.valid?).must_equal true end - # validates :username, presence: true, uniqueness: true - # validates :email, presence: true, uniqueness: true - # validates :uid, presence: true - # validates :provider, presence: true - describe "validations" do it "will not be valid if missing username" do + merchant.username = nil + expect(merchant.valid?).must_equal false end it "will not be valid if username is not unique" do + merchant_dup = Merchant.new(username: merchant.username, + email: "duplicate@adda.com", + uid: "4527", + provider: "github") + expect(merchant_dup.valid?).must_equal false end it "will not be valid if missing email" do + merchant.email = nil + expect(merchant.valid?).must_equal false end it "will not be valid if email is not unique" do + merchant_dup = Merchant.new(username: "gilfoyle", + email: merchant.email, + uid: "4527", + provider: "github") + expect(merchant_dup.valid?).must_equal false end it "will not be valid if missing uid" do + merchant.uid = nil + expect(merchant.valid?).must_equal false end - + it "will not be valid if missing provider" do + merchant.provider = nil + expect(merchant.valid?).must_equal false end end end From 6e4cfb5f7bc81dccf90fac41c6189421ff532f3a Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 22:00:43 -0700 Subject: [PATCH 019/260] troubleshooting fixture relationships --- test/fixtures/categories.yml | 4 ++-- test/fixtures/items.yml | 8 ++++---- test/fixtures/merchants.yml | 4 ++-- test/fixtures/orders.yml | 4 ++-- test/fixtures/products.yml | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/test/fixtures/categories.yml b/test/fixtures/categories.yml index 265b1f51c1..4c0ed821ca 100644 --- a/test/fixtures/categories.yml +++ b/test/fixtures/categories.yml @@ -1,7 +1,7 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: +category_1: name: majestic -two: +category_2: name: happiness diff --git a/test/fixtures/items.yml b/test/fixtures/items.yml index 8df94ece20..b344b7f047 100644 --- a/test/fixtures/items.yml +++ b/test/fixtures/items.yml @@ -1,11 +1,11 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: +item_1: quantity: 5 order: orders(:one) - product: products(:one) + product: product_1 -two: +item_2: quantity: 3 order: orders(:one) - product: products(:two) + product: product_2 diff --git a/test/fixtures/merchants.yml b/test/fixtures/merchants.yml index f42e33ceba..51d62f0c52 100644 --- a/test/fixtures/merchants.yml +++ b/test/fixtures/merchants.yml @@ -1,12 +1,12 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: +merchant_1: username: pickchu email: pickhu@yahoo.com uid: 2342 provider: github -two: +merchant_2: username: lemonlulu email: lululumen@yahoo.com uid: 5435 diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index 641cd21c09..5d21fcc4e8 100644 --- a/test/fixtures/orders.yml +++ b/test/fixtures/orders.yml @@ -1,6 +1,6 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: +orders_one: status: completed shopper_name: susie shopper_email: dalmation@susy.org @@ -8,7 +8,7 @@ one: cc_four: 3434 cc_exp: 03022020 -two: +orders_two: status: completed shopper_name: miranda shopper_email: panda@hooo.com diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index 0961a5c584..73d38f78d7 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -1,19 +1,19 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: +product_1: name: bucket of rain price: 1087 description: just like it sounds you sad person photo_url: https://notonmyblock.com stock: 8 active: true - merchant: merchants(:one) + merchant: merchant_2 -two: +product_2: name: sushine and rainbows price: 1722 description: nice stuff wooowza photo_url: https://yeahforsure.org stock: 7 active: true - merchant: merchants(:one) + merchant: merchant_2 From 6788fbe2e2849bafd5732fa8daeceb52cd568a63 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 22:07:56 -0700 Subject: [PATCH 020/260] updated fixture keys for easier use and to generate more fixtures if required --- test/fixtures/items.yml | 4 ++-- test/fixtures/orders.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/fixtures/items.yml b/test/fixtures/items.yml index b344b7f047..34d89caf4b 100644 --- a/test/fixtures/items.yml +++ b/test/fixtures/items.yml @@ -2,10 +2,10 @@ item_1: quantity: 5 - order: orders(:one) + order: orders_1 product: product_1 item_2: quantity: 3 - order: orders(:one) + order: orders_1 product: product_2 diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index 5d21fcc4e8..67b254081f 100644 --- a/test/fixtures/orders.yml +++ b/test/fixtures/orders.yml @@ -1,6 +1,6 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -orders_one: +orders_1: status: completed shopper_name: susie shopper_email: dalmation@susy.org @@ -8,7 +8,7 @@ orders_one: cc_four: 3434 cc_exp: 03022020 -orders_two: +orders_2: status: completed shopper_name: miranda shopper_email: panda@hooo.com From 2487c9d603e0462d1c3d03969ce90115cba9715f Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 22:41:02 -0700 Subject: [PATCH 021/260] finished testing relationships and validations for merchant --- test/models/merchant_test.rb | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/test/models/merchant_test.rb b/test/models/merchant_test.rb index 21e7b113c1..9a5322be02 100644 --- a/test/models/merchant_test.rb +++ b/test/models/merchant_test.rb @@ -1,7 +1,7 @@ require "test_helper" describe Merchant do - let(:merchant) { merchants(:one) } + let(:merchant) { merchants(:merchant_1) } it "must be valid" do expect(merchant.valid?).must_equal true @@ -11,6 +11,8 @@ it "will not be valid if missing username" do merchant.username = nil expect(merchant.valid?).must_equal false + expect(merchant.errors.include?(:username)).must_equal true + expect(merchant.errors[:username]).must_equal ["can't be blank"] end it "will not be valid if username is not unique" do @@ -19,11 +21,15 @@ uid: "4527", provider: "github") expect(merchant_dup.valid?).must_equal false + expect(merchant_dup.errors.include?(:username)).must_equal true + expect(merchant_dup.errors[:username]).must_equal ["has already been taken"] end it "will not be valid if missing email" do merchant.email = nil expect(merchant.valid?).must_equal false + expect(merchant.errors.include?(:email)).must_equal true + expect(merchant.errors[:email]).must_equal ["can't be blank"] end it "will not be valid if email is not unique" do @@ -32,16 +38,41 @@ uid: "4527", provider: "github") expect(merchant_dup.valid?).must_equal false + expect(merchant_dup.errors.include?(:email)).must_equal true + expect(merchant_dup.errors[:email]).must_equal ["has already been taken"] end it "will not be valid if missing uid" do merchant.uid = nil expect(merchant.valid?).must_equal false + expect(merchant.errors.include?(:uid)).must_equal true + expect(merchant.errors[:uid]).must_equal ["can't be blank"] end it "will not be valid if missing provider" do merchant.provider = nil expect(merchant.valid?).must_equal false + expect(merchant.errors.include?(:provider)).must_equal true + expect(merchant.errors[:provider]).must_equal ["can't be blank"] + end + end + + describe "relationship with product" do + it "can have 0 products" do + expect(merchant.products.count).must_equal 0 + end + + it "can have 1 or more products" do + merchant = merchants(:merchant_2) + expect(merchant.products.count).must_equal 2 + end + + it "can shovel product to create relationship" do + product = Product.new(name: "penny", price: 1200) + expect(product.valid?).must_equal false + merchant.products << product + expect(product.valid?).must_equal true + expect(merchant.products.include?(product)).must_equal true end end end From 2c11e1a4a9ec26bd200570e2c1870fef029d8eff Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 22:42:44 -0700 Subject: [PATCH 022/260] starting on reviews --- test/models/review_test.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/models/review_test.rb b/test/models/review_test.rb index ce8378a033..7c1b87012f 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -7,3 +7,9 @@ value(review).must_be :valid? end end + + +# belongs_to :product + +# validates :rating, presence: true +# validates_inclusion_of :rating, :in => [1, 2, 3, 4, 5] \ No newline at end of file From 833504c059d3ed66e5c9ca3136cca8f424b588b0 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 22:43:58 -0700 Subject: [PATCH 023/260] missed updates on reviews, updated --- test/fixtures/reviews.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml index 057cb575ef..1e84698a2a 100644 --- a/test/fixtures/reviews.yml +++ b/test/fixtures/reviews.yml @@ -1,11 +1,11 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: +reivew_1: rating: 4 comment: impressive liked it a lot it was supppper good - product: products(:one) + product: product_1 -two: +review_2: rating: 2 comment: not so awesome sad face - product: products(:one) + product: product_1 From ef64de753cbb2161d69dffc1edb5186a5458179e Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 22:51:22 -0700 Subject: [PATCH 024/260] found spelling error on fixture review --- test/fixtures/reviews.yml | 4 ++-- test/models/review_test.rb | 21 +++++++++++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml index 1e84698a2a..9df21fd3f4 100644 --- a/test/fixtures/reviews.yml +++ b/test/fixtures/reviews.yml @@ -1,7 +1,7 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -reivew_1: - rating: 4 +review_1: + rating: 5 comment: impressive liked it a lot it was supppper good product: product_1 diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 7c1b87012f..9bb119b13f 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -1,15 +1,28 @@ require "test_helper" describe Review do - let(:review) { Review.new } + let(:review) { reviews(:review_1) } it "must be valid" do - value(review).must_be :valid? + expect(review.valid?).must_be true end -end + describe "validations" do + it "will not be valid if missing rating" do + # review.rating = nil + expect(review.valid?).must_equal false + + end + + it "will not be valid if rating is less than 1" do + end + + it "will not be valid if rating is greater than 5" do + end + end +end # belongs_to :product # validates :rating, presence: true -# validates_inclusion_of :rating, :in => [1, 2, 3, 4, 5] \ No newline at end of file +# validates_inclusion_of :rating, :in => [1, 2, 3, 4, 5] From 22774629f127de51f7764fd3c0367343ce377442 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 22:52:04 -0700 Subject: [PATCH 025/260] fixed spelling error on review fixture --- test/fixtures/reviews.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml index 1e84698a2a..ab36e0ed83 100644 --- a/test/fixtures/reviews.yml +++ b/test/fixtures/reviews.yml @@ -1,6 +1,6 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -reivew_1: +review_1: rating: 4 comment: impressive liked it a lot it was supppper good product: product_1 From e1f411f7cd0bbf24ca744c11247dc022c17f4871 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 23:00:34 -0700 Subject: [PATCH 026/260] added validations for review model tests --- test/models/review_test.rb | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 9bb119b13f..66af1106d8 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -4,20 +4,29 @@ let(:review) { reviews(:review_1) } it "must be valid" do - expect(review.valid?).must_be true + expect(review.valid?).must_equal true end describe "validations" do it "will not be valid if missing rating" do - # review.rating = nil + review.rating = nil expect(review.valid?).must_equal false - + expect(review.errors.include?(:rating)).must_equal true + expect(review.errors[:rating]).must_equal ["can't be blank", "is not included in the list"] end it "will not be valid if rating is less than 1" do + review.rating = -1 + expect(review.valid?).must_equal false + expect(review.errors.include?(:rating)).must_equal true + expect(review.errors[:rating]).must_equal ["is not included in the list"] end it "will not be valid if rating is greater than 5" do + review.rating = 6 + expect(review.valid?).must_equal false + expect(review.errors.include?(:rating)).must_equal true + expect(review.errors[:rating]).must_equal ["is not included in the list"] end end end From 3f74a911f07d7f5c92d6570d2ed73400bacefec3 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 23:05:48 -0700 Subject: [PATCH 027/260] finished testing review --- test/models/review_test.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 66af1106d8..2461b0ffc3 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -29,9 +29,10 @@ expect(review.errors[:rating]).must_equal ["is not included in the list"] end end -end - -# belongs_to :product -# validates :rating, presence: true -# validates_inclusion_of :rating, :in => [1, 2, 3, 4, 5] + describe "relationship with product" do + it "belongs to a product" do + expect(review.product).must_equal products(:product_1) + end + end +end From a0a0a5222c4acf5be5b4f6102bd3ee204b74d25b Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 23:47:48 -0700 Subject: [PATCH 028/260] finished category model validationis and relationship model testing --- test/models/category_test.rb | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/test/models/category_test.rb b/test/models/category_test.rb index 781320ad8e..48f57e2e24 100644 --- a/test/models/category_test.rb +++ b/test/models/category_test.rb @@ -1,9 +1,40 @@ require "test_helper" describe Category do - let(:category) { Category.new } + let(:category) { categories(:category_1) } it "must be valid" do - value(category).must_be :valid? + expect(category.valid?).must_equal true + end + + describe "validations" do + it "will not be valid if missing name" do + category.name = nil + expect(category.valid?).must_equal false + expect(category.errors.include?(:name)).must_equal true + expect(category.errors[:name]).must_equal ["can't be blank"] + end + + it "will not be valid if name not unique" do + category_dup = Category.new(name: category.name) + expect(category_dup.valid?).must_equal false + expect(category_dup.errors.include?(:name)).must_equal true + expect(category_dup.errors[:name]).must_equal ["has already been taken"] + end + end + + describe "relationships for products" do + it "can have 0 products" do + expect(category.products.count).must_equal 0 + end + + it "can have one or more products" do + category.products << products(:product_1) + category.products << products(:product_2) + expect(category.products.include?(products(:product_1))).must_equal true + expect(category.products.include?(products(:product_2))).must_equal true + expect(products(:product_1).categories.include?(category)).must_equal true + end end end + From 1ba92fc1bb9391096d23a33eae6ad4dcb60a3471 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 1 May 2019 23:57:35 -0700 Subject: [PATCH 029/260] removed s from order fixture names (ordres_1 updated to order_1) to conform to pattern of other fixtures --- test/fixtures/orders.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index 67b254081f..d0d0de3feb 100644 --- a/test/fixtures/orders.yml +++ b/test/fixtures/orders.yml @@ -1,6 +1,6 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -orders_1: +order_1: status: completed shopper_name: susie shopper_email: dalmation@susy.org @@ -8,7 +8,7 @@ orders_1: cc_four: 3434 cc_exp: 03022020 -orders_2: +order_2: status: completed shopper_name: miranda shopper_email: panda@hooo.com From b4fb626d9241441b7d0996ea058c47129768087e Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 2 May 2019 00:02:48 -0700 Subject: [PATCH 030/260] adjusted rating to 5 for review to avoid re-ocurring merge conflict with models_testing branch --- test/fixtures/reviews.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml index ab36e0ed83..9df21fd3f4 100644 --- a/test/fixtures/reviews.yml +++ b/test/fixtures/reviews.yml @@ -1,7 +1,7 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html review_1: - rating: 4 + rating: 5 comment: impressive liked it a lot it was supppper good product: product_1 From 85b519d8dc20dd01b2ed7deaf1cc7098ac125c9a Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 2 May 2019 00:16:11 -0700 Subject: [PATCH 031/260] merge branch --- test/fixtures/items.yml | 4 ++-- test/fixtures/reviews.yml | 8 -------- test/models/item_test.rb | 5 +++-- test/models/product_test.rb | 2 +- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/test/fixtures/items.yml b/test/fixtures/items.yml index 34d89caf4b..90c083239c 100644 --- a/test/fixtures/items.yml +++ b/test/fixtures/items.yml @@ -2,10 +2,10 @@ item_1: quantity: 5 - order: orders_1 + order: order_1 product: product_1 item_2: quantity: 3 - order: orders_1 + order: order_1 product: product_2 diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml index a9a4680f2e..9df21fd3f4 100644 --- a/test/fixtures/reviews.yml +++ b/test/fixtures/reviews.yml @@ -1,15 +1,7 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html review_1: -<<<<<<< HEAD -<<<<<<< HEAD rating: 5 -======= - rating: 4 ->>>>>>> fixtures -======= - rating: 5 ->>>>>>> fixtures comment: impressive liked it a lot it was supppper good product: product_1 diff --git a/test/models/item_test.rb b/test/models/item_test.rb index 9573bd9313..b1dbe42709 100644 --- a/test/models/item_test.rb +++ b/test/models/item_test.rb @@ -1,9 +1,10 @@ require "test_helper" describe Item do - let(:item) { Item.new } + let(:item) { items(:item_1) } it "must be valid" do - value(item).must_be :valid? + item.errors + expect(item.valid?).must_equal true end end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index a618b0a156..740350caf9 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -1,7 +1,7 @@ require "test_helper" describe Product do - let(:product) { Product.new } + let(:product) { products(:product_1) } it "must be valid" do value(product).must_be :valid? From 58b75e0125feab8b5e6601e06674b4eed768fb3a Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 2 May 2019 00:17:12 -0700 Subject: [PATCH 032/260] model testing all green so far, we'll finish other half tomorrow --- test/models/item_test.rb | 1 - test/models/order_test.rb | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/test/models/item_test.rb b/test/models/item_test.rb index b1dbe42709..30ebaaf6cd 100644 --- a/test/models/item_test.rb +++ b/test/models/item_test.rb @@ -4,7 +4,6 @@ let(:item) { items(:item_1) } it "must be valid" do - item.errors expect(item.valid?).must_equal true end end diff --git a/test/models/order_test.rb b/test/models/order_test.rb index df80f10fb6..3b3b2560da 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -1,7 +1,7 @@ require "test_helper" describe Order do - let(:order) { Order.new } + let(:order) { orders(:order_1) } it "must be valid" do value(order).must_be :valid? From fef7c5129fd357e9ebe75f66a12c2ec4958a3813 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 2 May 2019 00:18:37 -0700 Subject: [PATCH 033/260] updated orders reference in item --- test/fixtures/items.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fixtures/items.yml b/test/fixtures/items.yml index 34d89caf4b..90c083239c 100644 --- a/test/fixtures/items.yml +++ b/test/fixtures/items.yml @@ -2,10 +2,10 @@ item_1: quantity: 5 - order: orders_1 + order: order_1 product: product_1 item_2: quantity: 3 - order: orders_1 + order: order_1 product: product_2 From dbce826da57828325a7cb0a29c1d0fc51b6f7fca Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 2 May 2019 00:56:14 -0700 Subject: [PATCH 034/260] added reviews --- db/reviews_data.csv | 41 ++++++++++++++++++++++++++++++++++++ db/reviews_generate_seeds.rb | 19 +++++++++++++++++ db/seeds.rb | 10 +++++++++ review_data.csv | 41 ++++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+) create mode 100644 db/reviews_data.csv create mode 100644 db/reviews_generate_seeds.rb create mode 100644 review_data.csv diff --git a/db/reviews_data.csv b/db/reviews_data.csv new file mode 100644 index 0000000000..c8974a431a --- /dev/null +++ b/db/reviews_data.csv @@ -0,0 +1,41 @@ +rating,comment +4,"Bestfriend time brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +4,"Ada best seller pack brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +1,Cup of rainbows design does not hold up on rugged use and did not reduce fatique. +4,"Kitten cuddles brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +3,Teleport into bed design does not hold up on rugged use and did not reduce fatique. +2,Bondfire time design does not hold up on rugged use and did not reduce fatique. +5,"Sleep revival brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +2,Puppy play pack design does not hold up on rugged use and did not reduce fatique. +2,Sleep revival design does not hold up on rugged use and did not reduce fatique. +5,"Ada best seller pack brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +1,Kitten cuddles design does not hold up on rugged use and did not reduce fatique. +3,Bondfire time design does not hold up on rugged use and did not reduce fatique. +5,"Cup of rainbows brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +2,Pause time design does not hold up on rugged use and did not reduce fatique. +1,A good hair day design does not hold up on rugged use and did not reduce fatique. +3,Bucket of sunshine design does not hold up on rugged use and did not reduce fatique. +1,Pause time design does not hold up on rugged use and did not reduce fatique. +3,Puppy play pack design does not hold up on rugged use and did not reduce fatique. +4,"Bestfriend time brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +1,Juicy secret design does not hold up on rugged use and did not reduce fatique. +1,Juicy secret design does not hold up on rugged use and did not reduce fatique. +3,Giggle party design does not hold up on rugged use and did not reduce fatique. +1,Relaxation design does not hold up on rugged use and did not reduce fatique. +3,Ada best seller pack design does not hold up on rugged use and did not reduce fatique. +1,Bucket of sunshine design does not hold up on rugged use and did not reduce fatique. +2,Cup of sunshine design does not hold up on rugged use and did not reduce fatique. +1,Bondfire time design does not hold up on rugged use and did not reduce fatique. +3,Bondfire time design does not hold up on rugged use and did not reduce fatique. +2,Freshly showered design does not hold up on rugged use and did not reduce fatique. +1,Puppy play pack design does not hold up on rugged use and did not reduce fatique. +4,"High fives brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +3,Bestfriend time design does not hold up on rugged use and did not reduce fatique. +2,Ada starter kit design does not hold up on rugged use and did not reduce fatique. +4,"Teleport into bed brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +2,Relaxation design does not hold up on rugged use and did not reduce fatique. +3,Sleep revival design does not hold up on rugged use and did not reduce fatique. +4,"High fives brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +5,"Kitten cuddles brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +2,Giggle party design does not hold up on rugged use and did not reduce fatique. +3,Giggle party design does not hold up on rugged use and did not reduce fatique. diff --git a/db/reviews_generate_seeds.rb b/db/reviews_generate_seeds.rb new file mode 100644 index 0000000000..48658660ed --- /dev/null +++ b/db/reviews_generate_seeds.rb @@ -0,0 +1,19 @@ +require "faker" +require "csv" + +CSV.open("db/reviews_data.csv", "w", :write_headers => true, + :headers => ["rating", "comment"]) do |csv| + intangibles = [ + "high fives", "cup of sunshine", "bucket of sunshine", "sleep revival", "relaxation", "energy", "a good hair day", "pause time", "freshly showered", "teleport into bed", "ada starter kit", "ada best seller pack", "cup of rainbows", "puppy play pack", "kitten cuddles", "giggle party", "bestfriend time", "juicy secret", "inside joke moment", "bondfire time", + ] + 40.times do |i| + index = rand(0...20) + rating = rand(1..5) + if rating > 3 + comment = "#{intangibles[index].capitalize} brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." + else + comment = "#{intangibles[index].capitalize} design does not hold up on rugged use and did not reduce fatique. " + end + csv << [rating, comment] + end +end diff --git a/db/seeds.rb b/db/seeds.rb index 57c2ee2366..90702ced1d 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -26,3 +26,13 @@ stock: line["stock"]) product.valid? ? (puts "#{i + 1} product") : failed_to_save << product end + +CSV.open("db/reviews_data.csv", headers: true).each_with_index do |line, i| + product = Product.find(rand(1..Product.count)) + review = Review.new(rating: line["rating"], + comment: line["comment"]) + product.reviews << review + review.valid? ? (puts "#{i + 1} review") : failed_to_save << review +end + +puts "#{failed_to_save.count} failed to save" diff --git a/review_data.csv b/review_data.csv new file mode 100644 index 0000000000..9d170832fc --- /dev/null +++ b/review_data.csv @@ -0,0 +1,41 @@ +review,rating +2,Freshly showered design does not hold up on rugged use and did not reduce fatique. +3,Giggle party design does not hold up on rugged use and did not reduce fatique. +4,"Juicy secret brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +4,"Bondfire time brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +4,"Ada starter kit brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +1,A good hair day design does not hold up on rugged use and did not reduce fatique. +3,Puppy play pack design does not hold up on rugged use and did not reduce fatique. +5,"Bestfriend time brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +5,"Inside joke moment brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +1,Cup of sunshine design does not hold up on rugged use and did not reduce fatique. +5,"Pause time brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +2,A good hair day design does not hold up on rugged use and did not reduce fatique. +3,Inside joke moment design does not hold up on rugged use and did not reduce fatique. +2,Juicy secret design does not hold up on rugged use and did not reduce fatique. +2,Ada starter kit design does not hold up on rugged use and did not reduce fatique. +3,A good hair day design does not hold up on rugged use and did not reduce fatique. +3,Kitten cuddles design does not hold up on rugged use and did not reduce fatique. +4,"Ada starter kit brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +5,"Cup of rainbows brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +1,Relaxation design does not hold up on rugged use and did not reduce fatique. +2,Giggle party design does not hold up on rugged use and did not reduce fatique. +4,"Bucket of sunshine brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +5,"Ada starter kit brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +3,Freshly showered design does not hold up on rugged use and did not reduce fatique. +4,"Freshly showered brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +2,Cup of rainbows design does not hold up on rugged use and did not reduce fatique. +4,"Bestfriend time brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +5,"Relaxation brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +1,Ada best seller pack design does not hold up on rugged use and did not reduce fatique. +3,Ada best seller pack design does not hold up on rugged use and did not reduce fatique. +1,Puppy play pack design does not hold up on rugged use and did not reduce fatique. +2,Giggle party design does not hold up on rugged use and did not reduce fatique. +2,Teleport into bed design does not hold up on rugged use and did not reduce fatique. +1,Cup of sunshine design does not hold up on rugged use and did not reduce fatique. +5,"Bondfire time brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +2,Ada starter kit design does not hold up on rugged use and did not reduce fatique. +2,Juicy secret design does not hold up on rugged use and did not reduce fatique. +4,"Bestfriend time brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +5,"Giggle party brightened my day. It was also promises to make shooting daytime and nighttime action simpler and professional-looking, providing the budding photographer with new and enticing reasons to hone their skills." +1,Cup of rainbows design does not hold up on rugged use and did not reduce fatique. From 4d5ed3960b6e1b5d5b74742506ecf1014c1d90db Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 2 May 2019 09:48:58 -0700 Subject: [PATCH 035/260] setting up simpleCov --- .gitignore | 1 + Gemfile | 2 +- Gemfile.lock | 8 ++++++++ test/test_helper.rb | 6 ++++-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 18b43c9cd2..851f76762f 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ # Ignore master key for decrypting credentials and more. /config/master.key +coverage diff --git a/Gemfile b/Gemfile index 04cfa9b68c..4c41019917 100644 --- a/Gemfile +++ b/Gemfile @@ -80,6 +80,6 @@ group :test do gem 'minitest-reporters' end - +gem 'simplecov', require: false, group: :test gem 'csv' \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index 2e754159d4..4e8ccba8f8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -83,6 +83,7 @@ GEM crass (1.0.4) csv (3.1.1) debug_inspector (0.0.3) + docile (1.3.1) erubi (1.8.0) execjs (2.7.0) ffi (1.10.0) @@ -115,6 +116,7 @@ GEM jquery-turbolinks (2.1.0) railties (>= 3.1.0) turbolinks + json (2.1.0) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -208,6 +210,11 @@ GEM childprocess (>= 0.5, < 2.0) rubyzip (~> 1.2, >= 1.2.2) shellany (0.0.1) + simplecov (0.16.1) + docile (~> 1.1) + 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) @@ -267,6 +274,7 @@ DEPENDENCIES rails (~> 5.2.3) sass-rails (~> 5.0) selenium-webdriver + simplecov spring spring-watcher-listen (~> 2.0.0) turbolinks (~> 5) diff --git a/test/test_helper.rb b/test/test_helper.rb index 2b5172a7d6..6faf3ca4e2 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,7 +1,10 @@ +require "simplecov" +SimpleCov.start "rails" ENV["RAILS_ENV"] = "test" require File.expand_path("../../config/environment", __FILE__) require "rails/test_help" -require "minitest/rails"require "minitest/reporters" # for Colorized output +require "minitest/rails" +require "minitest/reporters" # for Colorized output # For colorful output! Minitest::Reporters.use!( Minitest::Reporters::SpecReporter.new, @@ -9,7 +12,6 @@ Minitest.backtrace_filter ) - # To add Capybara feature tests add `gem "minitest-rails-capybara"` # to the test group in the Gemfile and uncomment the following: # require "minitest/rails/capybara" From f66659b29f75a36276a98407409d42cb17153c3a Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 2 May 2019 10:40:42 -0700 Subject: [PATCH 036/260] adde .env --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 851f76762f..30a6810d56 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ # Ignore master key for decrypting credentials and more. /config/master.key coverage +.env From 2daa0a4124b1f39834f82a310eacb3641ecd901d Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 2 May 2019 13:38:12 -0700 Subject: [PATCH 037/260] merge --- Gemfile.lock | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0a4b01bde2..48f56a3dfc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -83,14 +83,11 @@ GEM crass (1.0.4) csv (3.1.1) debug_inspector (0.0.3) -<<<<<<< HEAD docile (1.3.1) -======= dotenv (2.7.2) dotenv-rails (2.7.2) dotenv (= 2.7.2) railties (>= 3.2, < 6.1) ->>>>>>> e64e8c98c180215bf73588c062d844a448190082 erubi (1.8.0) execjs (2.7.0) faraday (0.15.4) @@ -126,11 +123,8 @@ GEM jquery-turbolinks (2.1.0) railties (>= 3.1.0) turbolinks -<<<<<<< HEAD json (2.1.0) -======= jwt (2.1.0) ->>>>>>> e64e8c98c180215bf73588c062d844a448190082 listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -320,4 +314,4 @@ RUBY VERSION ruby 2.5.1p57 BUNDLED WITH - 1.17.3 + 1.16.6 From c6ba4efb4629ca59366e0b7ba2e86c542e579c16 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Thu, 2 May 2019 14:13:00 -0700 Subject: [PATCH 038/260] Added .env to gitignore file. Ready for review. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 18b43c9cd2..529c3fe70c 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ # Ignore master key for decrypting credentials and more. /config/master.key +.env \ No newline at end of file From 85240b3aade707b2d5700c4b3c6136e9ebcf61e9 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Thu, 2 May 2019 14:13:28 -0700 Subject: [PATCH 039/260] squashed bug in application.js file --- app/assets/javascripts/application.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index b0ef35b723..06eea96ab2 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -8,7 +8,8 @@ // 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 jquery3 +// about supported directives. +//= require jquery3 //= require popper //= require bootstrap-sprockets From 180f35ac0e6560bd6e398c3a6adc812af640d80b Mon Sep 17 00:00:00 2001 From: Sav <41908878+qqdipps@users.noreply.github.com> Date: Thu, 2 May 2019 14:21:54 -0700 Subject: [PATCH 040/260] Update and rename .env to deleteme.rb --- .env | 2 -- deleteme.rb | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 .env create mode 100644 deleteme.rb diff --git a/.env b/.env deleted file mode 100644 index 55771652bc..0000000000 --- a/.env +++ /dev/null @@ -1,2 +0,0 @@ -GITHUB_CLIENT_ID: 3c49067b5430afe2f192 -GITHUB_CLIENT_SECRET: 739c1767ae23ed4d4ef085e7509483d5702dac73 \ No newline at end of file diff --git a/deleteme.rb b/deleteme.rb new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/deleteme.rb @@ -0,0 +1 @@ + From 254eb8a0443ff0e61a86930c20afbd1995b9ac03 Mon Sep 17 00:00:00 2001 From: Sav <41908878+qqdipps@users.noreply.github.com> Date: Thu, 2 May 2019 14:22:36 -0700 Subject: [PATCH 041/260] Delete deleteme.rb --- deleteme.rb | 1 - 1 file changed, 1 deletion(-) delete mode 100644 deleteme.rb diff --git a/deleteme.rb b/deleteme.rb deleted file mode 100644 index 8b13789179..0000000000 --- a/deleteme.rb +++ /dev/null @@ -1 +0,0 @@ - From f0df641c5b8d509eac2affbdc92bc1bc5d24a58b Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Thu, 2 May 2019 14:45:38 -0700 Subject: [PATCH 042/260] Generating submaster branch. --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index c29f52d502..0af266ba38 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,7 +8,7 @@ get "/auth/github", as: "github_login" get "/auth/:provider/callback", to: "users#create" - delete "/logout", to: "users#destroy", as: “logout” + delete "/logout", to: "users#destroy", as: "logout" # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end From c37cca458e88bb2c5f620f21f1f60377acc3ac8b Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Thu, 2 May 2019 15:29:36 -0700 Subject: [PATCH 043/260] basic show page and index for products --- app/controllers/products_controller.rb | 6 ++ app/views/products/index.html.erb | 11 +++- app/views/products/show.html.erb | 59 +++++++++++++++++- config/routes.rb | 2 +- test/controllers/products_controller_test.rb | 63 +++++++++++++------- 5 files changed, 114 insertions(+), 27 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 616cc46ce5..8c39c8adc8 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -6,9 +6,15 @@ def create end def index + @products = Product.all end def show + @product = Product.find_by(id: params[:id]) + + if @product.nil? + redirect_to products_path + end end def edit diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index f8eeb82674..fbe5ce960a 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,2 +1,9 @@ -

Products#index

-

Find me in app/views/products/index.html.erb

+

Product index, this is just a placeholder page, feel free to make any changes

+ +
    +<% @products.each do |product| %> +
  • + <%= link_to product.name, product_path(product.id) %> +
  • +<% end %> +
\ No newline at end of file diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 5f44ec44d2..ae8e38d4ef 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,2 +1,57 @@ -

Products#show

-

Find me in app/views/products/show.html.erb

+

Product show page

+ +

+ Name: <%= @product.name %> +

+ +

+ Price: $ <%= @product.price / 100.0 %> +

+ +

+ Description: <%= @product.description%> +

+ +

+ Stock: <%= @product.stock%> +

+ +
+

+ Categories +

+ + <% if @product.categories.any? %> +
    + + <% @product.categories.each do |category| %> +
  • <%= category.name %>
  • + <% end %> + +
+ <% else %> +

There are no categories assigned to this product

+ <% end %> +
+ +
+

+ Reviews +

+ +<% reviews = Review.where(product_id: @product.id)%> + <% if reviews.any? %> +
    + + <% reviews.each do |review| %> +
  • Rating: <%= review.rating%>
  • +
  • Comment: <%= review.comment%>
  • +
  • Product: <%= review.product_id%>
  • + <% end %> + +
+ <% else %> +

There are no categories assigned to this product

+ <% end %> +
+ diff --git a/config/routes.rb b/config/routes.rb index c29f52d502..0af266ba38 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,7 +8,7 @@ get "/auth/github", as: "github_login" get "/auth/:provider/callback", to: "users#create" - delete "/logout", to: "users#destroy", as: “logout” + delete "/logout", to: "users#destroy", as: "logout" # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index e8b99e3c29..73c8f54a51 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -1,34 +1,53 @@ require "test_helper" describe ProductsController do - it "should get new" do - get products_new_url - value(response).must_be :success? - end + # it "should get new" do + # get products_new_url + # value(response).must_be :success? + # end - it "should get create" do - get products_create_url - value(response).must_be :success? - end + # it "should get create" do + # get products_create_url + # value(response).must_be :success? + # end - it "should get index" do - get products_index_url - value(response).must_be :success? - end + describe "index" do + it "should get index" do + # Act + get products_path - it "should get show" do - get products_show_url - value(response).must_be :success? + # Assert + must_respond_with :success + end end - it "should get edit" do - get products_edit_url - value(response).must_be :success? - end + describe "show" do + it "can get a valid product" do + + # Act + get product_path(products(:product_1).id) - it "should get update" do - get products_update_url - value(response).must_be :success? + # Assert + must_respond_with :success + end + + it "will redirect for an invalid product" do + + # Act + get product_path(-1) + + # Assert + must_respond_with :redirect + end end + # it "should get edit" do + # get products_edit_url + # value(response).must_be :success? + # end + + # it "should get update" do + # get products_update_url + # value(response).must_be :success? + # end end From 0fabe86978075c1abd65ba4d9762c9e69d6df202 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 2 May 2019 15:35:01 -0700 Subject: [PATCH 044/260] generating categories --- coverage/.last_run.json | 5 + coverage/.resultset.json | 184 ++ coverage/.resultset.json.lock | 0 coverage/assets/0.10.2/application.css | 799 ++++++++ coverage/assets/0.10.2/application.js | 1707 +++++++++++++++++ coverage/assets/0.10.2/colorbox/border.png | Bin 0 -> 163 bytes coverage/assets/0.10.2/colorbox/controls.png | Bin 0 -> 2033 bytes coverage/assets/0.10.2/colorbox/loading.gif | Bin 0 -> 9427 bytes .../0.10.2/colorbox/loading_background.png | Bin 0 -> 166 bytes coverage/assets/0.10.2/favicon_green.png | Bin 0 -> 1009 bytes coverage/assets/0.10.2/favicon_red.png | Bin 0 -> 1009 bytes coverage/assets/0.10.2/favicon_yellow.png | Bin 0 -> 1009 bytes coverage/assets/0.10.2/loading.gif | Bin 0 -> 7247 bytes coverage/assets/0.10.2/magnify.png | Bin 0 -> 1301 bytes .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes coverage/index.html | 1198 ++++++++++++ db/categories_data.csv | 6 + db/categories_generate_seeds.rb | 11 + 30 files changed, 3910 insertions(+) create mode 100644 coverage/.last_run.json create mode 100644 coverage/.resultset.json create mode 100644 coverage/.resultset.json.lock create mode 100644 coverage/assets/0.10.2/application.css create mode 100644 coverage/assets/0.10.2/application.js create mode 100644 coverage/assets/0.10.2/colorbox/border.png create mode 100644 coverage/assets/0.10.2/colorbox/controls.png create mode 100644 coverage/assets/0.10.2/colorbox/loading.gif create mode 100644 coverage/assets/0.10.2/colorbox/loading_background.png create mode 100644 coverage/assets/0.10.2/favicon_green.png create mode 100644 coverage/assets/0.10.2/favicon_red.png create mode 100644 coverage/assets/0.10.2/favicon_yellow.png create mode 100644 coverage/assets/0.10.2/loading.gif create mode 100644 coverage/assets/0.10.2/magnify.png create mode 100644 coverage/assets/0.10.2/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 coverage/assets/0.10.2/smoothness/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 coverage/assets/0.10.2/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 coverage/assets/0.10.2/smoothness/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 coverage/assets/0.10.2/smoothness/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 coverage/assets/0.10.2/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 coverage/assets/0.10.2/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 coverage/assets/0.10.2/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 coverage/assets/0.10.2/smoothness/images/ui-icons_222222_256x240.png create mode 100644 coverage/assets/0.10.2/smoothness/images/ui-icons_2e83ff_256x240.png create mode 100644 coverage/assets/0.10.2/smoothness/images/ui-icons_454545_256x240.png create mode 100644 coverage/assets/0.10.2/smoothness/images/ui-icons_888888_256x240.png create mode 100644 coverage/assets/0.10.2/smoothness/images/ui-icons_cd0a0a_256x240.png create mode 100644 coverage/index.html create mode 100644 db/categories_data.csv create mode 100644 db/categories_generate_seeds.rb diff --git a/coverage/.last_run.json b/coverage/.last_run.json new file mode 100644 index 0000000000..d762fbb555 --- /dev/null +++ b/coverage/.last_run.json @@ -0,0 +1,5 @@ +{ + "result": { + "covered_percent": 65.96 + } +} diff --git a/coverage/.resultset.json b/coverage/.resultset.json new file mode 100644 index 0000000000..ba3009678d --- /dev/null +++ b/coverage/.resultset.json @@ -0,0 +1,184 @@ +{ + "MiniTest": { + "coverage": { + "/Users/qqdipps/ada/projects/betsy/app/helpers/application_helper.rb": [ + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/category.rb": [ + 1, + 1, + null, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/application_record.rb": [ + 1, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/item.rb": [ + 1, + 1, + 1, + null, + 1, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/merchant.rb": [ + 1, + 1, + null, + 1, + 1, + 1, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/order.rb": [ + 1, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/product.rb": [ + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/review.rb": [ + 1, + 1, + null, + 1, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/mailers/application_mailer.rb": [ + 0, + 0, + 0, + 0 + ], + "/Users/qqdipps/ada/projects/betsy/app/jobs/application_job.rb": [ + 0, + 0 + ], + "/Users/qqdipps/ada/projects/betsy/app/controllers/application_controller.rb": [ + 0, + 0 + ], + "/Users/qqdipps/ada/projects/betsy/app/channels/application_cable/connection.rb": [ + 0, + 0, + 0, + 0 + ], + "/Users/qqdipps/ada/projects/betsy/app/channels/application_cable/channel.rb": [ + 0, + 0, + 0, + 0 + ] + }, + "timestamp": 1556815526 + }, + "Unit Tests": { + "coverage": { + "/Users/qqdipps/ada/projects/betsy/app/helpers/application_helper.rb": [ + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/product.rb": [ + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/application_record.rb": [ + 1, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/review.rb": [ + 1, + 1, + null, + 1, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/category.rb": [ + 1, + 1, + null, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/order.rb": [ + 1, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/merchant.rb": [ + 1, + 1, + null, + 1, + 1, + 1, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/models/item.rb": [ + 1, + 1, + 1, + null, + 1, + 1, + null + ], + "/Users/qqdipps/ada/projects/betsy/app/mailers/application_mailer.rb": [ + 0, + 0, + 0, + 0 + ], + "/Users/qqdipps/ada/projects/betsy/app/jobs/application_job.rb": [ + 0, + 0 + ], + "/Users/qqdipps/ada/projects/betsy/app/controllers/application_controller.rb": [ + 0, + 0 + ], + "/Users/qqdipps/ada/projects/betsy/app/channels/application_cable/connection.rb": [ + 0, + 0, + 0, + 0 + ], + "/Users/qqdipps/ada/projects/betsy/app/channels/application_cable/channel.rb": [ + 0, + 0, + 0, + 0 + ] + }, + "timestamp": 1556833448 + } +} diff --git a/coverage/.resultset.json.lock b/coverage/.resultset.json.lock new file mode 100644 index 0000000000..e69de29bb2 diff --git a/coverage/assets/0.10.2/application.css b/coverage/assets/0.10.2/application.css new file mode 100644 index 0000000000..d86560434d --- /dev/null +++ b/coverage/assets/0.10.2/application.css @@ -0,0 +1,799 @@ +/* ----------------------------------------------------------------------- + + + Blueprint CSS Framework 0.9 + http://blueprintcss.org + + * Copyright (c) 2007-Present. See LICENSE for more info. + * See README for instructions on how to use Blueprint. + * For credits and origins, see AUTHORS. + * This is a compressed file. See the sources in the 'src' directory. + +----------------------------------------------------------------------- */ + +/* reset.css */ + +html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, dialog, figure, footer, header, hgroup, nav, section {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;} +article, aside, dialog, figure, footer, header, hgroup, nav, section {display:block;} +body {line-height:1.5;} +table {border-collapse:separate;border-spacing:0;} +caption, th, td {text-align:left;font-weight:normal;} +table, td, th {vertical-align:middle;} +blockquote:before, blockquote:after, q:before, q:after {content:"";} +blockquote, q {quotes:"" "";} +a img {border:none;} + +/* typography.css */ +html {font-size:100.01%;} +body {font-size:82%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;} +h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;} +h1 {font-size:3em;line-height:1;margin-bottom:0.5em;} +h2 {font-size:2em;margin-bottom:0.75em;} +h3 {font-size:1.5em;line-height:1;margin-bottom:1em;} +h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;} +h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;} +h6 {font-size:1em;font-weight:bold;} +h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;} +p {margin:0 0 1.5em;} +p img.left {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;} +p img.right {float:right;margin:1.5em 0 1.5em 1.5em;} +a:focus, a:hover {color:#000;} +a {color:#009;text-decoration:underline;} +blockquote {margin:1.5em;color:#666;font-style:italic;} +strong {font-weight:bold;} +em, dfn {font-style:italic;} +dfn {font-weight:bold;} +sup, sub {line-height:0;} +abbr, acronym {border-bottom:1px dotted #666;} +address {margin:0 0 1.5em;font-style:italic;} +del {color:#666;} +pre {margin:1.5em 0;white-space:pre;} +pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;} +li ul, li ol {margin:0;} +ul, ol {margin:0 1.5em 1.5em 0;padding-left:3.333em;} +ul {list-style-type:disc;} +ol {list-style-type:decimal;} +dl {margin:0 0 1.5em 0;} +dl dt {font-weight:bold;} +dd {margin-left:1.5em;} +table {margin-bottom:1.4em;width:100%;} +th {font-weight:bold;} +thead th {background:#c3d9ff;} +th, td, caption {padding:4px 10px 4px 5px;} +tr.even td {background:#efefef;} +tfoot {font-style:italic;} +caption {background:#eee;} +.small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;} +.large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;} +.hide {display:none;} +.quiet {color:#666;} +.loud {color:#000;} +.highlight {background:#ff0;} +.added {background:#060;color:#fff;} +.removed {background:#900;color:#fff;} +.first {margin-left:0;padding-left:0;} +.last {margin-right:0;padding-right:0;} +.top {margin-top:0;padding-top:0;} +.bottom {margin-bottom:0;padding-bottom:0;} + +/* forms.css */ +label {font-weight:bold;} +fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;} +legend {font-weight:bold;font-size:1.2em;} +input[type=text], input[type=password], input.text, input.title, textarea, select {background-color:#fff;border:1px solid #bbb;} +input[type=text]:focus, input[type=password]:focus, input.text:focus, input.title:focus, textarea:focus, select:focus {border-color:#666;} +input[type=text], input[type=password], input.text, input.title, textarea, select {margin:0.5em 0;} +input.text, input.title {width:300px;padding:5px;} +input.title {font-size:1.5em;} +textarea {width:390px;height:250px;padding:5px;} +input[type=checkbox], input[type=radio], input.checkbox, input.radio {position:relative;top:.25em;} +form.inline {line-height:3;} +form.inline p {margin-bottom:0;} +.error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;} +.error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;} +.notice {background:#FFF6BF;color:#514721;border-color:#FFD324;} +.success {background:#E6EFC2;color:#264409;border-color:#C6D880;} +.error a {color:#8a1f11;} +.notice a {color:#514721;} +.success a {color:#264409;} +.box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;} +hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;} +hr.space {background:#fff;color:#fff;visibility:hidden;} +.clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;} +.clearfix, .container {display:block;} +.clear {clear:both;} +/* +github.com style (c) Vasily Polovnyov +*/ + + +pre code { +} + +pre .comment, +pre .template_comment, +pre .diff .header, +pre .javadoc { + color: #998; + font-style: italic +} + +pre .keyword, +pre .css .rule .keyword, +pre .winutils, +pre .javascript .title, +pre .lisp .title { + color: #000; + font-weight: bold +} + +pre .number, +pre .hexcolor { + color: #458 +} + + +pre .string, +pre .tag .value, +pre .phpdoc, +pre .tex .formula { + color: #d14 +} + +pre .subst { + color: #712; +} + +pre .constant, +pre .title, +pre .id { + color: #900; + font-weight: bold +} + +pre .javascript .title, +pre .lisp .title, +pre .subst { + font-weight: normal +} + +pre .class .title, +pre .haskell .label, +pre .tex .command { + color: #458; + font-weight: bold +} + +pre .tag, +pre .tag .title, +pre .rules .property, +pre .django .tag .keyword { + color: #000080; + font-weight: normal +} + +pre .attribute, +pre .variable, +pre .instancevar, +pre .lisp .body { + color: #008080 +} + +pre .regexp { + color: #009926 +} + +pre .class { + color: #458; + font-weight: bold +} + +pre .symbol, +pre .ruby .symbol .string, +pre .ruby .symbol .keyword, +pre .ruby .symbol .keymethods, +pre .lisp .keyword, +pre .tex .special, +pre .input_number { + color: #990073 +} + +pre .builtin, +pre .built_in, +pre .lisp .title { + color: #0086b3 +} + +pre .preprocessor, +pre .pi, +pre .doctype, +pre .shebang, +pre .cdata { + color: #999; + font-weight: bold +} + +pre .deletion { + background: #fdd +} + +pre .addition { + background: #dfd +} + +pre .diff .change { + background: #0086b3 +} + +pre .chunk { + color: #aaa +} + +pre .tex .formula { + opacity: 0.5; +} +/* + * jQuery UI CSS Framework @VERSION + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ + +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + +/* + * jQuery UI CSS Framework @VERSION + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } +.ui-widget-content a { color: #222222; } +.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } +.ui-widget-header a { color: #222222; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; } +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; } +/* + ColorBox Core Style: + The following CSS is consistent between example themes and should not be altered. +*/ +#colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden;} +#cboxOverlay{position:fixed; width:100%; height:100%;} +#cboxMiddleLeft, #cboxBottomLeft{clear:left;} +#cboxContent{position:relative;} +#cboxLoadedContent{overflow:auto;} +#cboxTitle{margin:0;} +#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;} +#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;} +.cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none;} +.cboxIframe{width:100%; height:100%; display:block; border:0;} +#colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box;} + +/* + User Style: + Change the following styles to modify the appearance of ColorBox. They are + ordered & tabbed in a way that represents the nesting of the generated HTML. +*/ +#cboxOverlay{background:#000;} +#colorbox{} + #cboxTopLeft{width:14px; height:14px; background:url(colorbox/controls.png) no-repeat 0 0;} + #cboxTopCenter{height:14px; background:url(colorbox/border.png) repeat-x top left;} + #cboxTopRight{width:14px; height:14px; background:url(colorbox/controls.png) no-repeat -36px 0;} + #cboxBottomLeft{width:14px; height:43px; background:url(colorbox/controls.png) no-repeat 0 -32px;} + #cboxBottomCenter{height:43px; background:url(colorbox/border.png) repeat-x bottom left;} + #cboxBottomRight{width:14px; height:43px; background:url(colorbox/controls.png) no-repeat -36px -32px;} + #cboxMiddleLeft{width:14px; background:url(colorbox/controls.png) repeat-y -175px 0;} + #cboxMiddleRight{width:14px; background:url(colorbox/controls.png) repeat-y -211px 0;} + #cboxContent{background:#fff; overflow:visible;} + .cboxIframe{background:#fff;} + #cboxError{padding:50px; border:1px solid #ccc;} + #cboxLoadedContent{margin-bottom:5px;} + #cboxLoadingOverlay{background:url(colorbox/loading_background.png) no-repeat center center;} + #cboxLoadingGraphic{background:url(colorbox/loading.gif) no-repeat center center;} + #cboxTitle{position:absolute; bottom:-25px; left:0; text-align:center; width:100%; font-weight:bold; color:#7C7C7C;} + #cboxCurrent{position:absolute; bottom:-25px; left:58px; font-weight:bold; color:#7C7C7C;} + + #cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{position:absolute; bottom:-29px; background:url(colorbox/controls.png) no-repeat 0px 0px; width:23px; height:23px; text-indent:-9999px;} + #cboxPrevious{left:0px; background-position: -51px -25px;} + #cboxPrevious:hover{background-position:-51px 0px;} + #cboxNext{left:27px; background-position:-75px -25px;} + #cboxNext:hover{background-position:-75px 0px;} + #cboxClose{right:0; background-position:-100px -25px;} + #cboxClose:hover{background-position:-100px 0px;} + + .cboxSlideshow_on #cboxSlideshow{background-position:-125px 0px; right:27px;} + .cboxSlideshow_on #cboxSlideshow:hover{background-position:-150px 0px;} + .cboxSlideshow_off #cboxSlideshow{background-position:-150px -25px; right:27px;} + .cboxSlideshow_off #cboxSlideshow:hover{background-position:-125px 0px;} +#loading { + position: fixed; + left: 40%; + top: 50%; } + +a { + color: #333333; + text-decoration: none; } + a:hover { + color: black; + text-decoration: underline; } + +body { + font-family: "Lucida Grande", Helvetica, "Helvetica Neue", Arial, sans-serif; + padding: 12px; + background-color: #333333; } + +h1, h2, h3, h4 { + color: #1c2324; + margin: 0; + padding: 0; + margin-bottom: 12px; } + +table { + width: 100%; } + +#content { + clear: left; + background-color: white; + border: 2px solid #dddddd; + border-top: 8px solid #dddddd; + padding: 18px; + -webkit-border-bottom-left-radius: 5px; + -webkit-border-bottom-right-radius: 5px; + -webkit-border-top-right-radius: 5px; + -moz-border-radius-bottomleft: 5px; + -moz-border-radius-bottomright: 5px; + -moz-border-radius-topright: 5px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + border-top-right-radius: 5px; } + +.dataTables_filter, .dataTables_info { + padding: 2px 6px; } + +abbr.timeago { + text-decoration: none; + border: none; + font-weight: bold; } + +.timestamp { + float: right; + color: #dddddd; } + +.group_tabs { + list-style: none; + float: left; + margin: 0; + padding: 0; } + .group_tabs li { + display: inline; + float: left; } + .group_tabs li a { + font-family: Helvetica, Arial, sans-serif; + display: block; + float: left; + text-decoration: none; + padding: 4px 8px; + background-color: #aaaaaa; + background: -webkit-gradient(linear, 0 0, 0 bottom, from(#dddddd), to(#aaaaaa)); + background: -moz-linear-gradient(#dddddd, #aaaaaa); + background: linear-gradient(#dddddd, #aaaaaa); + text-shadow: #e5e5e5 1px 1px 0px; + border-bottom: none; + color: #333333; + font-weight: bold; + margin-right: 8px; + border-top: 1px solid #efefef; + -webkit-border-top-left-radius: 2px; + -webkit-border-top-right-radius: 2px; + -moz-border-radius-topleft: 2px; + -moz-border-radius-topright: 2px; + border-top-left-radius: 2px; + border-top-right-radius: 2px; } + .group_tabs li a:hover { + background-color: #cccccc; + background: -webkit-gradient(linear, 0 0, 0 bottom, from(#eeeeee), to(#aaaaaa)); + background: -moz-linear-gradient(#eeeeee, #aaaaaa); + background: linear-gradient(#eeeeee, #aaaaaa); } + .group_tabs li a:active { + padding-top: 5px; + padding-bottom: 3px; } + .group_tabs li.active a { + color: black; + text-shadow: white 1px 1px 0px; + background-color: #dddddd; + background: -webkit-gradient(linear, 0 0, 0 bottom, from(white), to(#dddddd)); + background: -moz-linear-gradient(white, #dddddd); + background: linear-gradient(white, #dddddd); } + +.file_list { + margin-bottom: 18px; } + +a.src_link { + background: url("./magnify.png") no-repeat left 50%; + padding-left: 18px; } + +tr, td { + margin: 0; + padding: 0; } + +th { + white-space: nowrap; } + th.ui-state-default { + cursor: pointer; } + th span.ui-icon { + float: left; } + +td { + padding: 4px 8px; } + td.strong { + font-weight: bold; } + +.source_table h3, .source_table h4 { + padding: 0; + margin: 0; + margin-bottom: 4px; } +.source_table .header { + padding: 10px; } +.source_table pre { + margin: 0; + padding: 0; + white-space: normal; + color: black; + font-family: "Monaco", "Inconsolata", "Consolas", monospace; } +.source_table code { + color: black; + font-family: "Monaco", "Inconsolata", "Consolas", monospace; } +.source_table pre { + background-color: #333333; } + .source_table pre ol { + margin: 0px; + padding: 0px; + margin-left: 45px; + font-size: 12px; + color: white; } + .source_table pre li { + margin: 0px; + padding: 2px 6px; + border-left: 5px solid white; } + .source_table pre li code { + white-space: pre; + white-space: pre-wrap; } + .source_table pre .hits { + float: right; + margin-left: 10px; + padding: 2px 4px; + background-color: #444444; + background: -webkit-gradient(linear, 0 0, 0 bottom, from(#222222), to(#666666)); + background: -moz-linear-gradient(#222222, #666666); + background: linear-gradient(#222222, #666666); + color: white; + font-family: Helvetica, "Helvetica Neue", Arial, sans-serif; + font-size: 10px; + font-weight: bold; + text-align: center; + border-radius: 6px; } + +#footer { + color: #dddddd; + font-size: 12px; + font-weight: bold; + margin-top: 12px; + text-align: right; } + #footer a { + color: #eeeeee; + text-decoration: underline; } + #footer a:hover { + color: white; + text-decoration: none; } + +.green { + color: #009900; } + +.red { + color: #990000; } + +.yellow { + color: #ddaa00; } + +.source_table .covered { + border-color: #009900; } +.source_table .missed { + border-color: #990000; } +.source_table .never { + border-color: black; } +.source_table .skipped { + border-color: #ffcc00; } +.source_table .covered:nth-child(odd) { + background-color: #cdf2cd; } +.source_table .covered:nth-child(even) { + background-color: #dbf2db; } +.source_table .missed:nth-child(odd) { + background-color: #f7c0c0; } +.source_table .missed:nth-child(even) { + background-color: #f7cfcf; } +.source_table .never:nth-child(odd) { + background-color: #efefef; } +.source_table .never:nth-child(even) { + background-color: #f4f4f4; } +.source_table .skipped:nth-child(odd) { + background-color: #fbf0c0; } +.source_table .skipped:nth-child(even) { + background-color: #fbffcf; } + + + diff --git a/coverage/assets/0.10.2/application.js b/coverage/assets/0.10.2/application.js new file mode 100644 index 0000000000..fe65d88219 --- /dev/null +++ b/coverage/assets/0.10.2/application.js @@ -0,0 +1,1707 @@ +/*! + * jQuery JavaScript Library v1.6.2 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Jun 30 14:16:56 2011 -0400 + */ + +(function(a,b){function cv(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cs(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"":"")+""),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cr(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cq(){cn=b}function cp(){setTimeout(cq,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bx(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bm(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(be,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bl(a){f.nodeName(a,"input")?bk(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bk)}function bk(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bj(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bi(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bh(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z])/ig,x=function(a,b){return b.toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!A){A=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||D.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
a",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0},m&&f.extend(p,{position:"absolute",left:-1e3,top:-1e3});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
t
",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]||i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=w:v&&c!=="className"&&(f.nodeName(a,"form")||u.test(c))&&(i=v)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}},value:{get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return f.prop(a,c)?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.attrHooks.title=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i. +shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function(c){var d=c.target,e,g;if(!!y.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=I(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};bf.optgroup=bf.option,bf.tbody=bf.tfoot=bf.colgroup=bf.caption=bf.thead,bf.th=bf.td,f.support.htmlSerialize||(bf._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!bf[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j +)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bi(a,d),e=bj(a),g=bj(d);for(h=0;e[h];++h)bi(e[h],g[h])}if(b){bh(a,d);if(c){e=bj(a),g=bj(d);for(h=0;e[h];++h)bh(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!ba.test(k))k=b.createTextNode(k);else{k=k.replace(Z,"<$1>");var l=($.exec(k)||["",""])[1].toLowerCase(),m=bf[l]||bf._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=_.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Y.test(k)&&o.insertBefore(b.createTextNode(Y.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bo.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bn.test(g)?g.replace(bn,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bB=/%20/g,bC=/\[\]$/,bD=/\r?\n/g,bE=/#.*$/,bF=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bG=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bH=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bI=/^(?:GET|HEAD)$/,bJ=/^\/\//,bK=/\?/,bL=/)<[^<]*)*<\/script>/gi,bM=/^(?:select|textarea)/i,bN=/\s+/,bO=/([?&])_=[^&]*/,bP=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bQ=f.fn.load,bR={},bS={},bT,bU;try{bT=e.href}catch(bV){bT=c.createElement("a"),bT.href="",bT=bT.href}bU=bP.exec(bT.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bQ)return bQ.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bL,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bM.test(this.nodeName)||bG.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bD,"\r\n")}}):{name:b.name,value:c.replace(bD,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bT,isLocal:bH.test(bU[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bW(bR),ajaxTransport:bW(bS),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?bZ(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b$(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bF.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bE,"").replace(bJ,bU[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bN),d.crossDomain==null&&(r=bP.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bU[1]&&r[2]==bU[2]&&(r[3]||(r[1]==="http:"?80:443))==(bU[3]||(bU[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bX(bR,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bI.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bK.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bO,"$1_="+x);d.url=y+(y===d.url?(bK.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bX(bS,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bB,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn,co=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cr("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b
";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cu.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cu.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cv(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cv(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); +var hljs=new function(){function l(o){return o.replace(/&/gm,"&").replace(/"}while(x.length||y.length){var u=t().splice(0,1)[0];v+=l(w.substr(q,u.offset-q));q=u.offset;if(u.event=="start"){v+=r(u.node);s.push(u.node)}else{if(u.event=="stop"){var p=s.length;do{p--;var o=s[p];v+=("")}while(o!=u.node);s.splice(p,1);while(p'+l(K[0])+""}else{M+=l(K[0])}O=N.lR.lastIndex;K=N.lR.exec(L)}M+=l(L.substr(O,L.length-O));return M}function J(r,L){if(L.sL&&d[L.sL]){var K=f(L.sL,r);s+=K.keyword_count;return K.value}else{return E(r,L)}}function H(L,r){var K=L.cN?'':"";if(L.rB){p+=K;L.buffer=""}else{if(L.eB){p+=l(r)+K;L.buffer=""}else{p+=K;L.buffer=r}}B.push(L);A+=L.r}function D(N,K,P){var Q=B[B.length-1];if(P){p+=J(Q.buffer+N,Q);return false}var L=y(K,Q);if(L){p+=J(Q.buffer+N,Q);H(L,K);return L.rB}var r=v(B.length-1,K);if(r){var M=Q.cN?"":"";if(Q.rE){p+=J(Q.buffer+N,Q)+M}else{if(Q.eE){p+=J(Q.buffer+N,Q)+M+l(K)}else{p+=J(Q.buffer+N+K,Q)+M}}while(r>1){M=B[B.length-2].cN?"":"";p+=M;r--;B.length--}var O=B[B.length-1];B.length--;B[B.length-1].buffer="";if(O.starts){H(O.starts,"")}return Q.rE}if(w(K,Q)){throw"Illegal"}}var G=d[I];var B=[G.dM];var A=0;var s=0;var p="";try{var u=0;G.dM.buffer="";do{var x=q(C,u);var t=D(x[0],x[1],x[2]);u+=x[0].length;if(!t){u+=x[1].length}}while(!x[2]);if(B.length>1){throw"Illegal"}return{language:I,r:A,keyword_count:s,value:p}}catch(F){if(F=="Illegal"){return{language:null,r:0,keyword_count:0,value:l(C)}}else{throw F}}}function h(){function o(t,s,u){if(t.compiled){return}if(!u){t.bR=c(s,t.b?t.b:"\\B|\\b");if(!t.e&&!t.eW){t.e="\\B|\\b"}if(t.e){t.eR=c(s,t.e)}}if(t.i){t.iR=c(s,t.i)}if(t.r==undefined){t.r=1}if(t.k){t.lR=c(s,t.l||hljs.IR,true)}for(var r in t.k){if(!t.k.hasOwnProperty(r)){continue}if(t.k[r] instanceof Object){t.kG=t.k}else{t.kG={keyword:t.k}}break}if(!t.c){t.c=[]}t.compiled=true;for(var q=0;qx.keyword_count+x.r){x=u}if(u.keyword_count+u.r>w.keyword_count+w.r){x=w;w=u}}}var s=t.className;if(!s.match(w.language)){s=s?(s+" "+w.language):w.language}var o=b(t);if(o.length){var q=document.createElement("pre");q.innerHTML=w.value;w.value=k(o,b(q),A)}if(y){w.value=w.value.replace(/^((<[^>]+>|\t)+)/gm,function(B,E,D,C){return E.replace(/\t/g,y)})}if(p){w.value=w.value.replace(/\n/g,"
")}if(/MSIE [678]/.test(navigator.userAgent)&&t.tagName=="CODE"&&t.parentNode.tagName=="PRE"){var q=t.parentNode;var v=document.createElement("div");v.innerHTML="
"+w.value+"
";t=v.firstChild.firstChild;v.firstChild.cN=q.cN;q.parentNode.replaceChild(v.firstChild,q)}else{t.innerHTML=w.value}t.className=s;t.dataset={};t.dataset.result={language:w.language,kw:w.keyword_count,re:w.r};if(x&&x.language){t.dataset.second_best={language:x.language,kw:x.keyword_count,re:x.r}}}function j(){if(j.called){return}j.called=true;e();var q=document.getElementsByTagName("pre");for(var o=0;o|>=|>>|>>=|>>>|>>>=|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\.",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE],r:0};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE],r:0};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.inherit=function(o,r){var q={};for(var p in o){q[p]=o[p]}if(r){for(var p in r){q[p]=r[p]}}return q}}();hljs.LANGUAGES.ruby=function(){var g="[a-zA-Z_][a-zA-Z0-9_]*(\\!|\\?)?";var a="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?";var n={keyword:{and:1,"false":1,then:1,defined:1,module:1,"in":1,"return":1,redo:1,"if":1,BEGIN:1,retry:1,end:1,"for":1,"true":1,self:1,when:1,next:1,until:1,"do":1,begin:1,unless:1,END:1,rescue:1,nil:1,"else":1,"break":1,undef:1,not:1,"super":1,"class":1,"case":1,require:1,yield:1,alias:1,"while":1,ensure:1,elsif:1,or:1,def:1},keymethods:{__id__:1,__send__:1,abort:1,abs:1,"all?":1,allocate:1,ancestors:1,"any?":1,arity:1,assoc:1,at:1,at_exit:1,autoload:1,"autoload?":1,"between?":1,binding:1,binmode:1,"block_given?":1,call:1,callcc:1,caller:1,capitalize:1,"capitalize!":1,casecmp:1,"catch":1,ceil:1,center:1,chomp:1,"chomp!":1,chop:1,"chop!":1,chr:1,"class":1,class_eval:1,"class_variable_defined?":1,class_variables:1,clear:1,clone:1,close:1,close_read:1,close_write:1,"closed?":1,coerce:1,collect:1,"collect!":1,compact:1,"compact!":1,concat:1,"const_defined?":1,const_get:1,const_missing:1,const_set:1,constants:1,count:1,crypt:1,"default":1,default_proc:1,"delete":1,"delete!":1,delete_at:1,delete_if:1,detect:1,display:1,div:1,divmod:1,downcase:1,"downcase!":1,downto:1,dump:1,dup:1,each:1,each_byte:1,each_index:1,each_key:1,each_line:1,each_pair:1,each_value:1,each_with_index:1,"empty?":1,entries:1,eof:1,"eof?":1,"eql?":1,"equal?":1,"eval":1,exec:1,exit:1,"exit!":1,extend:1,fail:1,fcntl:1,fetch:1,fileno:1,fill:1,find:1,find_all:1,first:1,flatten:1,"flatten!":1,floor:1,flush:1,for_fd:1,foreach:1,fork:1,format:1,freeze:1,"frozen?":1,fsync:1,getc:1,gets:1,global_variables:1,grep:1,gsub:1,"gsub!":1,"has_key?":1,"has_value?":1,hash:1,hex:1,id:1,include:1,"include?":1,included_modules:1,index:1,indexes:1,indices:1,induced_from:1,inject:1,insert:1,inspect:1,instance_eval:1,instance_method:1,instance_methods:1,"instance_of?":1,"instance_variable_defined?":1,instance_variable_get:1,instance_variable_set:1,instance_variables:1,"integer?":1,intern:1,invert:1,ioctl:1,"is_a?":1,isatty:1,"iterator?":1,join:1,"key?":1,keys:1,"kind_of?":1,lambda:1,last:1,length:1,lineno:1,ljust:1,load:1,local_variables:1,loop:1,lstrip:1,"lstrip!":1,map:1,"map!":1,match:1,max:1,"member?":1,merge:1,"merge!":1,method:1,"method_defined?":1,method_missing:1,methods:1,min:1,module_eval:1,modulo:1,name:1,nesting:1,"new":1,next:1,"next!":1,"nil?":1,nitems:1,"nonzero?":1,object_id:1,oct:1,open:1,pack:1,partition:1,pid:1,pipe:1,pop:1,popen:1,pos:1,prec:1,prec_f:1,prec_i:1,print:1,printf:1,private_class_method:1,private_instance_methods:1,"private_method_defined?":1,private_methods:1,proc:1,protected_instance_methods:1,"protected_method_defined?":1,protected_methods:1,public_class_method:1,public_instance_methods:1,"public_method_defined?":1,public_methods:1,push:1,putc:1,puts:1,quo:1,raise:1,rand:1,rassoc:1,read:1,read_nonblock:1,readchar:1,readline:1,readlines:1,readpartial:1,rehash:1,reject:1,"reject!":1,remainder:1,reopen:1,replace:1,require:1,"respond_to?":1,reverse:1,"reverse!":1,reverse_each:1,rewind:1,rindex:1,rjust:1,round:1,rstrip:1,"rstrip!":1,scan:1,seek:1,select:1,send:1,set_trace_func:1,shift:1,singleton_method_added:1,singleton_methods:1,size:1,sleep:1,slice:1,"slice!":1,sort:1,"sort!":1,sort_by:1,split:1,sprintf:1,squeeze:1,"squeeze!":1,srand:1,stat:1,step:1,store:1,strip:1,"strip!":1,sub:1,"sub!":1,succ:1,"succ!":1,sum:1,superclass:1,swapcase:1,"swapcase!":1,sync:1,syscall:1,sysopen:1,sysread:1,sysseek:1,system:1,syswrite:1,taint:1,"tainted?":1,tell:1,test:1,"throw":1,times:1,to_a:1,to_ary:1,to_f:1,to_hash:1,to_i:1,to_int:1,to_io:1,to_proc:1,to_s:1,to_str:1,to_sym:1,tr:1,"tr!":1,tr_s:1,"tr_s!":1,trace_var:1,transpose:1,trap:1,truncate:1,"tty?":1,type:1,ungetc:1,uniq:1,"uniq!":1,unpack:1,unshift:1,untaint:1,untrace_var:1,upcase:1,"upcase!":1,update:1,upto:1,"value?":1,values:1,values_at:1,warn:1,write:1,write_nonblock:1,"zero?":1,zip:1}};var h={cN:"yardoctag",b:"@[A-Za-z]+"};var d={cN:"comment",b:"#",e:"$",c:[h]};var c={cN:"comment",b:"^\\=begin",e:"^\\=end",c:[h],r:10};var b={cN:"comment",b:"^__END__",e:"\\n$"};var u={cN:"subst",b:"#\\{",e:"}",l:g,k:n};var p=[hljs.BE,u];var s={cN:"string",b:"'",e:"'",c:p,r:0};var r={cN:"string",b:'"',e:'"',c:p,r:0};var q={cN:"string",b:"%[qw]?\\(",e:"\\)",c:p,r:10};var o={cN:"string",b:"%[qw]?\\[",e:"\\]",c:p,r:10};var m={cN:"string",b:"%[qw]?{",e:"}",c:p,r:10};var l={cN:"string",b:"%[qw]?<",e:">",c:p,r:10};var k={cN:"string",b:"%[qw]?/",e:"/",c:p,r:10};var j={cN:"string",b:"%[qw]?%",e:"%",c:p,r:10};var i={cN:"string",b:"%[qw]?-",e:"-",c:p,r:10};var t={cN:"string",b:"%[qw]?\\|",e:"\\|",c:p,r:10};var e={cN:"function",b:"\\bdef\\s+",e:" |$|;",l:g,k:n,c:[{cN:"title",b:a,l:g,k:n},{cN:"params",b:"\\(",e:"\\)",l:g,k:n},d,c,b]};var f={cN:"identifier",b:g,l:g,k:n,r:0};var v=[d,c,b,s,r,q,o,m,l,k,j,i,t,{cN:"class",b:"\\b(class|module)\\b",e:"$|;",k:{"class":1,module:1},c:[{cN:"title",b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?",r:0},{cN:"inheritance",b:"<\\s*",c:[{cN:"parent",b:"("+hljs.IR+"::)?"+hljs.IR}]},d,c,b]},e,{cN:"constant",b:"(::)?([A-Z]\\w*(::)?)+",r:0},{cN:"symbol",b:":",c:[s,r,q,o,m,l,k,j,i,t,f],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{cN:"number",b:"\\?\\w"},{cN:"variable",b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},f,{b:"("+hljs.RSR+")\\s*",c:[d,c,b,{cN:"regexp",b:"/",e:"/[a-z]*",i:"\\n",c:[hljs.BE]}],r:0}];u.c=v;e.c[1].c=v;return{dM:{l:g,k:n,c:v}}}(); +/*! + Colorbox v1.5.13 - 2014-08-04 + jQuery lightbox and modal window plugin + (c) 2014 Jack Moore - http://www.jacklmoore.com/colorbox + license: http://www.opensource.org/licenses/mit-license.php + */ + +(function ($, document, window) { + var + // Default settings object. + // See http://jacklmoore.com/colorbox for details. + defaults = { + // data sources + html: false, + photo: false, + iframe: false, + inline: false, + + // behavior and appearance + transition: "elastic", + speed: 300, + fadeOut: 300, + width: false, + initialWidth: "600", + innerWidth: false, + maxWidth: false, + height: false, + initialHeight: "450", + innerHeight: false, + maxHeight: false, + scalePhotos: true, + scrolling: true, + opacity: 0.9, + preloading: true, + className: false, + overlayClose: true, + escKey: true, + arrowKey: true, + top: false, + bottom: false, + left: false, + right: false, + fixed: false, + data: undefined, + closeButton: true, + fastIframe: true, + open: false, + reposition: true, + loop: true, + slideshow: false, + slideshowAuto: true, + slideshowSpeed: 2500, + slideshowStart: "start slideshow", + slideshowStop: "stop slideshow", + photoRegex: /\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i, + + // alternate image paths for high-res displays + retinaImage: false, + retinaUrl: false, + retinaSuffix: '@2x.$1', + + // internationalization + current: "image {current} of {total}", + previous: "previous", + next: "next", + close: "close", + xhrError: "This content failed to load.", + imgError: "This image failed to load.", + + // accessbility + returnFocus: true, + trapFocus: true, + + // callbacks + onOpen: false, + onLoad: false, + onComplete: false, + onCleanup: false, + onClosed: false, + + rel: function() { + return this.rel; + }, + href: function() { + // using this.href would give the absolute url, when the href may have been inteded as a selector (e.g. '#container') + return $(this).attr('href'); + }, + title: function() { + return this.title; + } + }, + + // Abstracting the HTML and event identifiers for easy rebranding + colorbox = 'colorbox', + prefix = 'cbox', + boxElement = prefix + 'Element', + + // Events + event_open = prefix + '_open', + event_load = prefix + '_load', + event_complete = prefix + '_complete', + event_cleanup = prefix + '_cleanup', + event_closed = prefix + '_closed', + event_purge = prefix + '_purge', + + // Cached jQuery Object Variables + $overlay, + $box, + $wrap, + $content, + $topBorder, + $leftBorder, + $rightBorder, + $bottomBorder, + $related, + $window, + $loaded, + $loadingBay, + $loadingOverlay, + $title, + $current, + $slideshow, + $next, + $prev, + $close, + $groupControls, + $events = $(''), // $({}) would be prefered, but there is an issue with jQuery 1.4.2 + + // Variables for cached values or use across multiple functions + settings, + interfaceHeight, + interfaceWidth, + loadedHeight, + loadedWidth, + index, + photo, + open, + active, + closing, + loadingTimer, + publicMethod, + div = "div", + requests = 0, + previousCSS = {}, + init; + + // **************** + // HELPER FUNCTIONS + // **************** + + // Convenience function for creating new jQuery objects + function $tag(tag, id, css) { + var element = document.createElement(tag); + + if (id) { + element.id = prefix + id; + } + + if (css) { + element.style.cssText = css; + } + + return $(element); + } + + // Get the window height using innerHeight when available to avoid an issue with iOS + // http://bugs.jquery.com/ticket/6724 + function winheight() { + return window.innerHeight ? window.innerHeight : $(window).height(); + } + + function Settings(element, options) { + if (options !== Object(options)) { + options = {}; + } + + this.cache = {}; + this.el = element; + + this.value = function(key) { + var dataAttr; + + if (this.cache[key] === undefined) { + dataAttr = $(this.el).attr('data-cbox-'+key); + + if (dataAttr !== undefined) { + this.cache[key] = dataAttr; + } else if (options[key] !== undefined) { + this.cache[key] = options[key]; + } else if (defaults[key] !== undefined) { + this.cache[key] = defaults[key]; + } + } + + return this.cache[key]; + }; + + this.get = function(key) { + var value = this.value(key); + return $.isFunction(value) ? value.call(this.el, this) : value; + }; + } + + // Determine the next and previous members in a group. + function getIndex(increment) { + var + max = $related.length, + newIndex = (index + increment) % max; + + return (newIndex < 0) ? max + newIndex : newIndex; + } + + // Convert '%' and 'px' values to integers + function setSize(size, dimension) { + return Math.round((/%/.test(size) ? ((dimension === 'x' ? $window.width() : winheight()) / 100) : 1) * parseInt(size, 10)); + } + + // Checks an href to see if it is a photo. + // There is a force photo option (photo: true) for hrefs that cannot be matched by the regex. + function isImage(settings, url) { + return settings.get('photo') || settings.get('photoRegex').test(url); + } + + function retinaUrl(settings, url) { + return settings.get('retinaUrl') && window.devicePixelRatio > 1 ? url.replace(settings.get('photoRegex'), settings.get('retinaSuffix')) : url; + } + + function trapFocus(e) { + if ('contains' in $box[0] && !$box[0].contains(e.target) && e.target !== $overlay[0]) { + e.stopPropagation(); + $box.focus(); + } + } + + function setClass(str) { + if (setClass.str !== str) { + $box.add($overlay).removeClass(setClass.str).addClass(str); + setClass.str = str; + } + } + + function getRelated(rel) { + index = 0; + + if (rel && rel !== false && rel !== 'nofollow') { + $related = $('.' + boxElement).filter(function () { + var options = $.data(this, colorbox); + var settings = new Settings(this, options); + return (settings.get('rel') === rel); + }); + index = $related.index(settings.el); + + // Check direct calls to Colorbox. + if (index === -1) { + $related = $related.add(settings.el); + index = $related.length - 1; + } + } else { + $related = $(settings.el); + } + } + + function trigger(event) { + // for external use + $(document).trigger(event); + // for internal use + $events.triggerHandler(event); + } + + var slideshow = (function(){ + var active, + className = prefix + "Slideshow_", + click = "click." + prefix, + timeOut; + + function clear () { + clearTimeout(timeOut); + } + + function set() { + if (settings.get('loop') || $related[index + 1]) { + clear(); + timeOut = setTimeout(publicMethod.next, settings.get('slideshowSpeed')); + } + } + + function start() { + $slideshow + .html(settings.get('slideshowStop')) + .unbind(click) + .one(click, stop); + + $events + .bind(event_complete, set) + .bind(event_load, clear); + + $box.removeClass(className + "off").addClass(className + "on"); + } + + function stop() { + clear(); + + $events + .unbind(event_complete, set) + .unbind(event_load, clear); + + $slideshow + .html(settings.get('slideshowStart')) + .unbind(click) + .one(click, function () { + publicMethod.next(); + start(); + }); + + $box.removeClass(className + "on").addClass(className + "off"); + } + + function reset() { + active = false; + $slideshow.hide(); + clear(); + $events + .unbind(event_complete, set) + .unbind(event_load, clear); + $box.removeClass(className + "off " + className + "on"); + } + + return function(){ + if (active) { + if (!settings.get('slideshow')) { + $events.unbind(event_cleanup, reset); + reset(); + } + } else { + if (settings.get('slideshow') && $related[1]) { + active = true; + $events.one(event_cleanup, reset); + if (settings.get('slideshowAuto')) { + start(); + } else { + stop(); + } + $slideshow.show(); + } + } + }; + + }()); + + + function launch(element) { + var options; + + if (!closing) { + + options = $(element).data(colorbox); + + settings = new Settings(element, options); + + getRelated(settings.get('rel')); + + if (!open) { + open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys. + + setClass(settings.get('className')); + + // Show colorbox so the sizes can be calculated in older versions of jQuery + $box.css({visibility:'hidden', display:'block', opacity:''}); + + $loaded = $tag(div, 'LoadedContent', 'width:0; height:0; overflow:hidden; visibility:hidden'); + $content.css({width:'', height:''}).append($loaded); + + // Cache values needed for size calculations + interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height(); + interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width(); + loadedHeight = $loaded.outerHeight(true); + loadedWidth = $loaded.outerWidth(true); + + // Opens inital empty Colorbox prior to content being loaded. + var initialWidth = setSize(settings.get('initialWidth'), 'x'); + var initialHeight = setSize(settings.get('initialHeight'), 'y'); + var maxWidth = settings.get('maxWidth'); + var maxHeight = settings.get('maxHeight'); + + settings.w = (maxWidth !== false ? Math.min(initialWidth, setSize(maxWidth, 'x')) : initialWidth) - loadedWidth - interfaceWidth; + settings.h = (maxHeight !== false ? Math.min(initialHeight, setSize(maxHeight, 'y')) : initialHeight) - loadedHeight - interfaceHeight; + + $loaded.css({width:'', height:settings.h}); + publicMethod.position(); + + trigger(event_open); + settings.get('onOpen'); + + $groupControls.add($title).hide(); + + $box.focus(); + + if (settings.get('trapFocus')) { + // Confine focus to the modal + // Uses event capturing that is not supported in IE8- + if (document.addEventListener) { + + document.addEventListener('focus', trapFocus, true); + + $events.one(event_closed, function () { + document.removeEventListener('focus', trapFocus, true); + }); + } + } + + // Return focus on closing + if (settings.get('returnFocus')) { + $events.one(event_closed, function () { + $(settings.el).focus(); + }); + } + } + + var opacity = parseFloat(settings.get('opacity')); + $overlay.css({ + opacity: opacity === opacity ? opacity : '', + cursor: settings.get('overlayClose') ? 'pointer' : '', + visibility: 'visible' + }).show(); + + if (settings.get('closeButton')) { + $close.html(settings.get('close')).appendTo($content); + } else { + $close.appendTo('
'); // replace with .detach() when dropping jQuery < 1.4 + } + + load(); + } + } + + // Colorbox's markup needs to be added to the DOM prior to being called + // so that the browser will go ahead and load the CSS background images. + function appendHTML() { + if (!$box && document.body) { + init = false; + $window = $(window); + $box = $tag(div).attr({ + id: colorbox, + 'class': $.support.opacity === false ? prefix + 'IE' : '', // class for optional IE8 & lower targeted CSS. + role: 'dialog', + tabindex: '-1' + }).hide(); + $overlay = $tag(div, "Overlay").hide(); + $loadingOverlay = $([$tag(div, "LoadingOverlay")[0],$tag(div, "LoadingGraphic")[0]]); + $wrap = $tag(div, "Wrapper"); + $content = $tag(div, "Content").append( + $title = $tag(div, "Title"), + $current = $tag(div, "Current"), + $prev = $(' +
diff --git a/config/routes.rb b/config/routes.rb index f075025c11..2aed48ae75 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,9 +10,9 @@ root to: "cms/content#show" # root "works#root" - get "/auth/github", as: "github_login", as: "perform_login" + get "/auth/github", as: "github_login" get "/auth/:provider/callback", to: "merchants#create", as: "auth_callback" - delete "/logout", to: "merchants#destroy", as: "logout" + delete "/logout", to: "merchants#logout", as: "logout" # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end From 82c771ed70176d23b8316c710d96bf76ee0dd019 Mon Sep 17 00:00:00 2001 From: Cloudy Lopez Date: Fri, 3 May 2019 15:33:51 -0700 Subject: [PATCH 079/260] completed all relationship testing for ordertest --- test/models/order_test.rb | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/test/models/order_test.rb b/test/models/order_test.rb index 4c979ef1a7..720a852d83 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -4,8 +4,27 @@ let(:order) { orders(:order_1) } it "must be valid" do - value(order).must_be :valid? + expect(order.valid?).must_equal true end -end # has_many :items +describe "relationship with an order" do + it "can have 0 items" do + Item.destroy_all + expect(order.items.count).must_equal 0 + end + + it "can have 1 or more items" do + expect(order.items.count).must_equal 2 + end +end + +it "can shovel items to create a relationship" do + product = products(:product_1) + item = Item.new(quantity: 3, product: product) + expect(item.valid?).must_equal false + order.items << item + expect(item.valid?).must_equal true + expect(order.items.include?(item)).must_equal true + end +end \ No newline at end of file From c7384fc840cdd255de9ec48db48721d063f8754c Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Sat, 4 May 2019 09:24:19 -0700 Subject: [PATCH 080/260] Generated a homepages controller, index view; updated the root_path to hompages#index. Yay, we have a home page now, woooot --- app/assets/javascripts/homepages.js | 2 ++ app/assets/stylesheets/homepages.scss | 3 +++ app/controllers/homepages_controller.rb | 4 ++++ app/helpers/homepages_helper.rb | 2 ++ app/views/homepages/index.html.erb | 2 ++ config/routes.rb | 3 ++- test/controllers/homepages_controller_test.rb | 9 +++++++++ 7 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/homepages.js create mode 100644 app/assets/stylesheets/homepages.scss create mode 100644 app/controllers/homepages_controller.rb create mode 100644 app/helpers/homepages_helper.rb create mode 100644 app/views/homepages/index.html.erb create mode 100644 test/controllers/homepages_controller_test.rb diff --git a/app/assets/javascripts/homepages.js b/app/assets/javascripts/homepages.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/homepages.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/homepages.scss b/app/assets/stylesheets/homepages.scss new file mode 100644 index 0000000000..2305c36d10 --- /dev/null +++ b/app/assets/stylesheets/homepages.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Homepages controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/homepages_controller.rb b/app/controllers/homepages_controller.rb new file mode 100644 index 0000000000..f200c8ac2e --- /dev/null +++ b/app/controllers/homepages_controller.rb @@ -0,0 +1,4 @@ +class HomepagesController < ApplicationController + def index + end +end diff --git a/app/helpers/homepages_helper.rb b/app/helpers/homepages_helper.rb new file mode 100644 index 0000000000..4bd8098f37 --- /dev/null +++ b/app/helpers/homepages_helper.rb @@ -0,0 +1,2 @@ +module HomepagesHelper +end diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb new file mode 100644 index 0000000000..37d3ce7099 --- /dev/null +++ b/app/views/homepages/index.html.erb @@ -0,0 +1,2 @@ +

Homepages#index

+

Find me in app/views/homepages/index.html.erb

diff --git a/config/routes.rb b/config/routes.rb index 0591ad2d7f..81d302518e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,5 @@ Rails.application.routes.draw do + get "homepages/index" resources :categories, only: [:new, :create, :index, :show] resources :items, only: [:create, :update, :delete] resources :merchants, only: [:index, :create, :show, :delete] @@ -14,7 +15,7 @@ resources :reviews, only: [:create] end - root to: "cms/content#show" + root to: "homepages#index" # root "works#root" get "/auth/github", as: "github_login" get "/auth/:provider/callback", to: "merchants#create", as: "auth_callback" diff --git a/test/controllers/homepages_controller_test.rb b/test/controllers/homepages_controller_test.rb new file mode 100644 index 0000000000..7395af3dec --- /dev/null +++ b/test/controllers/homepages_controller_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe HomepagesController do + it "should get index" do + get homepages_index_url + value(response).must_be :success? + end + +end From 798f325073a387a1ec2e6b291207de60f2e1b4e1 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Sat, 4 May 2019 09:54:19 -0700 Subject: [PATCH 081/260] created products _form.html.erb, created products new, can add a new product, must manually add merchant id, does not have functionalitiy to let only logged in merchants create an item yet --- app/controllers/products_controller.rb | 18 ++++++++++++++++ app/views/products/_form.html.erb | 29 ++++++++++++++++++++++++++ app/views/products/new.html.erb | 10 +++++++-- config/routes.rb | 8 +++---- 4 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 app/views/products/_form.html.erb diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 96c1625769..b76b066c38 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,8 +1,20 @@ class ProductsController < ApplicationController def new + @product = Product.new end def create + product = Product.new(product_params) + + is_successful = product.save + + if is_successful + flash[:success] = "Product added successfully" + redirect_to product_path(product.id) + else + flash.now[:error] = "Could not add new product: #{product.errors.messages}" #need help formatting this flash better + end + render :new, status: :bad_request end def index @@ -23,4 +35,10 @@ def edit def update end + + private + + def product_params + return params.require(:product).permit(:name, :price, :description, :photo_url, :stock, :merchant_id, category_ids: []) + end end diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb new file mode 100644 index 0000000000..630914e836 --- /dev/null +++ b/app/views/products/_form.html.erb @@ -0,0 +1,29 @@ +<%= form_with model: @product, class: form_class do |f| %> + +

<%= intro_text %>

+ + <%= f.label :name %> + <%= f.text_field :name %> + + <%= f.label :merchant_id %> + <%= f.text_field :merchant_id %> + + <%= f.label :price %> + <%= f.text_field :price %> + + <%= f.label :category %> + <%= f.select :category_id, Category.all.map {|category| [category.name, category.id] } %> + + <%= f.label :description %> + <%= f.text_field :description %> + + <%= f.label :photo_url %> + <%= f.text_field :photo_url %> + + <%= f.label :stock %> + <%= f.text_field :stock %> + + <%= f.submit action_name, class: "product-form__submit-btn" %> + +<% end %> + diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index a14e0d91b6..ff9d657d6d 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -1,2 +1,8 @@ -

Products#new

-

Find me in app/views/products/new.html.erb

+

Form for creating a new product

+ + +<%= render partial: "form", locals: { + form_class: "new-product", + intro_text: "Use this form to create a new product", + action_name: "Create product" +} %> \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 0591ad2d7f..9e0bc7aa3e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,10 +4,10 @@ resources :merchants, only: [:index, :create, :show, :delete] resources :orders # UPDATE THIS AFTER WE DECIDE WHAT WE NEED/DON'T - # Is this correct? -mf - resources :categories do - resources :products, only: [:index] - end + # Not currently using this nested route -mf + # resources :categories do + # resources :products, only: [:index] + # end # resources :categories, only: [:new, :create, :index] resources :products, except: [:delete] do From 1222d684ac9bb1cc73194ae5802d7bdf430f566e Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Sat, 4 May 2019 10:09:46 -0700 Subject: [PATCH 082/260] added flash error messages to product create action, improved functionality on form to select multiple categories --- app/controllers/products_controller.rb | 4 ++-- app/views/products/_form.html.erb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index b76b066c38..857eb0f6c1 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -12,9 +12,9 @@ def create flash[:success] = "Product added successfully" redirect_to product_path(product.id) else - flash.now[:error] = "Could not add new product: #{product.errors.messages}" #need help formatting this flash better + flash[:error] = "Could not add new product: #{product.errors.messages}" #need help formatting this flash better + render :new, status: :bad_request end - render :new, status: :bad_request end def index diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb index 630914e836..a135632681 100644 --- a/app/views/products/_form.html.erb +++ b/app/views/products/_form.html.erb @@ -11,8 +11,8 @@ <%= f.label :price %> <%= f.text_field :price %> - <%= f.label :category %> - <%= f.select :category_id, Category.all.map {|category| [category.name, category.id] } %> + <%= f.label :categories %> + <%= collection_check_boxes(:product, :category_ids, Category.all, :id, :name) %> <%= f.label :description %> <%= f.text_field :description %> From e49d4b3d68f2728b720215d6b7cf2851925feb7c Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Sat, 4 May 2019 10:21:55 -0700 Subject: [PATCH 083/260] added private find_user method to application controller --- app/controllers/application_controller.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 09705d12ab..8f41082eab 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,9 @@ class ApplicationController < ActionController::Base + private + + def find_user + if session[:user_id] + @login_user = User.find_by(id: session[:user_id]) + end + end end From 34d67311d92a8b6bb1548d1a7c839d4c4e057cbe Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Sat, 4 May 2019 10:33:08 -0700 Subject: [PATCH 084/260] added fuctionality to only have logged in user (merchant) create a new product --- app/controllers/products_controller.rb | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 857eb0f6c1..c39bdc7a77 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -4,15 +4,20 @@ def new end def create - product = Product.new(product_params) - - is_successful = product.save - - if is_successful - flash[:success] = "Product added successfully" - redirect_to product_path(product.id) + if @login_user # if user is logged in + product = Product.new(product_params) + + is_successful = product.save + + if is_successful + flash[:success] = "Product added successfully" + redirect_to product_path(product.id) + else + flash.now[:error] = "Could not add new product: #{product.errors.messages}" #need help formatting this flash better + render :new, status: :bad_request + end else - flash[:error] = "Could not add new product: #{product.errors.messages}" #need help formatting this flash better + flash.now[:error] = "You must be logged in to create a new product" render :new, status: :bad_request end end From b6610b6d08b66dec793110cb25211ae8f03f1027 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Sat, 4 May 2019 10:51:46 -0700 Subject: [PATCH 085/260] Log in button is working. Log out has errors. --- app/controllers/merchants_controller.rb | 6 ++++-- app/models/merchant.rb | 1 + app/views/homepages/index.html.erb | 5 +++++ app/views/layouts/application.html.erb | 7 ++++++- config/routes.rb | 1 - 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 847dabba5c..d79fd11156 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -24,7 +24,7 @@ def create merchant = Merchant.build_from_github(auth_hash) if merchant.save - flash[:success] = "Logged in as new merchant #{merchant.name}" + flash[:success] = "Logged in as new merchant #{merchant.username}" else # Couldn't save the merchant for some reason. If we # hit this it probably means there's a bug with the @@ -77,8 +77,10 @@ def login_form # ^^^^^^^^^^^^^^^^^^^^^^^^^^^ def logout merchant = Merchant.find_by(id: session[:merchant_id]) + raise + # merchant_username = merchant.username session[:merchant_id] = nil - flash[:notice] = "Successfully logged out #{merchant.username}" + flash[:notice] = "Successfully logged out." #{merchant_username}" redirect_to root_path end end diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 4d93af1195..8acb69e831 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -12,5 +12,6 @@ def self.build_from_github(auth_hash) merchant.email = auth_hash["info"]["email"] merchant.uid = auth_hash[:uid] merchant.provider = "github" + return merchant end end diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index 37d3ce7099..62f196f3ef 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -1,2 +1,7 @@

Homepages#index

Find me in app/views/homepages/index.html.erb

+ +<% if @merchant %> +<% @merchant = Merchant.find_by_id(merchant_params[:id]) %> +<%= "You are currently logged in as #{merchant.username}" %> +<% end %> \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index f7e88ef734..71024b1351 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -27,7 +27,12 @@ <%= link_to "Merchants", merchants_path, class: "nav-link" %> - <%= link_to "Log In", auth_callback_path("github"), class: "btn btn-outline-success my-2 my-sm-0" %> + + <% if session.id %> + <%= link_to "Log Out", logout_path, method: :delete, class: "btn btn-outline-success my-2 my-sm-0" %> + <% else %> + <%= link_to "Log In", github_login_path, class: "btn btn-outline-success my-2 my-sm-0" %> + <% end %> <%#
diff --git a/config/routes.rb b/config/routes.rb index 81d302518e..5a41f466df 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -16,7 +16,6 @@ end root to: "homepages#index" - # root "works#root" get "/auth/github", as: "github_login" get "/auth/:provider/callback", to: "merchants#create", as: "auth_callback" delete "/logout", to: "merchants#logout", as: "logout" From 77579bf3fad26b7eb6a3b2fd0b684e5c2859429f Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Sat, 4 May 2019 11:38:45 -0700 Subject: [PATCH 086/260] Stumped on not being able to log out. Pushing changes so Cloudy can try, thereore narrowing down if it is a local issue or a code problem. --- app/controllers/merchants_controller.rb | 2 +- app/models/merchant.rb | 2 +- app/views/layouts/application.html.erb | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index d79fd11156..7c1c04420c 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -77,7 +77,7 @@ def login_form # ^^^^^^^^^^^^^^^^^^^^^^^^^^^ def logout merchant = Merchant.find_by(id: session[:merchant_id]) - raise + # raise # merchant_username = merchant.username session[:merchant_id] = nil flash[:notice] = "Successfully logged out." #{merchant_username}" diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 8acb69e831..75b22ce16e 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -8,7 +8,7 @@ class Merchant < ApplicationRecord def self.build_from_github(auth_hash) merchant = Merchant.new - merchant.username = auth_hash["info"]["name"] # check what comes from github; I think github sends name and we save as username (- Elle) + merchant.username = auth_hash["info"]["username"] # check what comes from github; I think github sends name and we save as username (- Elle) merchant.email = auth_hash["info"]["email"] merchant.uid = auth_hash[:uid] merchant.provider = "github" diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 71024b1351..41d3de3d13 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -21,17 +21,17 @@ <%= link_to "Products", products_path, class: "nav-link" %> - <% if session.id %> - <%= link_to "Log Out", logout_path, method: :delete, class: "btn btn-outline-success my-2 my-sm-0" %> - <% else %> + <% if session.id.nil? %> <%= link_to "Log In", github_login_path, class: "btn btn-outline-success my-2 my-sm-0" %> + <% else %> + <%= link_to "Log Out", logout_path, method: :delete, class: "btn btn-outline-success my-2 my-sm-0" %> <% end %> <%# From f897f4f408abb7aa21e09818802377b64a9a1dc8 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Sat, 4 May 2019 15:15:46 -0700 Subject: [PATCH 087/260] switching tasks --- app/controllers/items_controller.rb | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index 115f9a8fa7..4ae164ed56 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -2,20 +2,25 @@ class ItemsController < ApplicationController def create # find product and order @product = Product.find_by(id: params[:product_id]) - order = Order.find_by(id: session[:order_id]) + order = Order.find_by(id: session[:cart_id]) + # if no current cart, create order and save to session. + unless order + order = Order.create + session[:cart_id] = order.id + end - item = Item.new(item_params) + item = order.items.find_by(product_id: @product.id) + if item + item.quantity += params[:item][:quantity] + else + item = Item.new(item_params) + end # check if requested quanitity is available if @product.stock < item.quantity flash.now[:error] = "Could Not Add To Cart: quantity selected is more than available stock" render "products/show", status: :bad_request else - # if no current order, create order and save to session. - unless order - order = Order.create - session[:order_id] = order.id - end # set up relationships for item @product.items << item From 6c09b0c1649e471ab78a7135ebc5553d73a65a77 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Sat, 4 May 2019 16:50:17 -0700 Subject: [PATCH 088/260] products can be put in a cart --- app/controllers/items_controller.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index 4ae164ed56..b888be6772 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -9,12 +9,7 @@ def create session[:cart_id] = order.id end - item = order.items.find_by(product_id: @product.id) - if item - item.quantity += params[:item][:quantity] - else - item = Item.new(item_params) - end + item = Item.new(item_params) # can add more sophesticated logic for checking items quantitiy is available compared to stock. # check if requested quanitity is available if @product.stock < item.quantity From 7675910e70e45d12db50387ad3bff1b80a02ce53 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Sat, 4 May 2019 17:01:01 -0700 Subject: [PATCH 089/260] Finished fixing the log in and log out function. --- app/controllers/merchants_controller.rb | 2 +- app/models/merchant.rb | 2 +- app/views/homepages/index.html.erb | 4 ++-- app/views/layouts/application.html.erb | 8 +++++--- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 7c1c04420c..d170b490e1 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -80,7 +80,7 @@ def logout # raise # merchant_username = merchant.username session[:merchant_id] = nil - flash[:notice] = "Successfully logged out." #{merchant_username}" + flash[:success] = "Successfully logged out." #{merchant_username}" redirect_to root_path end end diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 75b22ce16e..13a19a20cd 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -8,7 +8,7 @@ class Merchant < ApplicationRecord def self.build_from_github(auth_hash) merchant = Merchant.new - merchant.username = auth_hash["info"]["username"] # check what comes from github; I think github sends name and we save as username (- Elle) + merchant.username = auth_hash["info"]["nickname"] merchant.email = auth_hash["info"]["email"] merchant.uid = auth_hash[:uid] merchant.provider = "github" diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index 62f196f3ef..8dad84c44a 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -1,7 +1,7 @@

Homepages#index

Find me in app/views/homepages/index.html.erb

-<% if @merchant %> -<% @merchant = Merchant.find_by_id(merchant_params[:id]) %> +<% if session[:merchant_id] %> +<% merchant = Merchant.find_by(id: session[:merchant_id]) %> <%= "You are currently logged in as #{merchant.username}" %> <% end %> \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 41d3de3d13..5e89265c43 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -28,10 +28,12 @@ - <% if session.id.nil? %> - <%= link_to "Log In", github_login_path, class: "btn btn-outline-success my-2 my-sm-0" %> + <% if session[:merchant_id] %> + <% merchant = Merchant.find_by(id: session[:merchant_id]) %> + <%= "You are currently logged in as #{merchant.username}" %> + <%= link_to "Log Out", logout_path, method: "delete", class: "btn btn-outline-success my-2 my-sm-0" %> <% else %> - <%= link_to "Log Out", logout_path, method: :delete, class: "btn btn-outline-success my-2 my-sm-0" %> + <%= link_to "Log In", github_login_path, class: "btn btn-outline-success my-2 my-sm-0" %> <% end %> <%# From acd7f3368df6861550e48743310d33ea1095e472 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Sat, 4 May 2019 17:09:52 -0700 Subject: [PATCH 090/260] inprocess of testing --- test/controllers/items_controller_test.rb | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/test/controllers/items_controller_test.rb b/test/controllers/items_controller_test.rb index 154cdaaf00..8aa7d97d7c 100644 --- a/test/controllers/items_controller_test.rb +++ b/test/controllers/items_controller_test.rb @@ -2,13 +2,27 @@ describe ItemsController do describe "create" do + let(:product) { products(:product_1) } + let(:item_params) { { item: { quantity: 2 } } } it "will create a new item" do + expect { + post product_items_path(product.id), params: item_params + }.must_change "Item.count", 1 end it "will create a new order if no order in session" do + expect { + post product_items_path(product.id), params: item_params + }.must_change "Order.count", 1 end - it "will use current order if " do + it "will use current order if cart_id in session " do + expect { + post product_items_path(product.id), params: item_params + }.must_change "Order.count", 1 + expect { + post product_items_path(product.id), params: item_params + }.must_change "Order.count", 0 end it "will not create a new item if product is not valid" do From cec59505f7ac6b55486a34c12326c2f92705dda4 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Sat, 4 May 2019 18:47:26 -0700 Subject: [PATCH 091/260] completed testing for items --- app/controllers/items_controller.rb | 7 ++-- test/controllers/items_controller_test.rb | 44 +++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index b888be6772..28449c9a46 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -10,9 +10,12 @@ def create end item = Item.new(item_params) # can add more sophesticated logic for checking items quantitiy is available compared to stock. + if !@product + flash.now[:error] = "Could Not Add To Cart: product not available" + redirect_to products_path - # check if requested quanitity is available - if @product.stock < item.quantity + # check if requested quanitity is available + elsif item.quantity && @product.stock < item.quantity flash.now[:error] = "Could Not Add To Cart: quantity selected is more than available stock" render "products/show", status: :bad_request else diff --git a/test/controllers/items_controller_test.rb b/test/controllers/items_controller_test.rb index 8aa7d97d7c..34d73959cc 100644 --- a/test/controllers/items_controller_test.rb +++ b/test/controllers/items_controller_test.rb @@ -8,27 +8,71 @@ expect { post product_items_path(product.id), params: item_params }.must_change "Item.count", 1 + + expect(flash[:success]).must_equal "#{product.name} Successfully Added To Cart" + + must_respond_with :redirect + must_redirect_to product_path(product.id) end it "will create a new order if no order in session" do expect { post product_items_path(product.id), params: item_params }.must_change "Order.count", 1 + + expect(flash[:success]).must_equal "#{product.name} Successfully Added To Cart" + + must_respond_with :redirect + must_redirect_to product_path(product.id) end it "will use current order if cart_id in session " do expect { post product_items_path(product.id), params: item_params }.must_change "Order.count", 1 + expect { post product_items_path(product.id), params: item_params }.must_change "Order.count", 0 + + expect(flash[:success]).must_equal "#{product.name} Successfully Added To Cart" + + must_respond_with :redirect + must_redirect_to product_path(product.id) end it "will not create a new item if product is not valid" do + product_id = -1 + expect { + post product_items_path(product_id), params: item_params + }.must_change "Item.count", 0 + + expect(flash[:error]).must_equal "Could Not Add To Cart: product not available" + + must_respond_with :redirect + must_redirect_to products_path end it "will not create an item for with requested quantitiy greater tthan the products stock" do + item_params[:item][:quantity] = product.stock + 1 + expect { + post product_items_path(product.id), params: item_params + }.must_change "Item.count", 0 + + expect(flash[:error]).must_equal "Could Not Add To Cart: quantity selected is more than available stock" + + must_respond_with :bad_request + end + + it "will not create an item with in invalid quantity" do + item_params[:item][:quantity] = nil + expect { + post product_items_path(product.id), params: item_params + }.must_change "Item.count", 0 + + expect(flash[:error]).must_equal "Could Not Add To Cart" + + must_respond_with :bad_request end end end From 757e47f9993a1ea2c1fe6d5f38e3204828e2d305 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Sat, 4 May 2019 20:42:03 -0700 Subject: [PATCH 092/260] added defualt value to order.status and status validations. --- app/models/order.rb | 1 + db/migrate/20190505031625_remove_status_from_orders.rb | 5 +++++ db/migrate/20190505031640_add_status_to_orders.rb | 5 +++++ db/schema.rb | 4 ++-- test/fixtures/orders.yml | 4 ++-- test/models/merchant_test.rb | 1 + 6 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 db/migrate/20190505031625_remove_status_from_orders.rb create mode 100644 db/migrate/20190505031640_add_status_to_orders.rb diff --git a/app/models/order.rb b/app/models/order.rb index 7abfa6be57..d36a748478 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,3 +1,4 @@ class Order < ApplicationRecord has_many :items + validates_inclusion_of :status, :in => ["pending", "paid", "complete", "cancelled"] end diff --git a/db/migrate/20190505031625_remove_status_from_orders.rb b/db/migrate/20190505031625_remove_status_from_orders.rb new file mode 100644 index 0000000000..f855464443 --- /dev/null +++ b/db/migrate/20190505031625_remove_status_from_orders.rb @@ -0,0 +1,5 @@ +class RemoveStatusFromOrders < ActiveRecord::Migration[5.2] + def change + remove_column :orders, :status, :string + end +end diff --git a/db/migrate/20190505031640_add_status_to_orders.rb b/db/migrate/20190505031640_add_status_to_orders.rb new file mode 100644 index 0000000000..e0eaac3cfd --- /dev/null +++ b/db/migrate/20190505031640_add_status_to_orders.rb @@ -0,0 +1,5 @@ +class AddStatusToOrders < ActiveRecord::Migration[5.2] + def change + add_column :orders, :status, :string, default: "pending" + end +end diff --git a/db/schema.rb b/db/schema.rb index 1c7035b4bd..b57efe7098 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_05_01_215729) do +ActiveRecord::Schema.define(version: 2019_05_05_031640) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -48,7 +48,6 @@ end create_table "orders", force: :cascade do |t| - t.string "status" t.string "shopper_name" t.string "shopper_email" t.string "shopper_address" @@ -56,6 +55,7 @@ t.string "cc_exp" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "status", default: "pending" end create_table "products", force: :cascade do |t| diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index d0d0de3feb..406bbec035 100644 --- a/test/fixtures/orders.yml +++ b/test/fixtures/orders.yml @@ -1,7 +1,7 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html order_1: - status: completed + status: complete shopper_name: susie shopper_email: dalmation@susy.org shopper_address: 4455 mailing address @@ -9,7 +9,7 @@ order_1: cc_exp: 03022020 order_2: - status: completed + status: complete shopper_name: miranda shopper_email: panda@hooo.com shopper_address: 43244 tryagain address diff --git a/test/models/merchant_test.rb b/test/models/merchant_test.rb index 9a5322be02..2bddc3e989 100644 --- a/test/models/merchant_test.rb +++ b/test/models/merchant_test.rb @@ -59,6 +59,7 @@ describe "relationship with product" do it "can have 0 products" do + merchant.products.destroy_all expect(merchant.products.count).must_equal 0 end From 068b9c25fa0ca97231e0c101e06436cb07394fe3 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Sat, 4 May 2019 21:36:49 -0700 Subject: [PATCH 093/260] set up cart page with deleted item functionality --- app/controllers/items_controller.rb | 10 +++++++++- app/controllers/orders_controller.rb | 3 +++ app/views/layouts/application.html.erb | 1 + app/views/orders/view_cart.html.erb | 17 +++++++++++++++++ config/routes.rb | 6 +++--- 5 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 app/views/orders/view_cart.html.erb diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index 28449c9a46..87eea5fb86 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -40,7 +40,15 @@ def create def update end - def delete + def destroy + item = Item.find_by(id: params[:id]) + if item + flash[:success] = "#{item.product.name} successfully removed from cart" + item.destroy + redirect_to cart_path + else + flash[:error] = "Unable to remove item" + end end private diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 8a0e3659ae..74c0ebcc4f 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,2 +1,5 @@ class OrdersController < ApplicationController + def view_cart + @order = Order.find_by(id: session[:cart_id]) + end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 5e89265c43..075f52b263 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -35,6 +35,7 @@ <% else %> <%= link_to "Log In", github_login_path, class: "btn btn-outline-success my-2 my-sm-0" %> <% end %> + <%= link_to "Cart", cart_path, class: " nav-item nav-link"%> <%# diff --git a/app/views/orders/view_cart.html.erb b/app/views/orders/view_cart.html.erb new file mode 100644 index 0000000000..8cd076e4cf --- /dev/null +++ b/app/views/orders/view_cart.html.erb @@ -0,0 +1,17 @@ +
+ <%if @order && @order.items.any? %> +

<%=@order.items.count%> item<%="s" if @order.items.count != 1%> in cart

+ <%@order.items.each do |item| %> +
+

<%=item.product.name%>

+

<%=item.product.description%> +

quantity: <%=item.quantity%>

+ <%= link_to "Remove item", item_path(item.id), method: :delete, class: "btn btn-outline-danger btn-sm"%> +
+ <%end%> + <%=link_to "Keep shopping", products_path %> + <%else%> +

0 items in cart

+ <%= link_to "Discover something intangible to fill it up", products_path %> + <%end%> +
diff --git a/config/routes.rb b/config/routes.rb index 3670da1802..b02e65d64f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,16 +1,16 @@ Rails.application.routes.draw do get "homepages/index" resources :categories, only: [:new, :create, :index, :show] - resources :items, only: [:create, :update, :delete] - resources :merchants, only: [:index, :create, :show, :delete] + resources :items, only: [:create, :update, :destroy] + resources :merchants, only: [:index, :create, :show] resources :orders # UPDATE THIS AFTER WE DECIDE WHAT WE NEED/DON'T + get "/cart", to: "orders#view_cart", as: "cart" # Is this correct? -mf resources :categories do resources :products, only: [:index] end - # resources :categories, only: [:new, :create, :index] resources :products, except: [:delete] do resources :reviews, only: [:create] resources :items, only: [:create] From e79c97bd72b731cea72f1c966968f16fa5900066 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Sat, 4 May 2019 22:03:37 -0700 Subject: [PATCH 094/260] added tests destroy action for item --- app/controllers/items_controller.rb | 3 ++- app/views/layouts/application.html.erb | 2 +- test/controllers/items_controller_test.rb | 30 ++++++++++++++++++++--- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index 87eea5fb86..4d47acd082 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -25,7 +25,7 @@ def create order.items << item if item.valid? - flash[:success] = "#{@product.name} Successfully Added To Cart" + flash[:success] = "#{@product.name} (quantity: #{item.quantity}) Successfully Added To Cart" redirect_to product_path(@product.id) else flash.now[:error] = "Could Not Add To Cart" @@ -48,6 +48,7 @@ def destroy redirect_to cart_path else flash[:error] = "Unable to remove item" + redirect_to cart_path end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 075f52b263..7a2b425545 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -35,7 +35,7 @@ <% else %> <%= link_to "Log In", github_login_path, class: "btn btn-outline-success my-2 my-sm-0" %> <% end %> - <%= link_to "Cart", cart_path, class: " nav-item nav-link"%> + <%= link_to "Cart", cart_path, class: "nav-link"%> <%# diff --git a/test/controllers/items_controller_test.rb b/test/controllers/items_controller_test.rb index 34d73959cc..8a2d8feff4 100644 --- a/test/controllers/items_controller_test.rb +++ b/test/controllers/items_controller_test.rb @@ -9,7 +9,7 @@ post product_items_path(product.id), params: item_params }.must_change "Item.count", 1 - expect(flash[:success]).must_equal "#{product.name} Successfully Added To Cart" + expect(flash[:success]).must_equal "#{product.name} (quantity: #{item_params[:item][:quantity]}) Successfully Added To Cart" must_respond_with :redirect must_redirect_to product_path(product.id) @@ -20,7 +20,7 @@ post product_items_path(product.id), params: item_params }.must_change "Order.count", 1 - expect(flash[:success]).must_equal "#{product.name} Successfully Added To Cart" + expect(flash[:success]).must_equal "#{product.name} (quantity: #{item_params[:item][:quantity]}) Successfully Added To Cart" must_respond_with :redirect must_redirect_to product_path(product.id) @@ -35,7 +35,7 @@ post product_items_path(product.id), params: item_params }.must_change "Order.count", 0 - expect(flash[:success]).must_equal "#{product.name} Successfully Added To Cart" + expect(flash[:success]).must_equal "#{product.name} (quantity: #{item_params[:item][:quantity]}) Successfully Added To Cart" must_respond_with :redirect must_redirect_to product_path(product.id) @@ -53,7 +53,7 @@ must_redirect_to products_path end - it "will not create an item for with requested quantitiy greater tthan the products stock" do + it "will not create an item for with requested quantitiy greater than the products stock" do item_params[:item][:quantity] = product.stock + 1 expect { post product_items_path(product.id), params: item_params @@ -75,4 +75,26 @@ must_respond_with :bad_request end end + + describe "destroy" do + let(:item) { items(:item_1) } + it "will destroy a valid item" do + expect { + delete item_path(item.id) + }.must_change "Item.count", -1 + + must_respond_with :redirect + must_redirect_to cart_path + end + + it "will not destroy an item given invalid id" do + invalid_id = -1 + expect { + delete item_path(invalid_id) + }.must_change "Item.count", 0 + + must_respond_with :redirect + must_redirect_to cart_path + end + end end From 783eb3df4328cb039fea281c029122ed3e568157 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Sat, 4 May 2019 22:20:10 -0700 Subject: [PATCH 095/260] added test for view_cart order controller action. --- test/controllers/orders_controller_test.rb | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 68784595f3..97861ca936 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -1,7 +1,20 @@ require "test_helper" describe OrdersController do - # it "must be a real test" do - # flunk "Need real tests" - # end + describe "view_cart" do + it "will respond with success if no cart is stored in session" do + get cart_path + must_respond_with :success + expect(session[:cart_id]).must_be_nil + end + + let(:product) { products(:product_1) } + let(:item_params) { { item: { quantity: 2 } } } + it "will respond with success if cart stored in session" do + post product_items_path(product.id), params: item_params + get cart_path + must_respond_with :success + expect(session[:cart_id]).wont_be_nil + end + end end From 41b121acf651d720ba585524f2d2c645629510d5 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Sun, 5 May 2019 00:46:58 -0700 Subject: [PATCH 096/260] added checkout page, and routes, custom methods for calculation subtotal and total.' --- app/controllers/orders_controller.rb | 11 ++++ app/models/item.rb | 4 ++ app/models/order.rb | 6 ++ app/views/orders/_order_form.html.erb | 68 ++++++++++++++++++++++ app/views/orders/checkout.html.erb | 1 + config/routes.rb | 3 + test/controllers/orders_controller_test.rb | 20 +++++++ 7 files changed, 113 insertions(+) create mode 100644 app/views/orders/_order_form.html.erb create mode 100644 app/views/orders/checkout.html.erb diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 74c0ebcc4f..ca375571c7 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -2,4 +2,15 @@ class OrdersController < ApplicationController def view_cart @order = Order.find_by(id: session[:cart_id]) end + + def checkout + @order = Order.find_by(id: session[:cart_id]) + unless @order + flash[:error] = "Unable to checkout cart" + redirect_to cart_path + end + end + + def purchase + end end diff --git a/app/models/item.rb b/app/models/item.rb index 140fa35a21..e97ba89bcd 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -4,4 +4,8 @@ class Item < ApplicationRecord validates :quantity, presence: true validates_numericality_of :quantity, greater_than: 0 + + def subtotal + return quantity * product.price / 100.0 + end end diff --git a/app/models/order.rb b/app/models/order.rb index d36a748478..ab05e0a2c9 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,4 +1,10 @@ class Order < ApplicationRecord has_many :items validates_inclusion_of :status, :in => ["pending", "paid", "complete", "cancelled"] + + def total + return items.map do |item| + item.subtotal + end.sum + end end diff --git a/app/views/orders/_order_form.html.erb b/app/views/orders/_order_form.html.erb new file mode 100644 index 0000000000..54e6039313 --- /dev/null +++ b/app/views/orders/_order_form.html.erb @@ -0,0 +1,68 @@ +

Cart Check Out

+

Order Items:

+ + + + + + + + + + + + <%@order.items.each_with_index do |item| %> + + + + + + + <%end%> + + + + <%# REMOVE h3, temp added to get a feel for style%> + + + +
QuantityProductUnit PriceSubtotal
<%=item.quantity%><%=link_to item.product.name, product_path(item.product.id) %>$<%=item.product.price / 100.0%>$<%=item.subtotal %>

Total:

$<%=@order.total%>

+ +<%= form_with model: @order, url: cart_path, method: :post do |f|%> +
+
+ <%=f.label "Name on Credit Card"%> + <%=f.text_field :shopper_name, class: "form-control"%> +
+
+ <%=f.label "Email Address" %> + <%=f.email_field :shopper_email, class: "form-control" %> +
+
+
+ <%=f.label "Mailing Address"%> + <%=f.text_field :shopper_address, class: "form-control"%> +
+
+ <%=f.label "Credit Card Number" %> + <%=f.text_field :cc_all, class: "form-control"%> +
+
+
+ <%=f.label "Credit cart expiration"%> + <%=f.date_field :cc_exp, class: "form-control"%> +
+
+ <%=f.label "Credit Card CVV (security code)"%> + <%=f.text_field :cvv , class: "form-control"%> +
+
+ <%=f.label "Billing zip code"%> + <%=f.text_field :zip, class: "form-control"%> +
+
+
+ <%=f.submit "Purchase", class:"btn btn-primary"%> +
+<%end%> + diff --git a/app/views/orders/checkout.html.erb b/app/views/orders/checkout.html.erb new file mode 100644 index 0000000000..d2ec547773 --- /dev/null +++ b/app/views/orders/checkout.html.erb @@ -0,0 +1 @@ +<%=render "order_form"%> \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index b02e65d64f..acb83ca589 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,7 +4,10 @@ resources :items, only: [:create, :update, :destroy] resources :merchants, only: [:index, :create, :show] resources :orders # UPDATE THIS AFTER WE DECIDE WHAT WE NEED/DON'T + get "/cart", to: "orders#view_cart", as: "cart" + get "/cart/checkout", to: "orders#checkout", as: "checkout_cart" + post "/cart", to: "orders#purchase", as: "purchase_cart" # Is this correct? -mf resources :categories do diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 97861ca936..1c9a379d1c 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -17,4 +17,24 @@ expect(session[:cart_id]).wont_be_nil end end + + describe "checkout" do + + let(:product) { products(:product_1) } + let(:item_params) { { item: { quantity: 2 } } } + it "will respond with success if cart stored in session" do + post product_items_path(product.id), params: item_params + get checkout_cart_path + must_respond_with :success + expect(session[:cart_id]).wont_be_nil + end + + it "will redirect if no valid cart in session" do + get checkout_cart_path + must_respond_with :redirect + must_redirect_to cart_path + expect(flash[:error]).must_equal "Unable to checkout cart" + expect(session[:cart_id]).must_be_nil + end + end end From bf2c11111545ef723587ce52eaeea65d35a58391 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Sun, 5 May 2019 01:13:59 -0700 Subject: [PATCH 097/260] added more nav funct --- app/views/orders/checkout.html.erb | 3 ++- app/views/orders/view_cart.html.erb | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/views/orders/checkout.html.erb b/app/views/orders/checkout.html.erb index d2ec547773..ff100e5d57 100644 --- a/app/views/orders/checkout.html.erb +++ b/app/views/orders/checkout.html.erb @@ -1 +1,2 @@ -<%=render "order_form"%> \ No newline at end of file +<%=render "order_form"%> +<%= link_to "Back to Cart", cart_path, class: "btn btn-outline-primary"%> \ No newline at end of file diff --git a/app/views/orders/view_cart.html.erb b/app/views/orders/view_cart.html.erb index 8cd076e4cf..94473eec54 100644 --- a/app/views/orders/view_cart.html.erb +++ b/app/views/orders/view_cart.html.erb @@ -6,9 +6,11 @@

<%=item.product.name%>

<%=item.product.description%>

quantity: <%=item.quantity%>

+

subtotal: $<%=item.subtotal%> <%= link_to "Remove item", item_path(item.id), method: :delete, class: "btn btn-outline-danger btn-sm"%> <%end%> + <%= link_to "Check Out", checkout_cart_path, class: "btn btn-primary"%> <%=link_to "Keep shopping", products_path %> <%else%>

0 items in cart

From 7cbea50f3800d0e3f1158f2c33e57ee9f521b659 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Sun, 5 May 2019 11:49:11 -0700 Subject: [PATCH 098/260] forgot to save routes in earlier commit --- config/routes.rb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 986fa96770..acb83ca589 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -5,12 +5,6 @@ resources :merchants, only: [:index, :create, :show] resources :orders # UPDATE THIS AFTER WE DECIDE WHAT WE NEED/DON'T -<<<<<<< HEAD - # Not currently using this nested route -mf - # resources :categories do - # resources :products, only: [:index] - # end -======= get "/cart", to: "orders#view_cart", as: "cart" get "/cart/checkout", to: "orders#checkout", as: "checkout_cart" post "/cart", to: "orders#purchase", as: "purchase_cart" @@ -19,7 +13,6 @@ resources :categories do resources :products, only: [:index] end ->>>>>>> master resources :products, except: [:delete] do resources :reviews, only: [:create] From 8d5cd5b412920e0c995ed56d67496903c53f7a3d Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Sun, 5 May 2019 12:06:00 -0700 Subject: [PATCH 099/260] new product form working with OAuth, merchant must be logged in to create a new product --- app/controllers/application_controller.rb | 6 +- app/controllers/products_controller.rb | 3 +- test/controllers/products_controller_test.rb | 58 +++++++++++++++++++- 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8f41082eab..c079fc3e9f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,9 +1,9 @@ class ApplicationController < ActionController::Base private - def find_user - if session[:user_id] - @login_user = User.find_by(id: session[:user_id]) + def find_merchant + if session[:merchant_id] #if session[:merchant_id] is not nil + @login_merchant = Merchant.find_by(id: session[:merchant_id]) end end end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index c39bdc7a77..d823372033 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -4,7 +4,8 @@ def new end def create - if @login_user # if user is logged in + find_merchant + if @login_merchant # if merchant is logged in product = Product.new(product_params) is_successful = product.save diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index 475a59b0d3..b21afb3506 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -2,13 +2,23 @@ describe ProductsController do describe "index" do - it "should get index" do + it "successfully shows index" do # Act get products_path # Assert must_respond_with :success end + + it "successfully shows index with no products" do + Product.all do |product| + product.destroy + end + + get products_path + + must_respond_with :success + end end describe "show" do @@ -31,4 +41,50 @@ expect(flash[:error]).must_equal "Unknown product" end end + + describe "new" do + it "succeeds" do + get new_product_path + + must_respond_with :success + end + end + + describe "create" do + describe "logged in user" do + it "creates a product with valid data" do + merchant = merchants(:merchant_1) + new_product = {product: {name: "Something amazing", merchant_id: merchant.id, price: 1000}} + expect { + post products_path, params: new_product + }.must_change "Product.count", 1 + + # new_product_id = Product.find_by(name: "Something amazing").id + + # must_respond_with :redirect + # must_redirect_to work_path(new_work_id) + end + end + + # it "renders bad_request and does not update the DB for bogus data" do + # bad_work = {work: {title: nil, category: "book"}} + + # expect { + # post works_path, params: bad_work + # }.wont_change "Work.count" + + # must_respond_with :bad_request + # end + + # it "renders 400 bad_request for bogus categories" do + # INVALID_CATEGORIES.each do |category| + # invalid_work = {work: {title: "Invalid Work", category: category}} + + # proc { post works_path, params: invalid_work }.wont_change "Work.count" + + # Work.find_by(title: "Invalid Work", category: category).must_be_nil + # must_respond_with :bad_request + # end + # end + end end From ee39379ecb5565bf2aa0d4d15509c712c15cfa10 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Sun, 5 May 2019 12:54:39 -0700 Subject: [PATCH 100/260] added more products controller tests and fixed a view on the products form --- app/views/products/_form.html.erb | 4 +- test/controllers/products_controller_test.rb | 69 +++++++++++++------- 2 files changed, 50 insertions(+), 23 deletions(-) diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb index a135632681..70f4399c52 100644 --- a/app/views/products/_form.html.erb +++ b/app/views/products/_form.html.erb @@ -6,7 +6,9 @@ <%= f.text_field :name %> <%= f.label :merchant_id %> - <%= f.text_field :merchant_id %> + <%= f.select :merchant_id, Merchant.where(id: session[:merchant_id]) %> + <%# need help displaying just merchant name %> + <%= f.label :price %> <%= f.text_field :price %> diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index b21afb3506..6aabf86784 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -53,38 +53,63 @@ describe "create" do describe "logged in user" do it "creates a product with valid data" do - merchant = merchants(:merchant_1) + merchant = perform_login new_product = {product: {name: "Something amazing", merchant_id: merchant.id, price: 1000}} expect { post products_path, params: new_product }.must_change "Product.count", 1 - # new_product_id = Product.find_by(name: "Something amazing").id + new_product_id = Product.find_by(name: "Something amazing").id - # must_respond_with :redirect - # must_redirect_to work_path(new_work_id) + must_respond_with :redirect + must_redirect_to product_path(new_product_id) end end - # it "renders bad_request and does not update the DB for bogus data" do - # bad_work = {work: {title: nil, category: "book"}} - - # expect { - # post works_path, params: bad_work - # }.wont_change "Work.count" - - # must_respond_with :bad_request - # end - - # it "renders 400 bad_request for bogus categories" do - # INVALID_CATEGORIES.each do |category| - # invalid_work = {work: {title: "Invalid Work", category: category}} + it "renders bad_request and does not update the DB for bogus data" do + merchant = perform_login + bad_prod_name = {product: {name: nil, merchant_id: merchant.id, price: 1000}} + bad_merch_id = {product: {name: "Awesome product", merchant_id: nil, price: 1000}} + bad_price = {product: {name: "Awesomer product", merchant_id: merchant.id, price: 0}} + + expect { + post products_path, params: bad_prod_name + }.wont_change "Product.count" + + must_respond_with :bad_request + expect(flash[:error]).must_include "Could not add new product" + expect(flash[:error]).must_include "name" + expect(flash[:error]).must_include "can't be blank" + + expect { + post products_path, params: bad_merch_id + }.wont_change "Product.count" + + must_respond_with :bad_request + expect(flash[:error]).must_include "Could not add new product" + expect(flash[:error]).must_include "merchant" + expect(flash[:error]).must_include "must exist" + + expect { + post products_path, params: bad_price + }.wont_change "Product.count" + + must_respond_with :bad_request + expect(flash[:error]).must_include "Could not add new product" + expect(flash[:error]).must_include "must be greater than 0" + end + end - # proc { post works_path, params: invalid_work }.wont_change "Work.count" + describe "logged out user" do + it "cannot create a product with valid data" do + # is setting merchant id to nil enough to test this? + new_product = {product: {name: "Something amazing", merchant_id: nil, price: 1000}} + expect { + post products_path, params: new_product + }.wont_change "Product.count" - # Work.find_by(title: "Invalid Work", category: category).must_be_nil - # must_respond_with :bad_request - # end - # end + must_respond_with :bad_request + expect(flash[:error]).must_equal "You must be logged in to create a new product" + end end end From 2132f98acb04aad9accdaba08d94e68ceaa180fb Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Sun, 5 May 2019 13:12:11 -0700 Subject: [PATCH 101/260] added functionality that user must be logged in to see the new product form, updated tests, refactored perform login in products controller --- app/controllers/products_controller.rb | 10 ++++++++-- test/controllers/products_controller_test.rb | 17 ++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index d823372033..9c5b23d29c 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,10 +1,16 @@ class ProductsController < ApplicationController + before_action :find_merchant, only: [:new, :create] + def new - @product = Product.new + if @login_merchant + @product = Product.new + else + flash[:error] = "You must be logged in to add a new product" + redirect_to root_path + end end def create - find_merchant if @login_merchant # if merchant is logged in product = Product.new(product_params) diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index 6aabf86784..c281bd4f0b 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -43,10 +43,21 @@ end describe "new" do - it "succeeds" do - get new_product_path + describe "logged in merchant" do + it "succeeds" do + perform_login + get new_product_path - must_respond_with :success + must_respond_with :success + end + end + describe "not logged in" do + it "redirects user" do + get new_product_path + + must_respond_with :redirect + expect(flash[:error]).must_equal "You must be logged in to add a new product" + end end end From 25b0ebad09d96c4436e46d09bec5aff7f7580ba9 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Sun, 5 May 2019 13:14:31 -0700 Subject: [PATCH 102/260] added link to add new product to products index view, just a temporary place, I think we'll probably want this on the merchant dash --- app/views/products/index.html.erb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index e308290fdc..b33dc65c18 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,5 +1,7 @@

Products

+<%= link_to "Add new product", new_product_path %> +
    <% @products.each do |product| %>
  • From 2423938f3e77ec2e89f2222d5af882e4aa76d125 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Sun, 5 May 2019 16:14:19 -0700 Subject: [PATCH 103/260] refactor using controller filters --- app/controllers/application_controller.rb | 5 +++++ app/controllers/items_controller.rb | 11 ++++++----- app/controllers/orders_controller.rb | 14 ++++++++++++-- test/controllers/orders_controller_test.rb | 3 +-- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 09705d12ab..3818e64791 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,7 @@ class ApplicationController < ActionController::Base + private + + def find_cart_order + @order = Order.find_by(id: session[:cart_id]) + end end diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index 4d47acd082..88b45e4ba8 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -1,12 +1,13 @@ class ItemsController < ApplicationController + before_action :find_cart_order, only: [:create] + def create # find product and order @product = Product.find_by(id: params[:product_id]) - order = Order.find_by(id: session[:cart_id]) # if no current cart, create order and save to session. - unless order - order = Order.create - session[:cart_id] = order.id + unless @order + @order = Order.create + session[:cart_id] = @order.id end item = Item.new(item_params) # can add more sophesticated logic for checking items quantitiy is available compared to stock. @@ -22,7 +23,7 @@ def create # set up relationships for item @product.items << item - order.items << item + @order.items << item if item.valid? flash[:success] = "#{@product.name} (quantity: #{item.quantity}) Successfully Added To Cart" diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index ca375571c7..09bd8066ae 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,10 +1,10 @@ class OrdersController < ApplicationController + before_action :find_cart_order + def view_cart - @order = Order.find_by(id: session[:cart_id]) end def checkout - @order = Order.find_by(id: session[:cart_id]) unless @order flash[:error] = "Unable to checkout cart" redirect_to cart_path @@ -12,5 +12,15 @@ def checkout end def purchase + unless @order + flash[:error] = "Unable to checkout cart" + redirect_to cart_path + end + end + + private + + def find_cart_order + @order = Order.find_by(id: session[:cart_id]) end end diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 1c9a379d1c..d3dc03601a 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -17,9 +17,8 @@ expect(session[:cart_id]).wont_be_nil end end - - describe "checkout" do + describe "checkout" do let(:product) { products(:product_1) } let(:item_params) { { item: { quantity: 2 } } } it "will respond with success if cart stored in session" do From d7af187e535de4fb2329e3f63f3ef9a3a9fc6531 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Mon, 6 May 2019 00:04:22 -0700 Subject: [PATCH 104/260] updated items crate action to find items that have already been added to cart and increase if selected again, updated tests as well --- app/controllers/items_controller.rb | 8 +++++++- app/controllers/orders_controller.rb | 11 ++++++++--- app/models/item.rb | 1 + test/controllers/items_controller_test.rb | 18 +++++++++++++++++- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index 88b45e4ba8..b1764fd622 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -9,8 +9,14 @@ def create @order = Order.create session[:cart_id] = @order.id end + # finds item in cart if already present and increments quantity (required for easy checkout) + item = @order.items.find_by(product_id: @product.id) if @product + if item + item.quantity += params[:item][:quantity].to_i + else + item = Item.new(item_params) + end - item = Item.new(item_params) # can add more sophesticated logic for checking items quantitiy is available compared to stock. if !@product flash.now[:error] = "Could Not Add To Cart: product not available" redirect_to products_path diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 09bd8066ae..1d4241831e 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -12,7 +12,12 @@ def checkout end def purchase - unless @order + if @order + @order.update(order_params) + if @order.valid? + end + @order.status = complete + else flash[:error] = "Unable to checkout cart" redirect_to cart_path end @@ -20,7 +25,7 @@ def purchase private - def find_cart_order - @order = Order.find_by(id: session[:cart_id]) + def order_params + params.require(:order).permit(:shopper_name, :shopper_email, :shopper_address, :cc_four, :cc_exp) end end diff --git a/app/models/item.rb b/app/models/item.rb index e97ba89bcd..4d9304bc38 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -8,4 +8,5 @@ class Item < ApplicationRecord def subtotal return quantity * product.price / 100.0 end + end diff --git a/test/controllers/items_controller_test.rb b/test/controllers/items_controller_test.rb index 8a2d8feff4..a726b408cc 100644 --- a/test/controllers/items_controller_test.rb +++ b/test/controllers/items_controller_test.rb @@ -28,7 +28,7 @@ it "will use current order if cart_id in session " do expect { - post product_items_path(product.id), params: item_params + post product_items_path(products(:product_2)), params: item_params }.must_change "Order.count", 1 expect { @@ -64,6 +64,22 @@ must_respond_with :bad_request end + it "will find an item if already created and increase its quantity rather than make new" do + expect { + post product_items_path(product.id), params: item_params + }.must_change "Item.count", 1 + + item = Item.find_by(product_id: product.id, order_id: session[:cart_id]) + expect(item.quantity).must_equal item_params[:item][:quantity] + + expect { + post product_items_path(product.id), params: item_params + }.must_change "Item.count", 0 + + item = Item.find_by(product_id: product.id, order_id: session[:cart_id]) + expect(item.quantity).must_equal item_params[:item][:quantity] * 2 + end + it "will not create an item with in invalid quantity" do item_params[:item][:quantity] = nil expect { From a25ddfe07232493cc2d94dd8e8ec885cc38c9f02 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Mon, 6 May 2019 00:21:12 -0700 Subject: [PATCH 105/260] added cart_errors custom method to order, available_for_purchase? custom method to item --- app/controllers/orders_controller.rb | 2 +- app/models/item.rb | 5 +++++ app/models/order.rb | 10 ++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 1d4241831e..531e86201b 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -15,8 +15,8 @@ def purchase if @order @order.update(order_params) if @order.valid? + @order.status = complete end - @order.status = complete else flash[:error] = "Unable to checkout cart" redirect_to cart_path diff --git a/app/models/item.rb b/app/models/item.rb index 4d9304bc38..f4c760c806 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -9,4 +9,9 @@ def subtotal return quantity * product.price / 100.0 end + # checks if item is are available w/ quantity selecged when checking out incase another person + # has checked out product since current item was placed in cart. + def available_for_purchase? + return item.quantity <= product.stock + end end diff --git a/app/models/order.rb b/app/models/order.rb index ab05e0a2c9..1195c442e4 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -7,4 +7,14 @@ def total item.subtotal end.sum end + + def cart_errors + cart_errors = [] + items.each do |item| + unless item.available_for_purchase? + cart_errors << item + end + end + return cart_errors + end end From 7c48a2719f675cf2023e119725bcff8e3f2771eb Mon Sep 17 00:00:00 2001 From: qqdipps Date: Mon, 6 May 2019 02:32:50 -0700 Subject: [PATCH 106/260] testing upto date for purchase action --- app/controllers/orders_controller.rb | 21 ++-- app/models/item.rb | 7 +- app/models/order.rb | 7 ++ app/models/product.rb | 5 + app/views/orders/_order_form.html.erb | 14 +-- test/controllers/orders_controller_test.rb | 118 +++++++++++++++++++++ test/fixtures/orders.yml | 2 + 7 files changed, 160 insertions(+), 14 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 531e86201b..f0aeca509c 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -12,20 +12,29 @@ def checkout end def purchase - if @order - @order.update(order_params) - if @order.valid? - @order.status = complete - end + if @order && @order.update(order_params) && @order.cart_errors.empty? + @order.cart_checkout + @order.update(status: "complete", cc_four: params[:order][:cc_all][-4..-1]) # front end valid. on form for min 4 chars + session[:cart_id] = nil + flash[:success] = "Purchase Successful" + redirect_to cart_path # temp will change to confirmation page. else flash[:error] = "Unable to checkout cart" + if @order.cart_errors.any? + cart_errors = [] + @order.cart_errors.each do |item| + cart_errors << "#{item.product.name} available stock is #{item.product.stock}." + end + flash["Item exceeds available stock:"] = cart_errors + end redirect_to cart_path end end private + # only partial params, update if more attributes are required. def order_params - params.require(:order).permit(:shopper_name, :shopper_email, :shopper_address, :cc_four, :cc_exp) + params.require(:order).permit(:shopper_name, :shopper_email, :shopper_address, :cc_exp) end end diff --git a/app/models/item.rb b/app/models/item.rb index f4c760c806..658a09ac6a 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -12,6 +12,11 @@ def subtotal # checks if item is are available w/ quantity selecged when checking out incase another person # has checked out product since current item was placed in cart. def available_for_purchase? - return item.quantity <= product.stock + return quantity <= product.stock + end + + def purchase + product.decrease_stock(quantity) + return true end end diff --git a/app/models/order.rb b/app/models/order.rb index 1195c442e4..b71ac2670f 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -17,4 +17,11 @@ def cart_errors end return cart_errors end + + def cart_checkout + items.each do |item| + item.purchase + end + return true + end end diff --git a/app/models/product.rb b/app/models/product.rb index f73c5ab3d3..be4e77b6b1 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -7,4 +7,9 @@ class Product < ApplicationRecord validates :name, presence: true, uniqueness: true validates :price, presence: true validates_numericality_of :price, greater_than: 0 + + def decrease_stock(quantity) + self.stock = self.stock - quantity + return self.save + end end diff --git a/app/views/orders/_order_form.html.erb b/app/views/orders/_order_form.html.erb index 54e6039313..36edb7791f 100644 --- a/app/views/orders/_order_form.html.erb +++ b/app/views/orders/_order_form.html.erb @@ -32,33 +32,33 @@
    <%=f.label "Name on Credit Card"%> - <%=f.text_field :shopper_name, class: "form-control"%> + <%=f.text_field :shopper_name, required: true, class: "form-control"%>
    <%=f.label "Email Address" %> - <%=f.email_field :shopper_email, class: "form-control" %> + <%=f.email_field :shopper_email, required: true, class: "form-control" %>
    <%=f.label "Mailing Address"%> - <%=f.text_field :shopper_address, class: "form-control"%> + <%=f.text_field :shopper_address, required: true, class: "form-control"%>
    <%=f.label "Credit Card Number" %> - <%=f.text_field :cc_all, class: "form-control"%> + <%=f.text_field :cc_all, required: true, minlength: 4 , class: "form-control"%>
    <%=f.label "Credit cart expiration"%> - <%=f.date_field :cc_exp, class: "form-control"%> + <%=f.date_field :cc_exp, required: true, class: "form-control"%>
    <%=f.label "Credit Card CVV (security code)"%> - <%=f.text_field :cvv , class: "form-control"%> + <%=f.text_field :cvv , required: true, class: "form-control"%>
    <%=f.label "Billing zip code"%> - <%=f.text_field :zip, class: "form-control"%> + <%=f.text_field :zip, required: true, class: "form-control"%>
    diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index d3dc03601a..6bbe0b0f3c 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -36,4 +36,122 @@ expect(session[:cart_id]).must_be_nil end end + + describe "purchase" do + let(:product) { products(:product_1) } + let(:product2) { products(:product_2) } + let(:item_params) { { item: { quantity: 2 } } } + let(:cart_params) { + { order: { shopper_name: "susie", + shopper_email: "dalmation@susy.org", + shopper_address: "4455 mailing address", + cc_all: "234443434", + cc_exp: "03022020" } } + } + before do + post product_items_path(product.id), params: item_params + post product_items_path(product2.id), params: item_params + end + it "will set cart in srssion to nil if valid cart purchase" do + expect(session[:cart_id]).wont_be_nil + + expect { + post purchase_cart_path, params: cart_params + }.wont_change "Order.count" + + expect(session[:cart_id]).must_be_nil + end + + it "will change order status from pending to complete if valid cart purchase" do + order = Order.find_by(id: session[:cart_id]) + expect(order.status).must_equal "pending" + + expect { + post purchase_cart_path, params: cart_params + }.wont_change "Order.count" + order.reload + expect(order.status).must_equal "complete" + end + + it "will change product stock by amount bought if valid cart purchase " do + product_stock = product.stock + product2.stock + + expect { + post purchase_cart_path, params: cart_params + }.wont_change "Order.count" + product.reload + product2.reload + expect(product_stock - 4).must_equal product.stock + product2.stock + end + + it "will have flash message and redirect to correct page if valid cart purchase" do + expect { + post purchase_cart_path, params: cart_params + }.wont_change "Order.count" + + expect(flash[:success]).must_equal "Purchase Successful" + must_respond_with :redirect + must_redirect_to cart_path + end + + describe "checking out will an invalid cart" do + let(:product) { products(:product_1) } + let(:product2) { products(:product_2) } + let(:item_params) { { item: { quantity: 2 } } } + let(:cart_params) { + { order: { shopper_name: "susie", + shopper_email: "dalmation@susy.org", + shopper_address: "4455 mailing address", + cc_all: "234443434", + cc_exp: "03022020" } } + } + before do + product.update(stock: 1) + post product_items_path(product.id), params: item_params + post product_items_path(product2.id), params: item_params + end + + it "will have flash message and redirect to correct page if invalid cart purchase" do + expect { + post purchase_cart_path, params: cart_params + }.wont_change "Order.count" + + expect(flash[:error]).must_equal "Unable to checkout cart" + expect(flash["Item exceeds available stock:"]).must_equal ["bucket of rain available stock is 1."] + must_respond_with :redirect + must_redirect_to cart_path + end + + it "will not change order status if invalid cart" do + order = Order.find_by(id: session[:cart_id]) + expect(order.status).must_equal "pending" + + expect { + post purchase_cart_path, params: cart_params + }.wont_change "Order.count" + + expect(order.status).must_equal "pending" + end + + it "will not change product stock if invalid cart" do + product_stock = product.stock + product2.stock + + expect { + post purchase_cart_path, params: cart_params + }.wont_change "Order.count" + + product.reload + product2.reload + expect(product_stock).must_equal product.stock + product2.stock + end + + it "will not change cart in session if invalid cart" do + expect(session[:cart_id]).wont_be_nil + expect { + post purchase_cart_path, params: cart_params + }.wont_change "Order.count" + expect(session[:cart_id]).wont_be_nil + end + end + end end diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index 406bbec035..f8f99ffe39 100644 --- a/test/fixtures/orders.yml +++ b/test/fixtures/orders.yml @@ -15,3 +15,5 @@ order_2: shopper_address: 43244 tryagain address cc_four: 2534 cc_exp: 09092020 + + From 2eff8f59736eee977d20ab8307601d2bddc74f7a Mon Sep 17 00:00:00 2001 From: qqdipps Date: Mon, 6 May 2019 08:18:58 -0700 Subject: [PATCH 107/260] fixed status to paid from complete --- app/controllers/orders_controller.rb | 2 +- test/controllers/orders_controller_test.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index f0aeca509c..bd787534d7 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -14,7 +14,7 @@ def checkout def purchase if @order && @order.update(order_params) && @order.cart_errors.empty? @order.cart_checkout - @order.update(status: "complete", cc_four: params[:order][:cc_all][-4..-1]) # front end valid. on form for min 4 chars + @order.update(status: "paid", cc_four: params[:order][:cc_all][-4..-1]) # front end valid. on form for min 4 chars session[:cart_id] = nil flash[:success] = "Purchase Successful" redirect_to cart_path # temp will change to confirmation page. diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 6bbe0b0f3c..2f5b59df33 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -62,7 +62,7 @@ expect(session[:cart_id]).must_be_nil end - it "will change order status from pending to complete if valid cart purchase" do + it "will change order status from pending to paid if valid cart purchase" do order = Order.find_by(id: session[:cart_id]) expect(order.status).must_equal "pending" @@ -70,7 +70,7 @@ post purchase_cart_path, params: cart_params }.wont_change "Order.count" order.reload - expect(order.status).must_equal "complete" + expect(order.status).must_equal "paid" end it "will change product stock by amount bought if valid cart purchase " do From 0aaec06fd4d2bdfb1184688c06018863759b442b Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Mon, 6 May 2019 11:43:49 -0700 Subject: [PATCH 108/260] debugged creating new product, updated tests, made form accept dollars instewad of cents --- app/controllers/products_controller.rb | 18 ++++++---- app/views/products/_form.html.erb | 16 ++++----- app/views/products/new.html.erb | 2 +- test/controllers/products_controller_test.rb | 38 ++++++-------------- 4 files changed, 30 insertions(+), 44 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 9c5b23d29c..030e626843 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -3,7 +3,7 @@ class ProductsController < ApplicationController def new if @login_merchant - @product = Product.new + @product = Product.new(photo_url: "http://placekitten.com/200/300") else flash[:error] = "You must be logged in to add a new product" redirect_to root_path @@ -12,15 +12,21 @@ def new def create if @login_merchant # if merchant is logged in - product = Product.new(product_params) - - is_successful = product.save + @product = Product.new(product_params) + @product.merchant_id = session[:merchant_id] + @product.price = params[:product][:price].to_f * 100.0 + # raise + is_successful = @product.save if is_successful flash[:success] = "Product added successfully" - redirect_to product_path(product.id) + redirect_to product_path(@product.id) else - flash.now[:error] = "Could not add new product: #{product.errors.messages}" #need help formatting this flash better + # raise + flash.now[:error] = "Could not add new product:" #need help formatting this flash better + @product.errors.messages.each do |label, message| + flash.now[label.to_sym] = message + end render :new, status: :bad_request end else diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb index 70f4399c52..ae72542c45 100644 --- a/app/views/products/_form.html.erb +++ b/app/views/products/_form.html.erb @@ -3,27 +3,23 @@

    <%= intro_text %>

    <%= f.label :name %> - <%= f.text_field :name %> - - <%= f.label :merchant_id %> - <%= f.select :merchant_id, Merchant.where(id: session[:merchant_id]) %> - <%# need help displaying just merchant name %> - + <%= f.text_field :name, required: true %> <%= f.label :price %> - <%= f.text_field :price %> + <%= f.number_field :price, in: 1.0..1000.0, step: 0.01, required: true %> <%= f.label :categories %> <%= collection_check_boxes(:product, :category_ids, Category.all, :id, :name) %> <%= f.label :description %> - <%= f.text_field :description %> + <%= f.text_field :description, required: true %> + <%= f.label :photo_url %> - <%= f.text_field :photo_url %> + <%= f.text_field :photo_url, required: true %> <%= f.label :stock %> - <%= f.text_field :stock %> + <%= f.text_field :stock, required: true %> <%= f.submit action_name, class: "product-form__submit-btn" %> diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index ff9d657d6d..8ff5f5e23e 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -5,4 +5,4 @@ form_class: "new-product", intro_text: "Use this form to create a new product", action_name: "Create product" -} %> \ No newline at end of file +} %> diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index c281bd4f0b..7abb2b93b5 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -11,9 +11,12 @@ end it "successfully shows index with no products" do - Product.all do |product| - product.destroy - end + # Product.all do |product| + # product.destroy + # end + Item.destroy_all + Review.destroy_all + Product.destroy_all get products_path @@ -65,13 +68,14 @@ describe "logged in user" do it "creates a product with valid data" do merchant = perform_login - new_product = {product: {name: "Something amazing", merchant_id: merchant.id, price: 1000}} + new_product = {product: {name: "Something amazing", price: 1000}} expect { post products_path, params: new_product }.must_change "Product.count", 1 new_product_id = Product.find_by(name: "Something amazing").id + expect(flash[:success]).must_equal "Product added successfully" must_respond_with :redirect must_redirect_to product_path(new_product_id) end @@ -79,9 +83,7 @@ it "renders bad_request and does not update the DB for bogus data" do merchant = perform_login - bad_prod_name = {product: {name: nil, merchant_id: merchant.id, price: 1000}} - bad_merch_id = {product: {name: "Awesome product", merchant_id: nil, price: 1000}} - bad_price = {product: {name: "Awesomer product", merchant_id: merchant.id, price: 0}} + bad_prod_name = {product: {name: nil, price: 1000}} expect { post products_path, params: bad_prod_name @@ -89,32 +91,14 @@ must_respond_with :bad_request expect(flash[:error]).must_include "Could not add new product" - expect(flash[:error]).must_include "name" - expect(flash[:error]).must_include "can't be blank" - - expect { - post products_path, params: bad_merch_id - }.wont_change "Product.count" - - must_respond_with :bad_request - expect(flash[:error]).must_include "Could not add new product" - expect(flash[:error]).must_include "merchant" - expect(flash[:error]).must_include "must exist" - - expect { - post products_path, params: bad_price - }.wont_change "Product.count" - - must_respond_with :bad_request - expect(flash[:error]).must_include "Could not add new product" - expect(flash[:error]).must_include "must be greater than 0" + expect(flash[:name]).must_include "can't be blank" end end describe "logged out user" do it "cannot create a product with valid data" do # is setting merchant id to nil enough to test this? - new_product = {product: {name: "Something amazing", merchant_id: nil, price: 1000}} + new_product = {product: {name: "Something amazing", price: 1000}} expect { post products_path, params: new_product }.wont_change "Product.count" From e6f00579fe9e3cf349a774a638794c6191af5728 Mon Sep 17 00:00:00 2001 From: Sav <41908878+qqdipps@users.noreply.github.com> Date: Mon, 6 May 2019 11:46:45 -0700 Subject: [PATCH 109/260] Update application_controller.rb --- app/controllers/application_controller.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index fabd675026..57e10f8218 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -4,9 +4,10 @@ class ApplicationController < ActionController::Base def find_merchant if session[:merchant_id] #if session[:merchant_id] is not nil @login_merchant = Merchant.find_by(id: session[:merchant_id]) + end + end def find_cart_order @order = Order.find_by(id: session[:cart_id]) - end end From 8fd0dffe9f03b5bb01fdc3ec96014e9f558a0f65 Mon Sep 17 00:00:00 2001 From: Cloudy Lopez Date: Mon, 6 May 2019 13:07:43 -0700 Subject: [PATCH 110/260] resolved issue in csv file. --- db/products_data.csv | 2 +- db/seeds.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db/products_data.csv b/db/products_data.csv index 53692feda9..80cb336517 100644 --- a/db/products_data.csv +++ b/db/products_data.csv @@ -1,4 +1,4 @@ -yname,price,description,photo_url,stock +name,price,description,photo_url,stock high fives,3990,They’ve got as much sex appeal as a road accident.,https://placekitten.com/g/200/300,9 cup of sunshine,4277,"But Mr. Dent, the plans have been available in the local planning office for the last nine months.",https://placekitten.com/g/200/300,5 bucket of sunshine,2089,Don’t Panic,https://placekitten.com/g/200/300,4 diff --git a/db/seeds.rb b/db/seeds.rb index 4fb8b17de3..368105edd8 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -19,7 +19,7 @@ CSV.open("db/products_data.csv", headers: true).each_with_index do |line, i| merchant = Merchant.find(rand(1..Merchant.count)) - product = merchant.products.create(name: line["name"].upcase, + product = merchant.products.create(name: line["name"], #.upcase, price: line["price"], description: line["description"], photo_url: line["photo_url"], From d4b4cdafa300fb1da5b9db1f7dfbc3a7fb2795f5 Mon Sep 17 00:00:00 2001 From: Cloudy Lopez Date: Mon, 6 May 2019 13:16:44 -0700 Subject: [PATCH 111/260] merge conflict --- test/models/order_test.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/models/order_test.rb b/test/models/order_test.rb index 858be77532..e2b76eb806 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -18,10 +18,6 @@ expect(order.items.count).must_equal 2 end end -<<<<<<< HEAD - - -======= it "can shovel items to create a relationship" do product = products(:product_1) @@ -32,4 +28,3 @@ expect(order.items.include?(item)).must_equal true end end ->>>>>>> 82c771ed70176d23b8316c710d96bf76ee0dd019 From c21bd5e736b83fc8a942d6a20eaf22cdaa270a2f Mon Sep 17 00:00:00 2001 From: Cloudy Lopez Date: Mon, 6 May 2019 13:21:37 -0700 Subject: [PATCH 112/260] resolved last merge prob --- db/seeds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/seeds.rb b/db/seeds.rb index 368105edd8..4fb8b17de3 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -19,7 +19,7 @@ CSV.open("db/products_data.csv", headers: true).each_with_index do |line, i| merchant = Merchant.find(rand(1..Merchant.count)) - product = merchant.products.create(name: line["name"], #.upcase, + product = merchant.products.create(name: line["name"].upcase, price: line["price"], description: line["description"], photo_url: line["photo_url"], From e5b86765dd3000b76d1b31ed5c5b568d17333b46 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Mon, 6 May 2019 13:36:56 -0700 Subject: [PATCH 113/260] added edit and update actions and edit view --- app/controllers/products_controller.rb | 25 ++++++++++++++++++++++--- app/views/products/edit.html.erb | 8 ++++++-- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 030e626843..bef6e734f8 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -15,15 +15,13 @@ def create @product = Product.new(product_params) @product.merchant_id = session[:merchant_id] @product.price = params[:product][:price].to_f * 100.0 - # raise is_successful = @product.save if is_successful flash[:success] = "Product added successfully" redirect_to product_path(@product.id) else - # raise - flash.now[:error] = "Could not add new product:" #need help formatting this flash better + flash.now[:error] = "Could not add new product:" @product.errors.messages.each do |label, message| flash.now[label.to_sym] = message end @@ -49,9 +47,30 @@ def show end def edit + @product = Product.find_by(id: params[:id]) + @product.price = @product.price.to_f / 100.0 + + if @product.nil? + flash[:error] = "Unknown product" + redirect_to products_path + end end def update + @product = Product.find_by(id: params[:id]) + @product.update(product_params) + @product.price = product_params[:price].to_f * 100.0 + @product.save + + if @product.valid? + flash[:success] = "Product updated successfully" + redirect_to product_path(@product.id) + else + @product.errors.messages.each do |label, message| + flash.now[label.to_sym] = message + end + render :edit, status: :bad_request + end end private diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb index 279b066f30..24968cc0fa 100644 --- a/app/views/products/edit.html.erb +++ b/app/views/products/edit.html.erb @@ -1,2 +1,6 @@ -

    Products#edit

    -

    Find me in app/views/products/edit.html.erb

    +<%= render partial: "form", locals: { + form_class: "edit-product", + intro_text: "Use this form to edit a product", + action_name: "Edit product" +} %> + From fbb3f97bf2dd1e79efae13ad9ba15491a96b02cd Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Mon, 6 May 2019 13:57:37 -0700 Subject: [PATCH 114/260] added tests for edit --- app/controllers/products_controller.rb | 15 ++-- test/controllers/products_controller_test.rb | 82 +++++++++++++++----- 2 files changed, 74 insertions(+), 23 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index bef6e734f8..3a7cb5112d 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -47,12 +47,17 @@ def show end def edit - @product = Product.find_by(id: params[:id]) - @product.price = @product.price.to_f / 100.0 + if @login_merchant + @product = Product.find_by(id: params[:id]) + @product.price = @product.price.to_f / 100.0 - if @product.nil? - flash[:error] = "Unknown product" - redirect_to products_path + if @product.nil? + flash[:error] = "Unknown product" + redirect_to products_path + end + else + flash[:error] = "You must be logged in to edit product" + redirect_to root_path end end diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index 7abb2b93b5..0035824287 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -79,32 +79,78 @@ must_respond_with :redirect must_redirect_to product_path(new_product_id) end + + it "renders bad_request and does not update the DB for bogus data" do + merchant = perform_login + bad_prod_name = {product: {name: nil, price: 1000}} + + expect { + post products_path, params: bad_prod_name + }.wont_change "Product.count" + + must_respond_with :bad_request + expect(flash[:error]).must_include "Could not add new product" + expect(flash[:name]).must_include "can't be blank" + end + + describe "logged out user" do + it "cannot create a product with valid data" do + # is setting merchant id to nil enough to test this? + new_product = {product: {name: "Something amazing", price: 1000}} + expect { + post products_path, params: new_product + }.wont_change "Product.count" + + must_respond_with :bad_request + expect(flash[:error]).must_equal "You must be logged in to create a new product" + end + end + end + end + + describe "edit" do + describe "logged in merchant" do + it "succeeds" do + merchant = perform_login + + get edit_product_path(merchant.products.first.id) + + must_respond_with :found + end + + it "will redirect if given an invalid product id" do + merchant = perform_login + + get edit_product_path(-1) + + must_respond_with :redirect + end end + describe "not logged in" do + it "redirects user" do + merchant = perform_login - it "renders bad_request and does not update the DB for bogus data" do - merchant = perform_login - bad_prod_name = {product: {name: nil, price: 1000}} + delete logout_path - expect { - post products_path, params: bad_prod_name - }.wont_change "Product.count" + get edit_product_path(merchant.products.first.id) - must_respond_with :bad_request - expect(flash[:error]).must_include "Could not add new product" - expect(flash[:name]).must_include "can't be blank" + must_respond_with :redirect + expect(flash[:error]).must_equal "You must be logged in to edit product" + end end end - describe "logged out user" do - it "cannot create a product with valid data" do - # is setting merchant id to nil enough to test this? - new_product = {product: {name: "Something amazing", price: 1000}} - expect { - post products_path, params: new_product - }.wont_change "Product.count" + describe "update" do + describe "logged in merchant" do + it "will update an existing product" do + end + + it "will not update an existing product if given bogus data" do + end + end - must_respond_with :bad_request - expect(flash[:error]).must_equal "You must be logged in to create a new product" + describe "not logged in" do + # do I even need to test this since they can't get to this page? end end end From e92de0a8ebc4c942068e2c5cf7a34e32e510ac31 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Mon, 6 May 2019 14:19:50 -0700 Subject: [PATCH 115/260] added functionality so merchants can only edit their own products --- app/controllers/products_controller.rb | 43 +++++++++++++------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 3a7cb5112d..5533ca08f6 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,5 +1,5 @@ class ProductsController < ApplicationController - before_action :find_merchant, only: [:new, :create] + before_action :find_merchant, only: [:new, :create, :update] def new if @login_merchant @@ -47,34 +47,35 @@ def show end def edit - if @login_merchant - @product = Product.find_by(id: params[:id]) - @product.price = @product.price.to_f / 100.0 + @product = Product.find_by(id: params[:id]) + @product.price = @product.price.to_f / 100.0 - if @product.nil? - flash[:error] = "Unknown product" - redirect_to products_path - end - else - flash[:error] = "You must be logged in to edit product" - redirect_to root_path + if @product.nil? + flash[:error] = "Unknown product" + redirect_to products_path end end def update @product = Product.find_by(id: params[:id]) - @product.update(product_params) - @product.price = product_params[:price].to_f * 100.0 - @product.save + # raise + if @product.merchant_id == @login_merchant.id + @product.update(product_params) + @product.price = product_params[:price].to_f * 100.0 + @product.save - if @product.valid? - flash[:success] = "Product updated successfully" - redirect_to product_path(@product.id) - else - @product.errors.messages.each do |label, message| - flash.now[label.to_sym] = message + if @product.valid? + flash[:success] = "Product updated successfully" + redirect_to product_path(@product.id) + else + @product.errors.messages.each do |label, message| + flash.now[label.to_sym] = message + end + render :edit, status: :bad_request end - render :edit, status: :bad_request + else + flash[:error] = "You can only update your own products" + redirect_to products_path end end From 32a803b962b6ce71729f78c18f84d026adb9c933 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Mon, 6 May 2019 14:22:36 -0700 Subject: [PATCH 116/260] added photo to product show page --- app/views/products/show.html.erb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 1d8b3b7d9d..9ad4f11d6f 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -2,6 +2,8 @@ Product Name: <%= @product.name %> +<%= image_tag @product.photo_url, alt: "Image of the product" %> +

    Price: $ <%= "%.2f" % (@product.price / 100.0) %>

    @@ -58,5 +60,4 @@ <%= render "/items/item_form"%>
- <%= link_to "Back to all products", products_path %> From bb456aef4c0fcd13d2c0f03e7e68ea746dcca392 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Mon, 6 May 2019 14:26:49 -0700 Subject: [PATCH 117/260] updated functionality so users must be logged in to see edit page --- app/controllers/products_controller.rb | 13 +++++++++---- test/controllers/products_controller_test.rb | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 5533ca08f6..134772db4b 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -47,11 +47,16 @@ def show end def edit - @product = Product.find_by(id: params[:id]) - @product.price = @product.price.to_f / 100.0 + if @login_merchant + @product = Product.find_by(id: params[:id]) + @product.price = @product.price.to_f / 100.0 - if @product.nil? - flash[:error] = "Unknown product" + if @product.nil? + flash[:error] = "Unknown product" + redirect_to products_path + end + else + flash[:error] = "You must be logged in to edit a product" redirect_to products_path end end diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index 0035824287..dd20798c83 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -135,7 +135,7 @@ get edit_product_path(merchant.products.first.id) must_respond_with :redirect - expect(flash[:error]).must_equal "You must be logged in to edit product" + expect(flash[:error]).must_equal "You must be logged in to edit a product" end end end From cdb782db5e06b4d16d8e8fade340c05dbc82ce18 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Mon, 6 May 2019 14:28:25 -0700 Subject: [PATCH 118/260] finished model testing products --- test/fixtures/items.yml | 6 ++++ test/models/product_test.rb | 70 +++++++++++++++++-------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/test/fixtures/items.yml b/test/fixtures/items.yml index 90c083239c..5d5928f8ca 100644 --- a/test/fixtures/items.yml +++ b/test/fixtures/items.yml @@ -9,3 +9,9 @@ item_2: quantity: 3 order: order_1 product: product_2 + +item_3: + quantity: 3 + order: order_2 + product: product_2 + diff --git a/test/models/product_test.rb b/test/models/product_test.rb index 6cad57dd1b..773e428bc2 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -10,94 +10,88 @@ describe "validations" do it "will not be valid if missing name" do product.name = nil - expect(product.valid?).must_equal false - expect(product.errors.include?(:name)).must_equal true + expect(product.valid?).must_equal false + expect(product.errors.include?(:name)).must_equal true expect(product.errors.messages[:name]).must_equal ["can't be blank"] end it "will not be valid if name is not unique" do - product_dupe = Product.new(name: product.name, - price: 222, - merchant: merchants(:merchant_1)) + product_dupe = Product.new(name: product.name, + price: 222, + merchant: merchants(:merchant_1)) expect(product_dupe.valid?).must_equal false - expect(product_dupe.errors.include?(:name)).must_equal true + expect(product_dupe.errors.include?(:name)).must_equal true expect(product_dupe.errors.messages[:name]).must_equal ["has already been taken"] - - # p product_dupe.errors end it "will not be valid if missing price" do product.price = nil expect(product.valid?).must_equal false - expect(product.errors.include?(:price)).must_equal true + expect(product.errors.include?(:price)).must_equal true expect(product.errors.messages[:price]).must_equal ["can't be blank", "is not a number"] end it "will not be valid if price is zero" do product.price = 0 expect(product.valid?).must_equal false - expect(product.errors.include?(:price)).must_equal true + expect(product.errors.include?(:price)).must_equal true expect(product.errors.messages[:price]).must_equal ["must be greater than 0"] end it "will not be valid if price is less than zero" do product.price = -1 expect(product.valid?).must_equal false - expect(product.errors.include?(:price)).must_equal true + expect(product.errors.include?(:price)).must_equal true expect(product.errors.messages[:price]).must_equal ["must be greater than 0"] end end - + describe "relationships" do describe "relationship with merchant" do it "will belong to a merchant" do - # expect(product.merchant).must_equal + expect(product.merchant).must_equal merchants(:merchant_2) end end describe "relationship with categories" do - it "can have 0 reviews" do - # product.categories << categories(:product_1) - # product.categories << categories(:product_2) - # expect(product.categories.include?(categories(:product_1))).must_equal true - # expect(product.categories.include?(categories(:product_2))).must_equal true - # expect(product(:product_1).product.include?(product)).must_equal true + it "can have 0 categories" do + expect(product.categories).must_equal [] end - it "can have 1 or many reviews" do - + it "can have 1 or many categories" do + product.categories << categories(:category_1) + product.categories << categories(:category_2) + expect(product.categories.include?(categories(:category_1))).must_equal true + expect(product.categories.include?(categories(:category_2))).must_equal true + expect(categories(:category_2).products.include?(product)).must_equal true end end describe "relationship with reviews" do it "can have 0 reviews" do - + product = products(:product_2) + expect(product.reviews).must_equal [] end - it "can have 1 or many reviews" do - + it "can have 1 or many reviews" do + expect(product.reviews.include?(reviews(:review_1))).must_equal true + expect(product.reviews.include?(reviews(:review_2))).must_equal true + expect(reviews(:review_2).product).must_equal product end end describe "relationship with items" do - it "can have 0 items" do - + product = products(:product_3) + expect(product.items).must_equal [] end - it "can have 1 or many items" do - + it "can have 1 or many items" do + product = products(:product_2) + expect(product.items.include?(items(:item_2))).must_equal true + expect(product.items.include?(items(:item_3))).must_equal true + expect(items(:item_3).product).must_equal product end end end end - - -# # belongs_to :merchant -# # has_and_belongs_to_many :categories -# # has_many :reviews -# # has_many :items - -# # validates :name, presence: true, uniqueness: true -# # validates :price, presence: true -# # validates_numericality_of :price, greater_than: 0 \ No newline at end of file From 711f6626f510d988e0cc441d6a53d2c09a9df26f Mon Sep 17 00:00:00 2001 From: qqdipps Date: Mon, 6 May 2019 14:35:49 -0700 Subject: [PATCH 119/260] tested changes to schema for order validations on status --- test/models/order_test.rb | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/test/models/order_test.rb b/test/models/order_test.rb index e2b76eb806..4e01a54c7c 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -7,19 +7,38 @@ expect(order.valid?).must_equal true end -# has_many :items -describe "relationship with an order" do - it "can have 0 items" do - Item.destroy_all - expect(order.items.count).must_equal 0 + describe "validations" do + it "has a default value of 'pending'" do + order = Order.new + expect(order.status).must_equal "pending" + end + + it "will be valid if given status of [\"pending\", \"paid\", \"complete\", \"cancelled\"]" do + ["pending", "paid", "complete", "cancelled"].each do |status| + order.update(status: status) + expect(order.valid?).must_equal true + end + end + + it "will not be valid if status is different from above" do + ["penddding", "paiad", "compledte", "cancnelled"].each do |status| + order.update(status: status) + expect(order.valid?).must_equal false + end + end end + describe "relationship with an order" do + it "can have 0 items" do + Item.destroy_all + expect(order.items.count).must_equal 0 + end - it "can have 1 or more items" do - expect(order.items.count).must_equal 2 + it "can have 1 or more items" do + expect(order.items.count).must_equal 2 + end end -end - -it "can shovel items to create a relationship" do + + it "can shovel items to create a relationship" do product = products(:product_1) item = Item.new(quantity: 3, product: product) expect(item.valid?).must_equal false From afb46cb08286905354a2c0d1b609da471e14ee9d Mon Sep 17 00:00:00 2001 From: qqdipps Date: Mon, 6 May 2019 15:00:46 -0700 Subject: [PATCH 120/260] added custom method tests, updated validations on stock, added tests for that too --- app/models/product.rb | 4 +++- test/models/product_test.rb | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/app/models/product.rb b/app/models/product.rb index be4e77b6b1..7372bfd8b3 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -6,10 +6,12 @@ class Product < ApplicationRecord validates :name, presence: true, uniqueness: true validates :price, presence: true + validates :stock, presence: true validates_numericality_of :price, greater_than: 0 + validates_numericality_of :stock, greater_than: -1 def decrease_stock(quantity) - self.stock = self.stock - quantity + self.stock -= quantity return self.save end end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index 773e428bc2..5d7fea0592 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -44,6 +44,25 @@ expect(product.errors.include?(:price)).must_equal true expect(product.errors.messages[:price]).must_equal ["must be greater than 0"] end + + it "will not be valid if missing stock" do + product.stock = nil + expect(product.valid?).must_equal false + expect(product.errors.include?(:stock)).must_equal true + expect(product.errors.messages[:stock]).must_equal ["can't be blank", "is not a number"] + end + + it "will be valid if stock is 0" do + product.stock = 0 + expect(product.valid?).must_equal true + end + + it "will not be valid if stock is less than zero" do + product.stock = -2 + expect(product.valid?).must_equal false + expect(product.errors.include?(:stock)).must_equal true + expect(product.errors.messages[:stock]).must_equal ["must be greater than -1"] + end end describe "relationships" do @@ -94,4 +113,25 @@ end end end + + describe "custom methods" do + let(:initial_stock) { product.stock } + describe " def decrease_stock(quantity)" do + it "will decrease the stock of a product by given quantity and return true if valid" do + quantity = 2 + expect(initial_stock).must_equal product.stock + expect(product.decrease_stock(quantity)).must_equal true + expect(initial_stock).wont_equal product.stock + expect(product.stock).must_equal initial_stock - quantity + end + + it "will return false if quantity exceeds stock and not decrease stock" do + quantity = 10 + expect(initial_stock).must_equal product.stock + expect(product.decrease_stock(quantity)).must_equal false + product.reload + expect(initial_stock).must_equal product.stock + end + end + end end From 2cef670fb72bfb3f86a790c8b6eeef0c9cab5cbd Mon Sep 17 00:00:00 2001 From: qqdipps Date: Mon, 6 May 2019 15:20:32 -0700 Subject: [PATCH 121/260] added custom methods testing for item model --- app/models/item.rb | 3 +-- test/models/item_test.rb | 57 +++++++++++++++++++++++++++++++--------- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/app/models/item.rb b/app/models/item.rb index 658a09ac6a..a376b3ec2f 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -16,7 +16,6 @@ def available_for_purchase? end def purchase - product.decrease_stock(quantity) - return true + return product.decrease_stock(quantity) end end diff --git a/test/models/item_test.rb b/test/models/item_test.rb index 2b599e96ac..1717ac3fd4 100644 --- a/test/models/item_test.rb +++ b/test/models/item_test.rb @@ -2,6 +2,7 @@ describe Item do let(:item) { items(:item_1) } + let(:product) { products(:product_1) } it "must be valid" do expect(item.valid?).must_equal true @@ -9,12 +10,12 @@ describe "validations" do it "will not be valid if missing quantity" do - item.quantity = nil - expect(item.valid?).must_equal false - expect(item.errors.include?(:quantity)).must_equal true - expect(item.errors.messages[:quantity]).must_equal ["can't be blank", "is not a number"] + item.quantity = nil + expect(item.valid?).must_equal false + expect(item.errors.include?(:quantity)).must_equal true + expect(item.errors.messages[:quantity]).must_equal ["can't be blank", "is not a number"] end - + it "will not be valid if quantity is zero" do item.quantity = 0 expect(item.valid?).must_equal false @@ -29,7 +30,7 @@ expect(item.errors.messages[:quantity]).must_equal ["must be greater than 0"] end end - + describe "relationships" do describe "relationship with an order" do it "will belong to an order" do @@ -38,14 +39,44 @@ end describe "relationship with an product" do - it "will belong to an product" do + it "will belong to an product" do expect(item.product).must_equal products(:product_1) end end - -end + end + + describe "custom methods" do + describe " def available_for_purchase?" do + it "will return true if the quantity requested is less than stock" do + expect(item.available_for_purchase?).must_equal true + end + + it "will return true if the quantity requested equal to stock" do + item.update(quantity: product.stock) + expect(item.available_for_purchase?).must_equal true + end + + it "will return false if the quantity requested is greater than stock" do + item.update(quantity: product.stock + 1) + expect(item.available_for_purchase?).must_equal false + end + end + describe " def purchase" do + # tests for quantity decrease/not decreasing + # done in product model test, custom methods section. + it "will return true if the quantity requested is less than stock" do + expect(item.purchase).must_equal true + end + + it "will return true if the quantity requested equal to stock" do + item.update(quantity: product.stock) + expect(item.purchase).must_equal true + end + + it "will return false if the quantity requested is greater than stock" do + item.update(quantity: product.stock + 1) + expect(item.purchase).must_equal false + end + end + end end -# belongs_to :order -# belongs_to :product -# validates :quantity, presence: true -# validates_numericality_of :quantity, greater_than: 0 \ No newline at end of file From 2deac5df10c26f05540f47bbc2594a667f56be83 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Mon, 6 May 2019 15:40:08 -0700 Subject: [PATCH 122/260] added missed edge case logic and tests to custom methods in items and proudcts --- app/models/item.rb | 7 +++++-- app/models/product.rb | 1 + test/models/item_test.rb | 36 ++++++++++++++++++++++++++++++++++ test/models/order_test.rb | 39 +++++++++++++++++++++++-------------- test/models/product_test.rb | 6 ++++++ 5 files changed, 72 insertions(+), 17 deletions(-) diff --git a/app/models/item.rb b/app/models/item.rb index a376b3ec2f..e5be7e4c1f 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -6,16 +6,19 @@ class Item < ApplicationRecord validates_numericality_of :quantity, greater_than: 0 def subtotal + return unless self.valid? && self.product.valid? return quantity * product.price / 100.0 end # checks if item is are available w/ quantity selecged when checking out incase another person # has checked out product since current item was placed in cart. def available_for_purchase? - return quantity <= product.stock + return unless self.valid? && self.product.valid? + return self.quantity <= product.stock end def purchase - return product.decrease_stock(quantity) + return unless self.valid? + return product.decrease_stock(self.quantity) end end diff --git a/app/models/product.rb b/app/models/product.rb index 7372bfd8b3..df4ae0c54b 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -11,6 +11,7 @@ class Product < ApplicationRecord validates_numericality_of :stock, greater_than: -1 def decrease_stock(quantity) + return unless self.valid? self.stock -= quantity return self.save end diff --git a/test/models/item_test.rb b/test/models/item_test.rb index 1717ac3fd4..3acd452e6d 100644 --- a/test/models/item_test.rb +++ b/test/models/item_test.rb @@ -46,6 +46,21 @@ end describe "custom methods" do + describe " def subtotal" do + it "will calculate the subtotal of an item given a valid item and product" do + expect(item.subtotal).must_equal item.quantity * product.price / 100.0 + end + + it "will return nil if item is invalid" do + item = Item.new + expect(item.subtotal).must_be_nil + end + + it "will return nil if product assoctiated with item is invalid" do + item.product = Product.new + expect(item.subtotal).must_be_nil + end + end describe " def available_for_purchase?" do it "will return true if the quantity requested is less than stock" do expect(item.available_for_purchase?).must_equal true @@ -60,7 +75,18 @@ item.update(quantity: product.stock + 1) expect(item.available_for_purchase?).must_equal false end + + it "will return nil if item is invalid" do + item = Item.new + expect(item.available_for_purchase?).must_be_nil + end + + it "will return nil if product assoctiated with item is invalid" do + item.product = Product.new + expect(item.available_for_purchase?).must_be_nil + end end + describe " def purchase" do # tests for quantity decrease/not decreasing # done in product model test, custom methods section. @@ -77,6 +103,16 @@ item.update(quantity: product.stock + 1) expect(item.purchase).must_equal false end + + it "will return nil if item is invalid" do + item = Item.new + expect(item.purchase).must_be_nil + end + + it "will return nil if product assoctiated with item is invalid" do + item.product = Product.new + expect(item.purchase).must_be_nil + end end end end diff --git a/test/models/order_test.rb b/test/models/order_test.rb index 4e01a54c7c..de36471d72 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -26,24 +26,33 @@ expect(order.valid?).must_equal false end end - end - describe "relationship with an order" do - it "can have 0 items" do - Item.destroy_all - expect(order.items.count).must_equal 0 + + describe "relationship with an order" do + it "can have 0 items" do + Item.destroy_all + expect(order.items.count).must_equal 0 + end + + it "can have 1 or more items" do + expect(order.items.count).must_equal 2 + end end - it "can have 1 or more items" do - expect(order.items.count).must_equal 2 + it "can shovel items to create a relationship" do + product = products(:product_1) + item = Item.new(quantity: 3, product: product) + expect(item.valid?).must_equal false + order.items << item + expect(item.valid?).must_equal true + expect(order.items.include?(item)).must_equal true end end - - it "can shovel items to create a relationship" do - product = products(:product_1) - item = Item.new(quantity: 3, product: product) - expect(item.valid?).must_equal false - order.items << item - expect(item.valid?).must_equal true - expect(order.items.include?(item)).must_equal true + describe "custom methods" do + describe do + end + describe do + end + describe do + end end end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index 5d7fea0592..270ba4b27b 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -132,6 +132,12 @@ product.reload expect(initial_stock).must_equal product.stock end + + it "will return nil if called on invalid product" do + product = Product.new + quantity = 1 + expect(product.decrease_stock(quantity)).must_be_nil + end end end end From f58459196eea89a92d2f34fdd2917fcfd675ce54 Mon Sep 17 00:00:00 2001 From: Elle K Date: Mon, 6 May 2019 15:57:21 -0700 Subject: [PATCH 123/260] Update application_controller.rb --- app/controllers/application_controller.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 468d42631e..57e10f8218 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -11,5 +11,3 @@ def find_cart_order @order = Order.find_by(id: session[:cart_id]) end end - -#hi From 1d24af411125511fc7ac7c987b4994626e69d56d Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Mon, 6 May 2019 16:00:01 -0700 Subject: [PATCH 124/260] Started writing test for custom merchant model method. Need to finish. --- app/controllers/application_controller.rb | 2 -- test/models/merchant_test.rb | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 468d42631e..57e10f8218 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -11,5 +11,3 @@ def find_cart_order @order = Order.find_by(id: session[:cart_id]) end end - -#hi diff --git a/test/models/merchant_test.rb b/test/models/merchant_test.rb index 2bddc3e989..1bf7356adb 100644 --- a/test/models/merchant_test.rb +++ b/test/models/merchant_test.rb @@ -76,4 +76,23 @@ expect(merchant.products.include?(product)).must_equal true end end + + describe "custom method build_from_github" do + it "build auth hash" do + # this_merchant = merchants(:merchant_1) + + new_auth_hash = { + provider: merchant.provider, + uid: merchant.uid, + info: { + email: merchant.email, + nickname: merchant.username, + }, + } + + merchant.provider.must_equal "github" + merchant.email.must_equal "pickhu@yahoo.com" + merchant.email.must_equal new_auth_hash[info][email] + end + end end From dc8c53823d748c91d79affa0ba779f243391a5ca Mon Sep 17 00:00:00 2001 From: qqdipps Date: Mon, 6 May 2019 16:20:59 -0700 Subject: [PATCH 125/260] tested custom order methods and added additional logic for edge cases --- app/models/order.rb | 3 ++ test/models/order_test.rb | 58 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/app/models/order.rb b/app/models/order.rb index b71ac2670f..c8b57c780a 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -4,6 +4,7 @@ class Order < ApplicationRecord def total return items.map do |item| + return unless item.valid? && item.product.valid? item.subtotal end.sum end @@ -11,6 +12,7 @@ def total def cart_errors cart_errors = [] items.each do |item| + return unless item.valid? && item.product.valid? unless item.available_for_purchase? cart_errors << item end @@ -20,6 +22,7 @@ def cart_errors def cart_checkout items.each do |item| + return unless item.valid? && item.product.valid? item.purchase end return true diff --git a/test/models/order_test.rb b/test/models/order_test.rb index de36471d72..a8021803aa 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -48,11 +48,63 @@ end end describe "custom methods" do - describe do + describe " def total" do + it "will calculate total cost of cart" do + total_cost = items(:item_1).quantity * items(:item_1).product.price / 100.0 + total_cost += items(:item_2).quantity * items(:item_2).product.price / 100.0 + expect(order.total).must_be_close_to total_cost + end + + it "will return nil if invalid item in cart" do + order.items << Item.new(order_id: order.id) + expect(order.total).must_be_nil + end + + it "will return nil if item has an invalid item in cart" do + items(:item_3).product = Product.new + order.items << items(:item_3) + expect(order.total).must_be_nil + end end - describe do + describe "cart errors" do + it "will return [] if all items are available for purchase" do + expect(order.cart_errors).must_equal [] + end + + it "will return items in array that are not available for purchase" do + items(:item_3).quantity = 1000 + order.items << items(:item_3) + items(:item_1).update(quantity: 2000) + expect(order.cart_errors.sort!).must_equal [items(:item_1), items(:item_3)].sort! + end + + it "will return nil if item(s) are not valid" do + order.items << Item.new(order_id: order.id) + expect(order.cart_errors).must_be_nil + end + + it "will return nil if an items product is not valid" do + items(:item_3).product = Product.new + order.items << items(:item_3) + expect(order.cart_errors).must_be_nil + end end - describe do + describe " def cart_checkout" do + # tests for quantity decrease/not decreasing + # done in product model test, custom methods section. + it "will return true if items and products are valid" do + expect(order.cart_checkout).must_equal true + end + + it "will return nil if item(s) are not valid" do + order.items << Item.new(order_id: order.id) + expect(order.cart_checkout).must_be_nil + end + it "will return nil if an items product is not valid" do + items(:item_3).product = Product.new + order.items << items(:item_3) + expect(order.cart_checkout).must_be_nil + end end end end From 7e22a7048c8d7cf864a0ecfdabf8f66e5101fa10 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Mon, 6 May 2019 16:23:17 -0700 Subject: [PATCH 126/260] added stock to missing params, ALL TEST GREEn =) --- test/controllers/products_controller_test.rb | 6 +++--- test/models/merchant_test.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index 7abb2b93b5..f99eb8dcb4 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -68,7 +68,7 @@ describe "logged in user" do it "creates a product with valid data" do merchant = perform_login - new_product = {product: {name: "Something amazing", price: 1000}} + new_product = { product: { name: "Something amazing", price: 1000, stock: 4 } } expect { post products_path, params: new_product }.must_change "Product.count", 1 @@ -83,7 +83,7 @@ it "renders bad_request and does not update the DB for bogus data" do merchant = perform_login - bad_prod_name = {product: {name: nil, price: 1000}} + bad_prod_name = { product: { name: nil, price: 1000 } } expect { post products_path, params: bad_prod_name @@ -98,7 +98,7 @@ describe "logged out user" do it "cannot create a product with valid data" do # is setting merchant id to nil enough to test this? - new_product = {product: {name: "Something amazing", price: 1000}} + new_product = { product: { name: "Something amazing", price: 1000 } } expect { post products_path, params: new_product }.wont_change "Product.count" diff --git a/test/models/merchant_test.rb b/test/models/merchant_test.rb index 2bddc3e989..4e294bc49e 100644 --- a/test/models/merchant_test.rb +++ b/test/models/merchant_test.rb @@ -69,7 +69,7 @@ end it "can shovel product to create relationship" do - product = Product.new(name: "penny", price: 1200) + product = Product.new(name: "penny", price: 1200, stock: 4) expect(product.valid?).must_equal false merchant.products << product expect(product.valid?).must_equal true From af43180b7945e470d32032dbe25ff8a050d06e3d Mon Sep 17 00:00:00 2001 From: Cloudy Lopez Date: Mon, 6 May 2019 17:02:39 -0700 Subject: [PATCH 127/260] more styling --- app/assets/stylesheets/homepages.scss | 93 ++++++++++++++++++++++++++ app/views/categories/show.html.erb | 5 +- app/views/homepages/index.html.erb | 7 +- app/views/layouts/application.html.erb | 19 ++++-- 4 files changed, 113 insertions(+), 11 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 2305c36d10..f4b3d46041 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -1,3 +1,96 @@ // Place all the styles related to the Homepages controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ +body { + background-color: rgb(255, 255, 255); + font-family: Helvetica, Arial, sans-serif +} + +h1 { + font-family: 'League Script', Helvetica, Arial, sans-serif; + font-size: 175px; + color: #fff; + text-align: center; + -webkit-animation: glow 1s ease-in-out infinite alternate; + -moz-animation: glow 1s ease-in-out infinite alternate; + animation: glow 1s ease-in-out infinite alternate; +} + +@-webkit-keyframes glow { + from { + text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #e60073, 0 0 40px #e60073, 0 0 50px #e60073, 0 0 60px #e60073, 0 0 70px #e60073; + } + to { + text-shadow: 0 0 20px #fff, 0 0 30px #ff4da6, 0 0 40px #ff4da6, 0 0 50px #ff4da6, 0 0 60px #ff4da6, 0 0 70px #ff4da6, 0 0 80px #ff4da6; + } +} + +h2 { + font-family: 'League Script', Helvetica, Arial, sans-serif; + font-size: 70px; + color: rgb(255, 255, 255); + text-align: center; + -webkit-animation: glow 1s ease-in-out infinite alternate; + -moz-animation: glow 1s ease-in-out infinite alternate; + animation: glow 1s ease-in-out infinite alternate; +} + +h3 { + font-family: 'Raleway Dots', Arial, sans-serif; + font-size: 50px; + color: rgba(241, 194, 255, 0.733); + text-align: center; +} + +h4 { + font-family: 'Raleway Dots', Arial, sans-serif; + font-size: 30px; + color: rgba(194, 217, 253, 0.842); + text-align: center; +} + +li { + font-family: 'Raleway Dots', Arial, sans-serif, Haettenschweiler, 'Arial Narrow Bold', sans-serif +} + +ul { + font-family: 'Courier New', Courier, monospace +} + +.nav_bar { + list-style: none; + display: flex; + flex-wrap: wrap; + justify-content: center; + padding: 20px 10px; + margin: 0; +} + +.nav_bar_header ul li { + padding: 20px 30px; + display: block; +} + +h3 { + text-align: center; + color: rgb(255, 255, 255); + text-shadow: 1px 1px 2px rgb(255, 255, 255), 0 0 25em hotpink, 0 0 0.2em white; +} + +p { + text-align: center; + color:rgb(136, 136, 136); + text-shadow: 1px 1px 2px rgb(255, 255, 255), 0 0 25em hotpink, 0 0 0.2em white; +} + + +#footer { + position: absolute; + bottom: 0; + width: 100%; + height: 2.5rem; +} + +ul { + list-style-type: none; +} \ No newline at end of file diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 4cd61ab305..2f6e6d0ebc 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -17,5 +17,6 @@ <% end %> -<%= link_to "Back to all products", products_path %> -<%= link_to "Back to all categories", categories_path %> \ No newline at end of file +

<%= link_to "Back to all products", products_path %>

+ +

<%= link_to "Back to all categories", categories_path %>

\ No newline at end of file diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index 8dad84c44a..b698c15fed 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -1,7 +1,8 @@ -

Homepages#index

-

Find me in app/views/homepages/index.html.erb

+

Intangibly

+

find your magic index.html.er

<% if session[:merchant_id] %> <% merchant = Merchant.find_by(id: session[:merchant_id]) %> -<%= "You are currently logged in as #{merchant.username}" %> +

<%= "You are currently logged in as #{merchant.username}" %>

+<%# wrap in class for footer %> <% end %> \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 7a2b425545..f53f562f42 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,7 +1,14 @@ + + + + - Betsy + SECRETS <%= csrf_meta_tags %> <%= csp_meta_tag %> @@ -15,22 +22,22 @@
+
<% if flash[:success] %> <%= flash[:success] %>
+
<% elsif flash[:error] %> <%= flash[:error] %> @@ -68,10 +70,15 @@ <% end %>
+
+ - + +
<%= yield %>
+ + From 451e7ed0659c2446c27ed0d4b4038e252a6ee790 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Tue, 7 May 2019 14:53:01 -0700 Subject: [PATCH 151/260] Styled the home page. Made font colors readable on products index page. Working to get major components in place and then will revisit making the fonts more magical later. --- app/assets/stylesheets/application.scss | 12 ++++++++ app/assets/stylesheets/homepages.scss | 37 ++++++++++++++++++------- app/views/layouts/application.html.erb | 4 +-- app/views/products/index.html.erb | 2 +- 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index b4d20f5641..afa576a0fa 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -15,3 +15,15 @@ @import "bootstrap"; /* Import scss content */ @import "**/*"; + +.nav-item { + color: rgba(131, 11, 142, 0.842); + } + .nav_bar { + list-style: none; + display: flex; + flex-wrap: wrap; + justify-content: center; + padding: 20px 10px; + margin: 0; + } diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index e1961b92c4..434185b34f 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -37,9 +37,11 @@ h4 { text-align: center; } - +.bg-purple { + background-color: rgba(131, 11, 142, 0.842); +} li { - font-family: 'Raleway Dots', Arial, sans-serif, 'Arial Narrow Bold', sans-serif + font-family: Arial, sans-serif, 'Arial Narrow Bold', sans-serif } ul { @@ -47,6 +49,14 @@ ul { list-style-type: none; } +a { + color: #333; +} + +a:hover { + color: #000; + text-decoration: none; +} .greybg { background-color: rgb(165, 164, 164); @@ -62,25 +72,32 @@ ul { #tagline { font-family: 'Raleway Dots', Arial, sans-serif; - font-size: 5em; + font-size: 4em; color: rgba(131, 11, 142, 0.842); text-align: center; } -.nav_bar { - list-style: none; - display: flex; - flex-wrap: wrap; - justify-content: center; - padding: 20px 10px; - margin: 0; +.nav-link { + color: rgba(253, 228, 255, 0.842); } +// .nav_bar { +// list-style: none; +// display: flex; +// flex-wrap: wrap; +// justify-content: center; +// padding: 20px 10px; +// margin: 0; +// } .nav_bar_header ul li { padding: 20px 30px; display: block; } +.page-btn { + padding: 5em; +} + p { text-align: center; diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 5e7cc2f8a4..8b6a39b450 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -17,7 +17,7 @@
-
-
- <% if flash[:success] %> + <% if flash[:success] %> +
<%= flash[:success] %> -
-
- <% elsif flash[:error] %> +
+ <% elsif flash[:error] %> +
<%= flash[:error] %>
    <%flash.each do |label, problems|%> @@ -59,8 +59,8 @@ <% end %> <% end %>
- <% end %> -
+
+ <% end %>
From 0cf98911967c52bc66aa9312298d4a1bf01f3b63 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Tue, 7 May 2019 20:53:00 -0700 Subject: [PATCH 160/260] fixed indentation for layout --- app/views/layouts/application.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 6754e4ef03..4882bdc9a0 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -59,7 +59,7 @@ <% end %> <% end %> - + <% end %> From f97ce2e6f6b8c7454df821bc7d10726589ceb143 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Tue, 7 May 2019 21:08:06 -0700 Subject: [PATCH 161/260] fixed bootstrap alerts --- app/views/layouts/application.html.erb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 4882bdc9a0..33d62c43a6 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -48,13 +48,13 @@ <%= flash[:success] %> <% elsif flash[:error] %> -
- <%= flash[:error] %> +
    + <%= flash[:error] %> <%flash.each do |label, problems|%> <% if label != "error" %> <% problems.each do |problem| %> -
  • <%= label %>: <%= problem %>
  • +
  • <%= label %>: <%= problem %>
  • <% end %> <% end %> <% end %> From ec9b94c7200f42d0d6ff8526c8597d13680f2087 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Tue, 7 May 2019 21:13:42 -0700 Subject: [PATCH 162/260] added bootstrap form to create and update product. would like help with the checkbox functionality. Form is functional. Branch can be merged if it looks good to reviewe --- app/views/products/_form.html.erb | 65 ++++++++++++++++++------------- app/views/products/edit.html.erb | 4 +- app/views/products/new.html.erb | 1 - 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb index 74bedb76a6..88522e8b0b 100644 --- a/app/views/products/_form.html.erb +++ b/app/views/products/_form.html.erb @@ -1,28 +1,39 @@ -<%= form_with model: @product, class: form_class do |f| %> - -

    <%= intro_text %>

    - - <%= f.label :name %> - <%= f.text_field :name, required: true %> - - <%= f.label :price %> - <%= f.number_field :price, in: 1.0..1000.0, step: 0.01, required: true %> - - - <%= f.label :categories %> - <%= collection_check_boxes(:product, :category_ids, Category.all, :id, :name) %> - - <%= f.label :description %> - <%= f.text_field :description, required: true %> - - - <%= f.label :photo_url %> - <%= f.text_field :photo_url, required: true %> - - <%= f.label :stock %> - <%= f.text_field :stock, required: true %> - - <%= f.submit action_name, class: "product-form__submit-btn" %> - -<% end %> +<%= form_with model: @product, class: form_class do |f| %> +
    +
    + <%=f.label "Name"%> + <%=f.text_field :name, required: true, class: "form-control"%> +
    +
    + <%=f.label "Price" %> + <%=f.number_field :price, in: 1.0..1000.0, step: 0.01, required: true, class: "form-control" %> +
    +
    +
    +
    + <%=f.label "Categories"%> + <%= collection_check_boxes(:product, :category_ids, Category.all, :id, :name)%> +
    +
    +
    +
    + <%=f.label "Product description" %> + <%=f.text_field :description, required: true, class: "form-control"%> +
    +
    +
+
+
+ <%=f.label "Photo URL"%> + <%=f.text_field :photo_url, required: true, class: "form-control"%> +
+
+ <%=f.label "Stock"%> + <%=f.text_field :stock, required: true, class: "form-control"%> +
+
+
+ <%=f.submit action_name, class:"btn btn-primary"%> +
+ <% end %> \ No newline at end of file diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb index a12a4f7552..5710a6c40c 100644 --- a/app/views/products/edit.html.erb +++ b/app/views/products/edit.html.erb @@ -1,6 +1,8 @@ +

Form for editing a new product

+ <%= render partial: "form", locals: { form_class: "edit-product", - intro_text: "Use this form to edit a product", action_name: "Edit product" } %> + diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index 8ff5f5e23e..232812c9df 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -3,6 +3,5 @@ <%= render partial: "form", locals: { form_class: "new-product", - intro_text: "Use this form to create a new product", action_name: "Create product" } %> From f8f79d91b716236afef37a19918da1bf10614877 Mon Sep 17 00:00:00 2001 From: Cloudy Lopez Date: Tue, 7 May 2019 21:17:46 -0700 Subject: [PATCH 163/260] styling without error, fingers crossed. --- app/assets/stylesheets/homepages.scss | 29 ++++++++++++--------------- app/views/products/show.html.erb | 23 +++++++++++---------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 434185b34f..8b0a162006 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -2,46 +2,45 @@ // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ body { - font-family: Helvetica, Arial, sans-serif + font-family: Helvetica, Arial, sans-serif; } h1 { font-family: 'League Script', Helvetica, Arial, sans-serif; - font-size: 175px; - color: #fff; + font-weight:bold; + font-size: 100px; + color: lavender; text-align: center; - } - - h2 { font-family: 'League Script', Helvetica, Arial, sans-serif; font-size: 70px; - color: rgb(255, 255, 255); + color: rgb(198, 239, 255); text-align: center; } h3 { font-family: 'Raleway Dots', Arial, sans-serif; + font-weight:bold; font-size: 50px; text-align: center; - color: rgb(255, 255, 255); + color: rgb(255, 157, 255); } h4 { font-family: 'Raleway Dots', Arial, sans-serif; + font-weight:bold; font-size: 30px; - color: rgba(194, 217, 253, 0.842); - text-align: center; + color:grey; } .bg-purple { - background-color: rgba(131, 11, 142, 0.842); + background-color: lavender; } li { - font-family: Arial, sans-serif, 'Arial Narrow Bold', sans-serif + font-family: Arial, sans-serif, 'Arial Narrow Bold', sans-serif; } ul { @@ -59,7 +58,7 @@ a:hover { } .greybg { - background-color: rgb(165, 164, 164); + background-color: rgb(255, 255, 255); } .whitebg { @@ -98,14 +97,12 @@ a:hover { padding: 5em; } - p { - text-align: center; + font-family: 'Raleway Dots', Arial, sans-serif; color:rgb(87, 87, 87); font-size: 1.3em; } - #footer { position: absolute; bottom: 0; diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index ef05b299ac..68ade07e4a 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,20 +1,21 @@ -

- Product Name: <%= @product.name %> -

+# erased product name +

+ <%= @product.name %> +

<%= image_tag @product.photo_url, alt: "Image of the product" %> -

- Price: $ <%= "%.2f" % (@product.price / 100.0) %> -

+

+<%= @product.description%> +

-

- Description: <%= @product.description%> -

+

+ Price: $ <%= "%.2f" % (@product.price / 100.0) %> +

-

+

Stock: <%= @product.stock%> -

+

From e4feb88a91a1f7dcb7aeced672ad61dad1caa8d7 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Tue, 7 May 2019 21:24:00 -0700 Subject: [PATCH 164/260] fixed tests --- test/controllers/products_controller_test.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index b839d04aab..52753e1ddb 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -57,7 +57,7 @@ describe "logged in user" do it "creates a product with valid data" do merchant = perform_login - new_product = { product: { name: "Something amazing", price: 1000, stock: 4 } } + new_product = {product: {name: "Something amazing", price: 1000, stock: 4}} expect { post products_path, params: new_product }.must_change "Product.count", 1 @@ -71,7 +71,7 @@ it "renders bad_request and does not update the DB for bogus data" do merchant = perform_login - bad_prod_name = { product: { name: nil, price: 1000 } } + bad_prod_name = {product: {name: nil, price: 1000}} expect { post products_path, params: bad_prod_name @@ -84,7 +84,7 @@ describe "logged out user" do it "cannot create a product with valid data" do - new_product = { product: { name: "Something amazing", price: 1000 } } + new_product = {product: {name: "Something amazing", price: 1000}} expect { post products_path, params: new_product }.wont_change "Product.count" @@ -112,6 +112,7 @@ get edit_product_path(-1) must_respond_with :redirect + must_redirect_to products_path end end describe "not logged in" do @@ -120,7 +121,8 @@ # do not do login get edit_product_path(merchant.products.first.id) - # must_respond_with :redirect + must_respond_with :redirect + must_redirect_to products_path expect(flash[:error]).must_equal "You must be logged in to edit a product" end end @@ -158,6 +160,7 @@ }.wont_change "Product.count" must_respond_with :redirect + must_redirect_to product_path(product_to_update.id) product_to_update.reload expect(product_to_update.name).must_equal test_input[:product][:name] expect(product_to_update.merchant_id).must_equal test_input[:product][:merchant_id] @@ -185,7 +188,7 @@ }.wont_change "Product.count" must_respond_with :bad_request - expect(flash[:name]).must_include "can't be blank" # working + expect(flash[:name]).must_include "can't be blank" end end From cfec4436c5bd997be95117f9a7b360461fa8e095 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Tue, 7 May 2019 21:57:50 -0700 Subject: [PATCH 165/260] current page refactor --- app/views/merchants/current.html.erb | 104 +++++++++------------------ 1 file changed, 35 insertions(+), 69 deletions(-) diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index f8be44c0be..f0aafb8987 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -19,75 +19,41 @@

$<%= Order.status_revenue(item_hash["paid"]) + Order.status_revenue(item_hash["completed"])%>

Orders by status

-

Status: Paid

- <% item_hash["paid"].each do |order, items| %> - - - - - - - - - - - - - - - - - - - - - <%items.each do |item| %> - - - - - - - - <%end%> - -
Order ID: <%= order %> Date & Time of order: <%= Order.find(order).created_at.strftime("%B %d, %T")%>Order Status: <%= Order.find(order).status %>
QuantityProduct NameUnit PriceSubtotalMark as Shipped
<%=item.quantity%><%=link_to item.product.name, product_path(item.product.id) %>$<%=item.product.price / 100.0%>$<%=item.subtotal %>placeholder for ship button
- <%end%> - - - - -

Status: Complete

- <% item_hash["paid"].each do |order, items| %> - - - - - - - - - - - - - - - - - - - <%items.each do |item| %> - - - - - - - <%end%> - -
Order ID: <%= order %> Date & Time of order: <%= Order.find(order).created_at.strftime("%B %d, %T")%>Order Status: <%= Order.find(order).status %>
QuantityProduct NameUnit PriceSubtotal
<%=item.quantity%><%=link_to item.product.name, product_path(item.product.id) %>$<%=item.product.price / 100.0%>$<%=item.subtotal %>
+<%["paid", "complete"].each do |status|%> +

Status: <%=status.capitalize%>

+ <% item_hash[status].each do |order, items| %> + + + + + + + + + + + + + + + + + + + + + <%items.each do |item| %> + + + + + + + <%end%> - + +
Order ID: <%= order %> Date & Time of order: <%= Order.find(order).created_at.strftime("%B %d, %T")%>Order Status: <%= Order.find(order).status %>
QuantityProduct NameUnit PriceSubtotalMark as Shipped
<%=item.quantity%><%=link_to item.product.name, product_path(item.product.id) %>$<%=item.product.price / 100.0%>$<%=item.subtotal %>placeholder for ship button
+ <%end%> +<%end%> \ No newline at end of file From c482a59983f481572664dae30ee223ba5c048789 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Tue, 7 May 2019 22:30:34 -0700 Subject: [PATCH 166/260] set up view, controller, routes, limited authorization to view to just after checkout --- app/views/merchants/create.html.erb | 2 -- app/views/merchants/delete.html.erb | 2 -- app/views/orders/confirmation.html.erb | 11 +++++++++-- 3 files changed, 9 insertions(+), 6 deletions(-) delete mode 100644 app/views/merchants/create.html.erb delete mode 100644 app/views/merchants/delete.html.erb diff --git a/app/views/merchants/create.html.erb b/app/views/merchants/create.html.erb deleted file mode 100644 index 1762feece0..0000000000 --- a/app/views/merchants/create.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -

Merchants#create

-

Find me in app/views/merchants/create.html.erb

diff --git a/app/views/merchants/delete.html.erb b/app/views/merchants/delete.html.erb deleted file mode 100644 index ba4a05e513..0000000000 --- a/app/views/merchants/delete.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -

Merchants#delete

-

Find me in app/views/merchants/delete.html.erb

diff --git a/app/views/orders/confirmation.html.erb b/app/views/orders/confirmation.html.erb index 507687124c..b96abaf248 100644 --- a/app/views/orders/confirmation.html.erb +++ b/app/views/orders/confirmation.html.erb @@ -1,6 +1,13 @@ -

Order Confirmation:

- +

Order Confirmation

+ + + + + + + + From 6450443ef212b0c4eaad4b5358d1453e16df3f60 Mon Sep 17 00:00:00 2001 From: Cloudy Lopez Date: Tue, 7 May 2019 22:42:21 -0700 Subject: [PATCH 167/260] updated hosted images --- db/products_data.csv | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/db/products_data.csv b/db/products_data.csv index 80cb336517..2f5bf78845 100644 --- a/db/products_data.csv +++ b/db/products_data.csv @@ -1,21 +1,21 @@ name,price,description,photo_url,stock -high fives,3990,They’ve got as much sex appeal as a road accident.,https://placekitten.com/g/200/300,9 -cup of sunshine,4277,"But Mr. Dent, the plans have been available in the local planning office for the last nine months.",https://placekitten.com/g/200/300,5 -bucket of sunshine,2089,Don’t Panic,https://placekitten.com/g/200/300,4 -sleep revival,4799,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://placekitten.com/g/200/300,3 -relaxation,3361,there’s an infinite number of monkeys outside who want to talk to us about this script for Hamlet they’ve worked out.,https://placekitten.com/g/200/300,9 -energy,1131,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://placekitten.com/g/200/300,15 -a good hair day,637,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://placekitten.com/g/200/300,8 -pause time,1758,42,https://placekitten.com/g/200/300,9 -freshly showered,4963,Parts of the inside of her head screamed at other parts of the inside of her head.,https://placekitten.com/g/200/300,5 -teleport into bed,3216,if you’ve never been through a matter transference beam before you’ve probably lost some salt and protein. The beer you had should have cushioned your system a bit.,https://placekitten.com/g/200/300,12 -ada starter kit,2397,"Whatever your tastes, Magrathea can cater for you. We are not proud.",https://placekitten.com/g/200/300,5 -ada best seller pack,4517,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://placekitten.com/g/200/300,11 -cup of rainbows,4282,"It’s only half completed, I’m afraid – we haven’t even finished burying the artificial dinosaur skeletons in the crust yet.",https://placekitten.com/g/200/300,1 -puppy play pack,2803,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://placekitten.com/g/200/300,1 -kitten cuddles,4928,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://placekitten.com/g/200/300,14 -giggle party,3250,"It seemed to me that any civilization that had so far lost its head as to need to include a set of detailed instructions for use in a packet of toothpicks, was no longer a civilization in which I could live and stay sane.",https://placekitten.com/g/200/300,1 -bestfriend time,2332,"According to the legends, the Magratheans lived most of their lives underground.",https://placekitten.com/g/200/300,10 -juicy secret,1170,"Evolution? they said to themselves, Who needs it?",https://placekitten.com/g/200/300,3 -inside joke moment,4141,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://placekitten.com/g/200/300,12 -bondfire time,2976,42,https://placekitten.com/g/200/300,8 +high fives,3990,They’ve got as much sex appeal as a road accident.,https://ibb.co/tDYJ7dj,6 +cup of sunshine,4277,"But Mr. Dent, the plans have been available in the local planning office for the last nine months.",https://photos.app.goo.gl/Hrhb4q9hMC4uvBh67 +bucket of sunshine,2089,Don’t Panic.,https://ibb.co/5Lkh7Gz,7 +sleep revival,4799,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://ibb.co/tsmDCVw,7 +relaxation,3361,there’s an infinite number of monkeys outside who want to talk to us about this script for Hamlet they’ve worked out.,https://ibb.co/QkFzjD9,5 +energy,1131,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/WcHtG5y,7 +a good hair day,637,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/kHrW2JW,6 +pause time,1758,42,https://ibb.co/qk1rWyt,8 +freshly showered,4963,Parts of the inside of her head screamed at other parts of the inside of her head.,https://ibb.co/LtDnP6W,8 +teleport into bed,3216,if you’ve never been through a matter transference beam before you’ve probably lost some salt and protein. The beer you had should have cushioned your system a bit.,https://ibb.co/tCW9CHN,8 +ada starter kit,2397,"Whatever your tastes, Magrathea can cater for you. We are not proud.",https://photos.app.goo.gl/EjCZFqdH32peKLVD8 +ada best seller pack,4517,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/bN6QLXJ,9 +cup of rainbows,4282,"It’s only half completed, I’m afraid – we haven’t even finished burying the artificial dinosaur skeletons in the crust yet.",https://ibb.co/nkBXzYb,7 +puppy play pack,2803,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/QH3CFxw,4 +kitten cuddles,4928,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/cyLJK6k,7 +giggle party,3250,"It seemed to me that any civilization that had so far lost its head as to need to include a set of detailed instructions for use in a packet of toothpicks, was no longer a civilization in which I could live and stay sane.",https://ibb.co/fpGjm13,3 +bestfriend time,2332,"According to the legends, the Magratheans lived most of their lives underground.",https://ibb.co/GJL7PfT,7 +juicy secret,1170,"Evolution? they said to themselves, Who needs it?",https://ibb.co/VNjtJzz,5 +inside joke moment,4141,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://ibb.co/KXrm3wG,8 +bondfire time,2976,42,https://ibb.co/mCqdnr0,8 \ No newline at end of file From 689d9bffbf4366508232869bb48fe30e02b23036 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 09:12:57 -0700 Subject: [PATCH 168/260] scaffodling testing --- app/controllers/orders_controller.rb | 31 +++++++++------------- test/controllers/orders_controller_test.rb | 22 +++++++++++++++ 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index acddf7d86b..1a0e262ff2 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -2,11 +2,20 @@ class OrdersController < ApplicationController before_action :find_cart_order, except: [:show, :index] before_action :find_logged_in_merchant, only: [:show] - def view_cart + def show + if @login_merchant + @order = Order.find_by(id: params[:id]) + if !@order && !@order.items.any? { |item| item.product.merchant_id == @login_merchant.id } + flash[:error] = "Can not view order page. No items sold by merchant." + redirect_to current_merchant_path + end + else + flash[:error] = "You must be logged to view this page" + redirect_to root_path + end end - def index - redirect_to root_path + def view_cart end def confirmation @@ -19,22 +28,6 @@ def confirmation end end - def show - if @login_merchant - @order = Order.find_by(id: params[:id]) - if !@order - flash[:error] = "Unknown order" - redirect_to root_path - elsif !@order.items.any? { |item| item.product.merchant_id == @login_merchant.id } - flash[:error] = "Can not view order page. No items sold by merchant." - redirect_to current_merchant_path - end - else - flash[:error] = "You must be logged to view this page" - redirect_to root_path - end - end - def checkout unless @order flash[:error] = "Unable to checkout cart" diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 2c698cc5da..515b8c2c8d 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -1,6 +1,28 @@ require "test_helper" describe OrdersController do + # removed index path and controller rather than using it just to redirect + # describe "index" do + # it "will redirect all calls to home page" do + # get orders_path + # must_respond_with :redirect + # must_redirect_to root_path + # end + # end + describe "show" do + describe "not logged in" do + it "will redirct to root path with flash message" do + end + end + + describe "as a logged in merchant" do + it "will show order page if merchant has a product in the order" do + end + + it "will redirect to merchant dashboard if no products for order belong to mechant" do + end + end +end describe "view_cart" do it "will respond with success if no cart is stored in session" do get cart_path From a2d1e94ac987e6222b6e667898dae9b970b1c4f6 Mon Sep 17 00:00:00 2001 From: Cloudy Lopez Date: Wed, 8 May 2019 09:26:16 -0700 Subject: [PATCH 169/260] updated and fixed products_data#stock and found error using seeds file. --- db/products_data.csv | 4 ++-- db/seeds.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/db/products_data.csv b/db/products_data.csv index 2f5bf78845..15ffe318ce 100644 --- a/db/products_data.csv +++ b/db/products_data.csv @@ -1,6 +1,6 @@ name,price,description,photo_url,stock high fives,3990,They’ve got as much sex appeal as a road accident.,https://ibb.co/tDYJ7dj,6 -cup of sunshine,4277,"But Mr. Dent, the plans have been available in the local planning office for the last nine months.",https://photos.app.goo.gl/Hrhb4q9hMC4uvBh67 +cup of sunshine,4277,"But Mr. Dent, the plans have been available in the local planning office for the last nine months.",https://photos.app.goo.gl/Hrhb4q9hMC4uvBh67,4 bucket of sunshine,2089,Don’t Panic.,https://ibb.co/5Lkh7Gz,7 sleep revival,4799,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://ibb.co/tsmDCVw,7 relaxation,3361,there’s an infinite number of monkeys outside who want to talk to us about this script for Hamlet they’ve worked out.,https://ibb.co/QkFzjD9,5 @@ -9,7 +9,7 @@ a good hair day,637,"Nothing travels faster than the speed of light with the pos pause time,1758,42,https://ibb.co/qk1rWyt,8 freshly showered,4963,Parts of the inside of her head screamed at other parts of the inside of her head.,https://ibb.co/LtDnP6W,8 teleport into bed,3216,if you’ve never been through a matter transference beam before you’ve probably lost some salt and protein. The beer you had should have cushioned your system a bit.,https://ibb.co/tCW9CHN,8 -ada starter kit,2397,"Whatever your tastes, Magrathea can cater for you. We are not proud.",https://photos.app.goo.gl/EjCZFqdH32peKLVD8 +ada starter kit,2397,"Whatever your tastes, Magrathea can cater for you. We are not proud.",https://photos.app.goo.gl/EjCZFqdH32peKLVD8,8 ada best seller pack,4517,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/bN6QLXJ,9 cup of rainbows,4282,"It’s only half completed, I’m afraid – we haven’t even finished burying the artificial dinosaur skeletons in the crust yet.",https://ibb.co/nkBXzYb,7 puppy play pack,2803,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/QH3CFxw,4 diff --git a/db/seeds.rb b/db/seeds.rb index 4fb8b17de3..d72615d044 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -44,5 +44,5 @@ category.valid? ? (puts "#{i += 1} category-product relationships") : failed_to_save << review end end - +p failed_to_save puts "#{failed_to_save.count} failed to save" From dc53c1a285894df367ef0927a3c27486ec55410d Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 09:26:24 -0700 Subject: [PATCH 170/260] fixed bug when order id is invalid --- app/controllers/orders_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 1a0e262ff2..340b1856ff 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -5,7 +5,7 @@ class OrdersController < ApplicationController def show if @login_merchant @order = Order.find_by(id: params[:id]) - if !@order && !@order.items.any? { |item| item.product.merchant_id == @login_merchant.id } + if !@order || !@order.items.any? { |item| item.product.merchant_id == @login_merchant.id } flash[:error] = "Can not view order page. No items sold by merchant." redirect_to current_merchant_path end From 75e82afa2ebe4dddcc5c2d6df12504614eabee3c Mon Sep 17 00:00:00 2001 From: Cloudy Lopez Date: Wed, 8 May 2019 10:33:01 -0700 Subject: [PATCH 171/260] attempt number 3 for hosting images. --- db/products_data.csv | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/db/products_data.csv b/db/products_data.csv index 15ffe318ce..12e9889fa7 100644 --- a/db/products_data.csv +++ b/db/products_data.csv @@ -1,21 +1,21 @@ -name,price,description,photo_url,stock -high fives,3990,They’ve got as much sex appeal as a road accident.,https://ibb.co/tDYJ7dj,6 -cup of sunshine,4277,"But Mr. Dent, the plans have been available in the local planning office for the last nine months.",https://photos.app.goo.gl/Hrhb4q9hMC4uvBh67,4 -bucket of sunshine,2089,Don’t Panic.,https://ibb.co/5Lkh7Gz,7 -sleep revival,4799,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://ibb.co/tsmDCVw,7 -relaxation,3361,there’s an infinite number of monkeys outside who want to talk to us about this script for Hamlet they’ve worked out.,https://ibb.co/QkFzjD9,5 -energy,1131,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/WcHtG5y,7 -a good hair day,637,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/kHrW2JW,6 -pause time,1758,42,https://ibb.co/qk1rWyt,8 -freshly showered,4963,Parts of the inside of her head screamed at other parts of the inside of her head.,https://ibb.co/LtDnP6W,8 -teleport into bed,3216,if you’ve never been through a matter transference beam before you’ve probably lost some salt and protein. The beer you had should have cushioned your system a bit.,https://ibb.co/tCW9CHN,8 -ada starter kit,2397,"Whatever your tastes, Magrathea can cater for you. We are not proud.",https://photos.app.goo.gl/EjCZFqdH32peKLVD8,8 -ada best seller pack,4517,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/bN6QLXJ,9 -cup of rainbows,4282,"It’s only half completed, I’m afraid – we haven’t even finished burying the artificial dinosaur skeletons in the crust yet.",https://ibb.co/nkBXzYb,7 -puppy play pack,2803,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/QH3CFxw,4 -kitten cuddles,4928,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/cyLJK6k,7 -giggle party,3250,"It seemed to me that any civilization that had so far lost its head as to need to include a set of detailed instructions for use in a packet of toothpicks, was no longer a civilization in which I could live and stay sane.",https://ibb.co/fpGjm13,3 -bestfriend time,2332,"According to the legends, the Magratheans lived most of their lives underground.",https://ibb.co/GJL7PfT,7 -juicy secret,1170,"Evolution? they said to themselves, Who needs it?",https://ibb.co/VNjtJzz,5 -inside joke moment,4141,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://ibb.co/KXrm3wG,8 -bondfire time,2976,42,https://ibb.co/mCqdnr0,8 \ No newline at end of file +name,price,stock,description,photo_url +high fives,3990,3,They’ve got as much sex appeal as a road accident.,https://ibb.co/tDYJ7dj +cup of sunshine,4277,6,"But Mr. Dent, the plans have been available in the local planning office for the last nine months.",https://photos.app.goo.gl/Hrhb4q9hMC4uvBh67 +bucket of sunshine,2089,3,Don’t Panic.,https://ibb.co/5Lkh7Gz +sleep revival,4799,5,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://ibb.co/tsmDCVw +relaxation,3361,8,there’s an infinite number of monkeys outside who want to talk to us about this script for Hamlet they’ve worked out.,https://ibb.co/QkFzjD9 +energy,1131,6,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/WcHtG5y +a good hair day,637,7,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/kHrW2JW +pause time,1758,4,take time to study for the test,https://ibb.co/qk1rWyt +freshly showered,4963,8,Parts of the inside of her head screamed at other parts of the inside of her head.,https://ibb.co/LtDnP6W,8 +teleport into bed,3216,6,if you’ve never been through a matter transference beam before you’ve probably lost some salt and protein. The beer you had should have cushioned your system a bit.,https://ibb.co/tCW9CHN +ada starter kit,2397,5,"Whatever your tastes, Magrathea can cater for you. We are not proud.",https://photos.app.goo.gl/EjCZFqdH32peKLVD8,8 +ada best seller pack,4517,8,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/bN6QLXJ +cup of rainbows,4282,4,"It’s only half completed, I’m afraid – we haven’t even finished burying the artificial dinosaur skeletons in the crust yet.",https://ibb.co/nkBXzYb +puppy play pack,2803,8,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/QH3CFxw +kitten cuddles,4928,7,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/cyLJK6k +giggle party,3250,3,"It seemed to me that any civilization that had so far lost its head as to need to include a set of detailed instructions for use in a packet of toothpicks, was no longer a civilization in which I could live and stay sane.",https://ibb.co/fpGjm13 +bestfriend time,2332,11,"According to the legends, the Magratheans lived most of their lives underground.",https://ibb.co/GJL7PfT +juicy secret,1170,5,"Evolution? they said to themselves, Who needs it?",https://ibb.co/VNjtJzz +inside joke moment,4141,4,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://ibb.co/KXrm3wG +bondfire time,2976,4,its a nice time,https://ibb.co/mCqdnr0 \ No newline at end of file From 03274e5c560f2190f4e34a381a2a6cfa1dbbb73a Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 10:50:36 -0700 Subject: [PATCH 172/260] new and create method for category, new form, and tests --- app/controllers/categories_controller.rb | 32 ++++++++++ app/views/categories/new.html.erb | 14 ++++- .../controllers/categories_controller_test.rb | 62 +++++++++++++++++++ 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index eec27854d8..63957b4bfd 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -1,8 +1,34 @@ class CategoriesController < ApplicationController + before_action :find_logged_in_merchant, only: [:new, :create] + def new + if @login_merchant + @category = Category.new + else + flash[:error] = "You must be logged in to add a new category" + redirect_to root_path + end end def create + if @login_merchant # if merchant is logged in + @category = Category.new(category_params) + is_successful = @category.save + + if is_successful + flash[:success] = "Category added successfully" + redirect_to categories_path + else + flash.now[:error] = "Could not add new category:" + @category.errors.messages.each do |label, message| + flash.now[label.to_sym] = message + end + render :new, status: :bad_request + end + else + flash.now[:error] = "You must be logged in to create a new category" + render :new, status: :bad_request + end end def index @@ -16,4 +42,10 @@ def show redirect_to categories_path end end + + private + + def category_params + return params.require(:category).permit(:name) + end end diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb index 7e5c27307e..e09846a7fb 100644 --- a/app/views/categories/new.html.erb +++ b/app/views/categories/new.html.erb @@ -1,2 +1,12 @@ -

Categories#new

-

Find me in app/views/categories/new.html.erb

+

Form for creating a new category

+<%= form_with model: @category, class: "new-category" do |f| %> +
+
+ <%=f.label "Category name"%> + <%=f.text_field :name, required: true, class: "form-control"%> +
+
+
+ <%=f.submit "Create Category", class:"btn btn-primary"%> +
+ <% end %> \ No newline at end of file diff --git a/test/controllers/categories_controller_test.rb b/test/controllers/categories_controller_test.rb index 91d64518e5..81b8468d5e 100644 --- a/test/controllers/categories_controller_test.rb +++ b/test/controllers/categories_controller_test.rb @@ -31,4 +31,66 @@ expect(flash[:error]).must_equal "Unknown category" end end + + describe "new" do + describe "logged in merchant" do + it "succeeds" do + perform_login + get new_category_path + + must_respond_with :success + end + end + + describe "logged out" do + it "redirects and give flash notice" do + get new_category_path + + must_respond_with :redirect + must_redirect_to root_path + expect(flash[:error]).must_equal "You must be logged in to add a new category" + end + end + end + + describe "create" do + describe "logged in merchant" do + it "creates a category with valid data" do + perform_login + new_category = {category: {name: "Magic feeling"}} + expect { + post categories_path, params: new_category + }.must_change "Category.count", 1 + + expect(flash[:success]).must_equal "Category added successfully" + must_respond_with :redirect + must_redirect_to categories_path + end + + it "renders bad_request and does not update the DB for bogus data" do + perform_login + bad_category_name = {category: {name: nil}} + + expect { + post categories_path, params: bad_category_name + }.wont_change "Category.count" + + must_respond_with :bad_request + expect(flash[:error]).must_include "Could not add new category" + expect(flash[:name]).must_include "can't be blank" + end + end + + describe "logged out" do + it "cannot create a category with valid data" do + new_category = {category: {name: "Magic feeling"}} + expect { + post categories_path, params: new_category + }.wont_change "Category.count" + + must_respond_with :bad_request + expect(flash[:error]).must_equal "You must be logged in to create a new category" + end + end + end end From 97ed02431fa2ed7a6e3f1bcf3b13f60546f0af13 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 10:53:23 -0700 Subject: [PATCH 173/260] added link to new category to merc dash --- app/views/merchants/current.html.erb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index f0aafb8987..f11bc3b42d 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -2,6 +2,7 @@

Welcome <%= @login_merchant.username %>

<%= link_to "Add new product", new_product_path %> +<%= link_to "Add new category", new_category_path %> <% item_hash = Order.find_merchant_order_items(@login_merchant) %> From 44a672260012a4d5717ef537e987d37bbbb49b62 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 10:54:12 -0700 Subject: [PATCH 174/260] testing for orders#confirmation complete. all tests green. made small update to controller logic, and updated related tests. --- app/controllers/orders_controller.rb | 6 +- test/controllers/orders_controller_test.rb | 82 ++++++++++++++++++++-- test/fixtures/items.yml | 5 ++ test/fixtures/orders.yml | 10 +++ 4 files changed, 93 insertions(+), 10 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 340b1856ff..b56fbe8749 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -20,9 +20,9 @@ def view_cart def confirmation @order = Order.find_by(id: params[:id]) - if !session[:confirmation] || !@order - redirect_to root_path + if !@order || session[:confirmation] != @order.id flash[:error] = "Checkout cart to view confirmation page" + redirect_to root_path else session[:confirmation] = nil end @@ -39,9 +39,9 @@ def purchase if @order && @order.update(order_params) && @order.cart_errors.empty? @order.cart_checkout @order.update(status: "paid", cc_four: params[:order][:cc_all][-4..-1]) # front end valid. on form for min 4 chars + session[:confirmation] = session[:cart_id] session[:cart_id] = nil flash[:success] = "Purchase Successful" - session[:confirmation] = true # needs test redirect_to order_confirmation_path(@order.id) else flash[:error] = "Unable to checkout cart" diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 515b8c2c8d..83d3e3d3e8 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -11,18 +11,18 @@ # end describe "show" do describe "not logged in" do - it "will redirct to root path with flash message" do + it "will redirct to root path with flash message" do end end - describe "as a logged in merchant" do - it "will show order page if merchant has a product in the order" do + describe "as a logged in merchant" do + it "will show order page if merchant has a product in the order" do end - it "will redirect to merchant dashboard if no products for order belong to mechant" do + it "will redirect to merchant dashboard if no products for order belong to mechant" do end - end -end + end + end describe "view_cart" do it "will respond with success if no cart is stored in session" do get cart_path @@ -40,6 +40,53 @@ end end + describe "confirmation" do + let(:product) { products(:product_1) } + let(:product2) { products(:product_2) } + let(:item_params) { { item: { quantity: 2 } } } + let(:cart_params) { + { order: { shopper_name: "susie", + shopper_email: "dalmation@susy.org", + shopper_address: "44550 mailing address", + cc_all: "234443434", + cc_exp: "03022020" } } + } + before do + post product_items_path(product.id), params: item_params + post product_items_path(product2.id), params: item_params + @order = Order.find(session[:cart_id]) + end + describe "following succesful purchase of cart" do + before do + post purchase_cart_path, params: cart_params + end + it "will respond with success" do + get order_confirmation_path(@order.id) + must_respond_with :success + end + + it "will reset confirmation in session to nil" do + expect(session[:confirmation]).must_equal @order.id + get order_confirmation_path(@order.id) + expect(session[:confirmation]).must_be_nil + end + end + + describe "not following purchase of cart" do + it "will redirect to root and not make changes to session[:confirmation]" do + expect(session[:confirmation]).must_be_nil + + get order_confirmation_path(@order.id) + + expect(session[:confirmation]).must_be_nil + expect(flash[:error]).must_equal "Checkout cart to view confirmation page" + + must_respond_with :redirect + must_redirect_to root_path + end + end + end + describe "checkout" do let(:product) { products(:product_1) } let(:item_params) { { item: { quantity: 2 } } } @@ -74,7 +121,7 @@ post product_items_path(product.id), params: item_params post product_items_path(product2.id), params: item_params end - it "will set cart in srssion to nil if valid cart purchase" do + it "will set cart in session to nil if valid cart purchase" do expect(session[:cart_id]).wont_be_nil expect { @@ -84,6 +131,17 @@ expect(session[:cart_id]).must_be_nil end + it "will set confirmation to true in session if valid cart purchase" do + expect(session[:confirmation]).must_be_nil + order_id = session[:cart_id] + + expect { + post purchase_cart_path, params: cart_params + }.wont_change "Order.count" + + expect(session[:confirmation]).must_equal order_id + end + it "will change order status from pending to paid if valid cart purchase" do order = Order.find_by(id: session[:cart_id]) expect(order.status).must_equal "pending" @@ -175,6 +233,16 @@ }.wont_change "Order.count" expect(session[:cart_id]).wont_be_nil end + + it "will set not set confirmation in session if invalid cart purchase attempt" do + expect(session[:confirmation]).must_be_nil + + expect { + post purchase_cart_path, params: cart_params + }.wont_change "Order.count" + + expect(session[:confirmation]).must_be_nil + end end end end diff --git a/test/fixtures/items.yml b/test/fixtures/items.yml index 5d5928f8ca..6e9749bd58 100644 --- a/test/fixtures/items.yml +++ b/test/fixtures/items.yml @@ -15,3 +15,8 @@ item_3: order: order_2 product: product_2 +item_4: + quantity: 3 + order: order_3 + product: product_2 + diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index f8f99ffe39..657816b7de 100644 --- a/test/fixtures/orders.yml +++ b/test/fixtures/orders.yml @@ -16,4 +16,14 @@ order_2: cc_four: 2534 cc_exp: 09092020 +order_3: + status: pending + shopper_name: miranda + shopper_email: panda@hooo.com + shopper_address: 43244 tryagain address + cc_four: 2534 + cc_exp: 09092020 + + + From 5a3eb8aa3a049a55acd05ed6ff8ad5280e576344 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 10:56:34 -0700 Subject: [PATCH 175/260] user acceptance testing looks good as well --- test/controllers/orders_controller_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 83d3e3d3e8..f97c556a55 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -80,7 +80,7 @@ expect(session[:confirmation]).must_be_nil expect(flash[:error]).must_equal "Checkout cart to view confirmation page" - + must_respond_with :redirect must_redirect_to root_path end From 5b1b62e9fc0b9a201ceae97f9f11243f6bce1fa7 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 10:59:47 -0700 Subject: [PATCH 176/260] removed change from tb photo display --- app/views/products/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 3424aa75ef..d03f54e2c4 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -2,7 +2,7 @@ Product Name: <%= @product.name %> -<%= image_tag image_url(@product.photo_url), alt: "Image of the product" %> +<%= image_tag @product.photo_url, alt: "Image of the product" %>

Price: $ <%= "%.2f" % (@product.price / 100.0) %> From e885ab96f92a5e753bc98a185be5f1dacc926ccb Mon Sep 17 00:00:00 2001 From: Cloudy Lopez Date: Wed, 8 May 2019 11:20:35 -0700 Subject: [PATCH 177/260] photos hosted and being supported --- db/products_data.csv | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/db/products_data.csv b/db/products_data.csv index 12e9889fa7..c646979085 100644 --- a/db/products_data.csv +++ b/db/products_data.csv @@ -1,21 +1,21 @@ name,price,stock,description,photo_url -high fives,3990,3,They’ve got as much sex appeal as a road accident.,https://ibb.co/tDYJ7dj -cup of sunshine,4277,6,"But Mr. Dent, the plans have been available in the local planning office for the last nine months.",https://photos.app.goo.gl/Hrhb4q9hMC4uvBh67 -bucket of sunshine,2089,3,Don’t Panic.,https://ibb.co/5Lkh7Gz -sleep revival,4799,5,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://ibb.co/tsmDCVw -relaxation,3361,8,there’s an infinite number of monkeys outside who want to talk to us about this script for Hamlet they’ve worked out.,https://ibb.co/QkFzjD9 -energy,1131,6,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/WcHtG5y -a good hair day,637,7,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/kHrW2JW -pause time,1758,4,take time to study for the test,https://ibb.co/qk1rWyt -freshly showered,4963,8,Parts of the inside of her head screamed at other parts of the inside of her head.,https://ibb.co/LtDnP6W,8 -teleport into bed,3216,6,if you’ve never been through a matter transference beam before you’ve probably lost some salt and protein. The beer you had should have cushioned your system a bit.,https://ibb.co/tCW9CHN -ada starter kit,2397,5,"Whatever your tastes, Magrathea can cater for you. We are not proud.",https://photos.app.goo.gl/EjCZFqdH32peKLVD8,8 -ada best seller pack,4517,8,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/bN6QLXJ -cup of rainbows,4282,4,"It’s only half completed, I’m afraid – we haven’t even finished burying the artificial dinosaur skeletons in the crust yet.",https://ibb.co/nkBXzYb -puppy play pack,2803,8,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/QH3CFxw -kitten cuddles,4928,7,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://ibb.co/cyLJK6k -giggle party,3250,3,"It seemed to me that any civilization that had so far lost its head as to need to include a set of detailed instructions for use in a packet of toothpicks, was no longer a civilization in which I could live and stay sane.",https://ibb.co/fpGjm13 -bestfriend time,2332,11,"According to the legends, the Magratheans lived most of their lives underground.",https://ibb.co/GJL7PfT -juicy secret,1170,5,"Evolution? they said to themselves, Who needs it?",https://ibb.co/VNjtJzz -inside joke moment,4141,4,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://ibb.co/KXrm3wG -bondfire time,2976,4,its a nice time,https://ibb.co/mCqdnr0 \ No newline at end of file +high fives,3990,3,They’ve got as much sex appeal as a road accident.,https://i.ibb.co/jD3rcp0/camylla-battani-784361-unsplash.jpg +cup of sunshine,4277,6,"But Mr. Dent, the plans have been available in the local planning office for the last nine months.",https://i.ibb.co/16kjtyH/mi-pham-223464-unsplash.jpg +bucket of sunshine,2089,3,Don’t Panic.,https://i.ibb.co/SBcwL51/hemerson-coelho-1364589-unsplash.jpg +sleep revival,4799,5,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://i.ibb.co/qsyp1TL/isaac-davis-598918-unsplash.jpg +relaxation,3361,8,there’s an infinite number of monkeys outside who want to talk to us about this script for Hamlet they’ve worked out.,https://i.ibb.co/ZS6t12d/allef-vinicius-111554-unsplash.jpg +energy,1131,6,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/qW7q6PW/maria-fernanda-gonzalez-461521-unsplash.jpg +a good hair day,637,7,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/ZhfmGX8/bruno-nascimento-149663-unsplash.jpg +pause time,1758,4,take time to study for the test,https://i.ibb.co/RzHDBvx/ahmadreza-sajadi-10140-unsplash.jpg +freshly showered,4963,8,Parts of the inside of her head screamed at other parts of the inside of her head.,https://i.ibb.co/RzHDBvx/ahmadreza-sajadi-10140-unsplash.jpg +teleport into bed,3216,6,if you’ve never been through a matter transference beam before you’ve probably lost some salt and protein. The beer you had should have cushioned your system a bit.,https://i.ibb.co/nk5FkwV/diego-ph-493991-unsplash.jpg +ada starter kit,2397,5,"Whatever your tastes, Magrathea can cater for you. We are not proud.",https://photos.app.goo.gl/EjCZFqdH32peKLVD8 +ada best seller pack,4517,8,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/vLcVmkY/ishan-seefromthesky-277746-unsplash.jpg +cup of rainbows,4282,4,"It’s only half completed, I’m afraid – we haven’t even finished burying the artificial dinosaur skeletons in the crust yet.",https://i.ibb.co/LprTnc8/alistair-macrobert-633034-unsplash.jpg +puppy play pack,2803,8,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/M1xGDJ0/bharathi-kannan-1260953-unsplash.jpg +kitten cuddles,4928,7,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/GdT7fWn/kote-puerto-771605-unsplash.jpg +giggle party,3250,3,"It seemed to me that any civilization that had so far lost its head as to need to include a set of detailed instructions for use in a packet of toothpicks, was no longer a civilization in which I could live and stay sane.",https://i.ibb.co/7WNs7Y3/carlos-pimentel-1206339-unsplash.jpg +bestfriend time,2332,11,"According to the legends, the Magratheans lived most of their lives underground.",https://i.ibb.co/Jd4nkWQ/ian-schneider-64307-unsplash.jpg +juicy secret,1170,5,"Evolution? they said to themselves, Who needs it?",https://i.ibb.co/pP0xbMM/dan-cook-508166-unsplash.jpg +inside joke moment,4141,4,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://i.ibb.co/PN6tfQY/marcela-rogante-432403-unsplash.jpg +bondfire time,2976,4,its a nice time,hhttps://i.ibb.co/JR78YWq/mike-erskine-144525-unsplash.jpg \ No newline at end of file From 3da1bac15461df512796b7eb8cfd8131b92ea174 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Wed, 8 May 2019 11:47:07 -0700 Subject: [PATCH 178/260] Small changes to make colors readable, centered text on empty cart. --- app/assets/stylesheets/homepages.scss | 15 +++++++++++---- app/views/layouts/application.html.erb | 5 ----- app/views/orders/view_cart.html.erb | 6 +++--- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 8b0a162006..8c6d844cf4 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -9,16 +9,16 @@ h1 { font-family: 'League Script', Helvetica, Arial, sans-serif; font-weight:bold; font-size: 100px; - color: lavender; + color: rgb(198, 158, 255); text-align: center; } h2 { font-family: 'League Script', Helvetica, Arial, sans-serif; font-size: 70px; - color: rgb(198, 239, 255); + color: rgb(198, 158, 255); text-align: center; - + padding-top: 1em; } h3 { @@ -65,6 +65,13 @@ a:hover { background-color: #fff; } +.centered_grey_text { + text-align: center; + font-size: 2em; + font-family: 'Raleway Dots', Arial, sans-serif; + color:rgb(87, 87, 87); +} + #mainpadding { padding-top: 2em; } @@ -77,7 +84,7 @@ a:hover { } .nav-link { - color: rgba(253, 228, 255, 0.842); + color: rgba(0, 0, 0, 0.5); } // .nav_bar { // list-style: none; diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 58bd91fd0c..f2155f880a 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -69,14 +69,9 @@ <% end %> <% end %> -<<<<<<< HEAD - - <% end %> -======= <% end %> ->>>>>>> 75e82afa2ebe4dddcc5c2d6df12504614eabee3c diff --git a/app/views/orders/view_cart.html.erb b/app/views/orders/view_cart.html.erb index 94473eec54..fa3514c821 100644 --- a/app/views/orders/view_cart.html.erb +++ b/app/views/orders/view_cart.html.erb @@ -1,6 +1,6 @@
<%if @order && @order.items.any? %> -

<%=@order.items.count%> item<%="s" if @order.items.count != 1%> in cart

+

<%=@order.items.count%> item<%="s" if @order.items.count != 1%> in cart

<%@order.items.each do |item| %>

<%=item.product.name%>

@@ -13,7 +13,7 @@ <%= link_to "Check Out", checkout_cart_path, class: "btn btn-primary"%> <%=link_to "Keep shopping", products_path %> <%else%> -

0 items in cart

- <%= link_to "Discover something intangible to fill it up", products_path %> +

0 items in cart

+

<%= link_to "Discover something intangible to fill it up", products_path %>

<%end%>
From a5778b35e0d49ce01e6455c920504f6ca4116d9c Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Wed, 8 May 2019 14:05:52 -0700 Subject: [PATCH 179/260] Changed merchant logged in name button to go to merchant dashboard. --- app/views/layouts/application.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index f2155f880a..59388b7788 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -37,7 +37,7 @@ <% if session[:merchant_id] %> <% merchant = Merchant.find_by(id: session[:merchant_id]) %> - <%= link_to merchant.username, cart_path, class: "nav-link"%> + <%= link_to merchant.username, merchant_path(merchant.id), class: "nav-link"%> <%= link_to "Log Out", logout_path, method: "delete", class: "btn btn-outline-success my-2 my-sm-0" %> <% else %> <%= link_to "Log In", github_login_path, class: "btn btn-outline-success my-2 my-sm-0" %> From 3aa6d32368550c1ed026139810a7dedb4a98e52e Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 14:19:24 -0700 Subject: [PATCH 180/260] inprocess of testing --- test/controllers/orders_controller_test.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index f97c556a55..4e35d00619 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -10,16 +10,34 @@ # end # end describe "show" do + let(:order) { orders(:order_1) } describe "not logged in" do it "will redirct to root path with flash message" do + get order_path(order.id) + + expect(flash[:error]).must_equal "You must be logged to view this page" + + must_respond_with :redirect + must_redirect_to root_path end end describe "as a logged in merchant" do it "will show order page if merchant has a product in the order" do + perform_login(merchants(:merchant_2)) + get order_path(order.id) + + must_respond_with :success end it "will redirect to merchant dashboard if no products for order belong to mechant" do + perform_login + get order_path(order.id) + + expect(flash[:error]).must_equal "Can not view order page. No items sold by merchant." + must_respond_with :redirect + must_redirect_to current_merchant_path + end end end From cfd9d32e0e4ec053a3feb56ef46039e42ab10140 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 14:30:33 -0700 Subject: [PATCH 181/260] fixed errors --- app/views/layouts/application.html.erb | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 59388b7788..86b870a651 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -50,27 +50,25 @@
- -
- <% if flash[:success] %> + <% if flash[:success] %> +
<%= flash[:success] %> -
+
-
- <% elsif flash[:error] %> + <% elsif flash[:error] %> +
<%= flash[:error] %>
    - <%= flash[:error] %> <%flash.each do |label, problems|%> <% if label != "error" %> <% problems.each do |problem| %> -
  • <%= label %>: <%= problem %>
  • +
  • <%= label %>: <%= problem %>
  • <% end %> <% end %> <% end %>
- <% end %> -
+
+ <% end %>
From 9af74457293e4b9d8df90b30080db6bc46bfecb3 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 14:35:22 -0700 Subject: [PATCH 182/260] tested show action --- test/controllers/orders_controller_test.rb | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 4e35d00619..57b4ac5c6e 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -23,6 +23,9 @@ end describe "as a logged in merchant" do + before do + perform_login + end it "will show order page if merchant has a product in the order" do perform_login(merchants(:merchant_2)) get order_path(order.id) @@ -31,13 +34,20 @@ end it "will redirect to merchant dashboard if no products for order belong to mechant" do - perform_login - get order_path(order.id) + get order_path(order.id) - expect(flash[:error]).must_equal "Can not view order page. No items sold by merchant." - must_respond_with :redirect - must_redirect_to current_merchant_path + expect(flash[:error]).must_equal "Can not view order page. No items sold by merchant." + must_respond_with :redirect + must_redirect_to current_merchant_path + end + it "if given invalid id and user is logged in " do + order_id = -1 + get order_path(-1) + + expect(flash[:error]).must_equal "Can not view order page. No items sold by merchant." + must_respond_with :redirect + must_redirect_to current_merchant_path end end end From a20ea9cba531afba04b9af0a8fc3134e9063cce1 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 14:37:41 -0700 Subject: [PATCH 183/260] small refactor, all tests greeen to go --- test/controllers/orders_controller_test.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 57b4ac5c6e..1e2fb75896 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -24,16 +24,16 @@ describe "as a logged in merchant" do before do - perform_login + perform_login(merchants(:merchant_2)) end it "will show order page if merchant has a product in the order" do - perform_login(merchants(:merchant_2)) get order_path(order.id) must_respond_with :success end - it "will redirect to merchant dashboard if no products for order belong to mechant" do + it "will redirect to merchant dashboard w/flashif no products for order belong to mechant" do + perform_login get order_path(order.id) expect(flash[:error]).must_equal "Can not view order page. No items sold by merchant." @@ -41,7 +41,7 @@ must_redirect_to current_merchant_path end - it "if given invalid id and user is logged in " do + it "if given invalid id and user is logged in redrect to dashboard w/ flash" do order_id = -1 get order_path(-1) From 1a2506c7ab78be0cba4e3f09a5cfa59ebb987453 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Wed, 8 May 2019 14:58:27 -0700 Subject: [PATCH 184/260] Pushing for Cloudy to look at adding links to photos --- app/assets/stylesheets/homepages.scss | 1 + app/assets/stylesheets/products.scss | 5 +++++ app/views/products/index.html.erb | 11 ++++++++++- app/views/products/show.html.erb | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 8c6d844cf4..08de0c3452 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -108,6 +108,7 @@ p { font-family: 'Raleway Dots', Arial, sans-serif; color:rgb(87, 87, 87); font-size: 1.3em; + margin: 1em; } #footer { diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss index bff386e55a..cfa8db124e 100644 --- a/app/assets/stylesheets/products.scss +++ b/app/assets/stylesheets/products.scss @@ -1,3 +1,8 @@ // 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/ + +.photo_max_size { + max-width: 25%; + max-height: 20%; +} \ No newline at end of file diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 8381d31c84..f36c37a7d6 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -2,10 +2,19 @@ <%= link_to "Add new product", new_product_path %> +
\ No newline at end of file + +
\ No newline at end of file diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 8876d0ad01..52fbe629ff 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,4 +1,4 @@ -# erased product name +

<%= @product.name %>

From 0c55d7c5d4e4684a59c8520b0b04d5ae119e22d1 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 15:23:26 -0700 Subject: [PATCH 185/260] added route and method to toggle a product retired, added temp link to product show page to test --- app/controllers/products_controller.rb | 25 ++++++++++++++++++++++++- app/views/products/show.html.erb | 2 ++ config/routes.rb | 2 ++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 85b9aa03e6..66864e5028 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,5 +1,5 @@ class ProductsController < ApplicationController - before_action :find_logged_in_merchant, only: [:new, :create, :update, :edit] + before_action :find_logged_in_merchant, only: [:new, :create, :update, :edit, :toggle_inactive] def new if @login_merchant @@ -82,6 +82,29 @@ def update end end + def toggle_inactive + @product = Product.find_by(id: params[:id]) + if @login_merchant + if @product.merchant_id == @login_merchant.id + if @product.active + @product.toggle(:active) + end + is_successful = @product.save + + if is_successful + flash[:success] = "Product retired successfully" + else + flash[:error] = "Product not retired successfully" + end + else + flash[:error] = "You may only retire your own products" + end + else + flash[:error] = "You must be logged in to retire a product" + end + redirect_to products_path + end + private def product_params diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 8876d0ad01..4d20af3dd2 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -66,3 +66,5 @@ <% if @product.merchant_id == session[:merchant_id]%> <%= link_to "Edit product", edit_product_path(@product.id) %> <% end %> + +<%= link_to "Temp toggle inactive link", { action: "toggle_inactive", id: @product.id }, method: :patch %> | \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index e1e0f26f4e..0be643a2e6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -26,5 +26,7 @@ get "/auth/:provider/callback", to: "merchants#create", as: "auth_callback" delete "/logout", to: "merchants#logout", as: "logout" + patch "products/:id/toggle_inactive", to: "products#toggle_inactive", as: "toggle_inactive" + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end From 9de24f8239c64890032479f668865b897ed5c820 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 15:27:33 -0700 Subject: [PATCH 186/260] changed product index so it only lists active products --- app/controllers/products_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 66864e5028..bae032e26d 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -34,7 +34,7 @@ def create end def index - @products = Product.all + @products = Product.where(active: true) end def show From c517caaed16561d0fe575f65da12bfebc2d9d0ee Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 15:30:03 -0700 Subject: [PATCH 187/260] product show page will flash error and redirect for a retired product --- app/controllers/products_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index bae032e26d..97144c8559 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -40,7 +40,7 @@ def index def show @product = Product.find_by(id: params[:id]) - if @product.nil? + if @product.nil? || !@product.active? # if product does not exist or it is not active (aka it is retired) flash[:error] = "Unknown product" redirect_to products_path end From 477b3e15f70ea1890d7f6c14c4823aaf56b668b1 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 15:31:09 -0700 Subject: [PATCH 188/260] updated view logic so only owner of a product can see the retire product link --- app/views/products/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 4d20af3dd2..ad7d637141 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -65,6 +65,6 @@ <% if @product.merchant_id == session[:merchant_id]%> <%= link_to "Edit product", edit_product_path(@product.id) %> + <%= link_to "Temp toggle inactive link", { action: "toggle_inactive", id: @product.id }, method: :patch %> <% end %> -<%= link_to "Temp toggle inactive link", { action: "toggle_inactive", id: @product.id }, method: :patch %> | \ No newline at end of file From d4b1286627c584f5a97d8cef3e0d64b92684aac7 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 15:40:15 -0700 Subject: [PATCH 189/260] added buttons to links for editing and retiring products --- app/views/products/show.html.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index ad7d637141..c5922fc634 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -64,7 +64,7 @@ <%= link_to "Back to all products", products_path %> <% if @product.merchant_id == session[:merchant_id]%> - <%= link_to "Edit product", edit_product_path(@product.id) %> - <%= link_to "Temp toggle inactive link", { action: "toggle_inactive", id: @product.id }, method: :patch %> + <%= link_to "Edit product", edit_product_path(@product.id), class: "btn btn-outline-primary" %> + <%= link_to "Retire product", { action: "toggle_inactive", id: @product.id }, method: :patch, class: "btn btn-outline-primary" %> <% end %> From 902d6927521f40a0d06d1bfc7e5bc62c22af8f5e Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 16:00:48 -0700 Subject: [PATCH 190/260] added table with all products to merchant show with buttons to retire a product --- app/controllers/products_controller.rb | 2 +- app/views/merchants/current.html.erb | 28 ++++++++++++++++++++++++-- app/views/products/index.html.erb | 2 +- app/views/products/show.html.erb | 5 ++++- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 97144c8559..d13c2b94a4 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -34,7 +34,7 @@ def create end def index - @products = Product.where(active: true) + @products = Product.all end def show diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index f11bc3b42d..6ce02593a9 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -56,5 +56,29 @@

Order ID: <%= @order.id %> Date & Time of order: <%= @order.created_at.strftime("%B %d, %T")%>Order Status: <%=@order.status %>
Quantity
<%end%> <%end%> - - \ No newline at end of file + +<% @products = Product.where(merchant_id: @login_merchant.id)%> +

All Products

+ + + + + + + + + + + + <% @products.each do |product|%> + + + + + + + + <%end%> + +
IDNamePriceDescriptionChange Status
<%=product.id%><%=link_to product.name, product_path(product.id) %>$<%=product.price / 100.0%><%=product.description %><%= link_to "Retire product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary" if product.active?%> + <%= link_to "Activate product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-secondary" if product.active? == false %>
\ No newline at end of file diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 8381d31c84..3f2af2e606 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -3,7 +3,7 @@ <%= link_to "Add new product", new_product_path %>
    -<% @products.each do |product| %> +<% Product.where(active: true).each do |product| %>
  • <%= link_to product.name, product_path(product.id) %>
  • diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index c5922fc634..f676c3ae96 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -65,6 +65,9 @@ <% if @product.merchant_id == session[:merchant_id]%> <%= link_to "Edit product", edit_product_path(@product.id), class: "btn btn-outline-primary" %> - <%= link_to "Retire product", { action: "toggle_inactive", id: @product.id }, method: :patch, class: "btn btn-outline-primary" %> + <% if @product.active? %> + <%= link_to "Retire product", { action: "toggle_inactive", id: @product.id }, method: :patch, class: "btn btn-outline-primary" %> + <% else %> + <%= link_to "Activate product", { action: "toggle_inactive", id: @product.id }, method: :patch, class: "btn btn-outline-primary" %> <% end %> From 24c1693a6ff9bc5c64de513cd7e093c4e2f40798 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 16:35:24 -0700 Subject: [PATCH 191/260] finished testing custom models for order --- app/models/order.rb | 15 ++++--- temp.rb | 1 + test/fixtures/merchants.yml | 7 ++++ test/fixtures/orders.yml | 2 +- test/models/order_test.rb | 80 +++++++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 9 deletions(-) create mode 100644 temp.rb diff --git a/app/models/order.rb b/app/models/order.rb index cf2e8874e7..532dbcf4bc 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -36,10 +36,10 @@ def cart_checkout # "complete" => {"15": [item11, item12, item17]} # } # to add more statuses to track follow items_hash template -> { "paid" => {}, "complete" => {} } - def self.find_merchant_order_items(merchant, items_hash: {"paid" => {}, "complete" => {}}) + def self.find_merchant_order_items(merchant, items_hash: { "paid" => {}, "complete" => {} }) Order.all.each do |order| order.items.each do |item| - if items_hash.include?(order.status) && item.product.merchant_id == merchant.id + if item && items_hash.include?(order.status) && item.product.merchant_id == merchant.id if !items_hash[order.status.to_s].include?(order.id.to_s) items_hash[order.status.to_s][order.id.to_s] = [item] else @@ -63,11 +63,10 @@ def self.status_revenue(item_status) end return revenue end -end -# takes input of items_hash["status"] where status is a status in items_hash -def self.status_count_orders(item_status) - return item_status.sum do |order_id, items| - items.count - end + # takes input of items_hash["status"] where status is a status in items_hash + def self.status_count_orders(item_status) + return 0 if !item_status + return item_status.count + end end diff --git a/temp.rb b/temp.rb new file mode 100644 index 0000000000..62d02d5528 --- /dev/null +++ b/temp.rb @@ -0,0 +1 @@ +{ "paid" => { "615724322" => [Item.find(477087474)] }, "complete" => { "1035625630" => [Item.find(845260767), Item.find(728299111)] } } diff --git a/test/fixtures/merchants.yml b/test/fixtures/merchants.yml index 51d62f0c52..67673550dc 100644 --- a/test/fixtures/merchants.yml +++ b/test/fixtures/merchants.yml @@ -11,3 +11,10 @@ merchant_2: email: lululumen@yahoo.com uid: 5435 provider: github + + +merchant_3: + username: leopoke + email: lhifi@yahoo.com + uid: 1234 + provider: github \ No newline at end of file diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index 657816b7de..c558135d06 100644 --- a/test/fixtures/orders.yml +++ b/test/fixtures/orders.yml @@ -9,7 +9,7 @@ order_1: cc_exp: 03022020 order_2: - status: complete + status: paid shopper_name: miranda shopper_email: panda@hooo.com shopper_address: 43244 tryagain address diff --git a/test/models/order_test.rb b/test/models/order_test.rb index a8021803aa..c8c9c4a566 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -106,5 +106,85 @@ expect(order.cart_checkout).must_be_nil end end + + describe "class methods " do + let(:merchant) { merchants(:merchant_2) } + let(:item_hash) { Order.find_merchant_order_items(merchant) } + describe "self.find_merchant_order_items(merchant, items_hash: {\"paid\" => {}, \"complete\" => {} })" do + it "will return a nested hash structure thatsstores merchant order items: + key is order status and value is a hash with order_id as key and array of item objects as value:" do + expect(item_hash.to_s).must_equal ({ "paid" => { "615724322" => [Item.find(477087474)] }, "complete" => { "1035625630" => [Item.find(845260767), Item.find(728299111)] } }).to_s + end + + it "will return empty hash for values with no orders in an order.status" do + expect(Order.find_merchant_order_items(merchants(:merchant_3)).to_s).must_equal ({ "paid" => {}, "complete" => {} }).to_s + end + + it "will return hash with additional statuses and add orders to them passed as params" do + expect(Order.find_merchant_order_items(merchant, items_hash: { "paid" => {}, "complete" => {}, "pending" => {} }).to_s).must_equal ({ "paid" => { "615724322" => [Item.find(477087474)] }, "complete" => { "1035625630" => [Item.find(845260767), Item.find(728299111)] }, "pending" => { "330565047" => [Item.find(34296661)] } }).to_s + end + + # NOT 100% SURE IF THESE TESTS ARE ACTUALLY TESTING WHAT THEY ARE SUPPOSED TO. + # ALSO LOTS OF CHECKS AND VAILDATIONS, SO THESE SCENARIOS WOULD NOT HAPPEN. DO # THESE EVEN HAVE TO BE TESTED? + + # it "invalid order will not be added to hash" do + # order = Order.new(status: "noneya") + # item = Item.new(product: products(:product_2), order: order, quantity: 4) + # expect(item.valid?).must_equal true + # expect(order.valid?).must_equal false + # expect(item_hash.to_s).must_equal ({ "paid" => { "615724322" => [Item.find(477087474)] }, "complete" => { "1035625630" => [Item.find(845260767), Item.find(728299111)] } }).to_s + # end + + # it "invalid item will not be added to hash" do + # items(:item_2).update(quantity: nil) + # expect(items(:item_2).valid?).must_equal false + # expect(item_hash.to_s).must_equal ({ "paid" => { "615724322" => [Item.find(477087474)] }, "complete" => { "1035625630" => [Item.find(845260767)] } }).to_s + # end + + it "invalid order will not be added to hash even if supplied the status in item_hash" do + order = Order.new(status: "noneya") + item = Item.new(product: products(:product_2), order: order, quantity: 4) + expect(item.valid?).must_equal true + expect(order.valid?).must_equal false + expect(Order.find_merchant_order_items(merchant, items_hash: { "paid" => {}, "complete" => {}, "noneya" => {} }).to_s).must_equal ({ "paid" => { "615724322" => [Item.find(477087474)] }, "complete" => { "1035625630" => [Item.find(845260767), Item.find(728299111)] }, "noneya" => {} }).to_s + end + end + + describe " def self.status_revenue(item_status)" do + let(:revenue_completed) { Order.status_revenue(item_hash["complete"]) } + + it "will calculate the sum of all the orders of a given satus" do + expect(revenue_completed).must_be_close_to Item.find(845260767).subtotal + Item.find(728299111).subtotal + end + + it "will return 0 if no items for a given status" do + Item.destroy_all + expect(revenue_completed).must_equal 0 + end + + it "will return 0 if asked for revenue of status that is not in hash" do + expect(Order.status_revenue(item_hash["not a real status"])).must_equal 0 + end + end + + describe "def self.status_count_orders(item_status)" do + it "will count all the orders of a given status " do + orders(:order_2).update(status: "complete") + expect(orders(:order_2).valid?).must_equal true + + expect(Order.status_count_orders(item_hash["complete"])).must_equal 2 + end + + it "will return 0 if no orders of a given status" do + Item.destroy_all + Order.destroy_all + expect(Order.status_count_orders(item_hash["complete"])).must_equal 0 + end + + it "will return 0 if given an empty hash (ie status not in items_hash)" do + expect(Order.status_count_orders(item_hash["no status"])).must_equal 0 + end + end + end end end From 4a4b6a88470634bd567ca91a6c22482fda07e436 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Wed, 8 May 2019 16:46:51 -0700 Subject: [PATCH 192/260] Initial implementations of flexbox. --- app/assets/stylesheets/homepages.scss | 1 + app/assets/stylesheets/products.scss | 24 ++++++++++++++++++++---- app/views/products/index.html.erb | 18 ++++++------------ 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 08de0c3452..014bcc9e4e 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -83,6 +83,7 @@ a:hover { text-align: center; } + .nav-link { color: rgba(0, 0, 0, 0.5); } diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss index cfa8db124e..ee8ca35a33 100644 --- a/app/assets/stylesheets/products.scss +++ b/app/assets/stylesheets/products.scss @@ -2,7 +2,23 @@ // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -.photo_max_size { - max-width: 25%; - max-height: 20%; -} \ No newline at end of file +img { + border: .1em #333333 solid; + max-width: 200px; + max-height: 200px; + } + + .flex-container { + display: flex; + flex-wrap: wrap; + flex-direction: row; + justify-content: space-around; + align-items: flex-start; + } + +// div.flex-item { +// display: flex; +// flex-flow: column wrap; +// max-width: 25vw; +// } + diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index f36c37a7d6..26aff20fcb 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -3,18 +3,12 @@ <%= link_to "Add new product", new_product_path %>
    -
      + <% @products.each do |product| %> -
    • - > < img src= <% product.photo_url %> alt="product photo"> - - product photo - - <%# <%= image_tag product.photo_url %> %> - - <%= link_to product.photo_url, product_path(product.id)%> - <%= link_to product.name, product_path(product.id) %> -
    • + + <%= link_to image_tag(product.photo_url), product_path(product.id) %> +

      <%= link_to product.name, product_path(product.id) %>

      +
      <% end %> -
    +
    \ No newline at end of file From e4616a85f2d5a9442e173e293249ba1d8b645cbe Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 18:20:15 -0700 Subject: [PATCH 193/260] working our what shows where --- app/controllers/products_controller.rb | 6 +++--- app/views/categories/show.html.erb | 2 +- app/views/merchants/current.html.erb | 12 +++++++----- app/views/merchants/show.html.erb | 2 +- app/views/products/show.html.erb | 9 --------- 5 files changed, 12 insertions(+), 19 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index d13c2b94a4..ce0085d023 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -40,7 +40,7 @@ def index def show @product = Product.find_by(id: params[:id]) - if @product.nil? || !@product.active? # if product does not exist or it is not active (aka it is retired) + if @product.nil? || @product.active? == false # if product does not exist or it is not active (aka it is retired) flash[:error] = "Unknown product" redirect_to products_path end @@ -50,7 +50,7 @@ def edit if @login_merchant @product = Product.find_by(id: params[:id]) - if @product.nil? + if @product.nil? || !@product.active #don't show if product is inactive/retired flash[:error] = "Unknown product" redirect_to products_path end @@ -102,7 +102,7 @@ def toggle_inactive else flash[:error] = "You must be logged in to retire a product" end - redirect_to products_path + redirect_to current_merchant_path end private diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 2a5b314d3c..9cdda4b355 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -8,7 +8,7 @@
      <% @category.product_ids.each do |product| %> -
    • <%= link_to Product.find(product).name, product_path(product)%>
    • +
    • <%= link_to Product.find(product).name, product_path(product) if Product.find(product).active? %>
    • <% end %>
    diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index 6ce02593a9..a3ad06e7ba 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -1,8 +1,8 @@

    Merchant Dashboard

    Welcome <%= @login_merchant.username %>

    -<%= link_to "Add new product", new_product_path %> -<%= link_to "Add new category", new_category_path %> +<%= link_to "Add new product", new_product_path, class: "btn btn-outline-primary" %> +<%= link_to "Add new category", new_category_path, class: "btn btn-outline-primary" %> <% item_hash = Order.find_merchant_order_items(@login_merchant) %> @@ -66,7 +66,8 @@ Name Price Description - Change Status + Active + Retire Product @@ -76,8 +77,9 @@ <%=link_to product.name, product_path(product.id) %> $<%=product.price / 100.0%> <%=product.description %> - <%= link_to "Retire product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary" if product.active?%> - <%= link_to "Activate product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-secondary" if product.active? == false %> + <%=product.active? ? "Active" : "Retired" %> + <%=link_to "Retire product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary" if product.active?%> + <%end%> diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index 4589da65c1..7a9a51d5fa 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -8,7 +8,7 @@
      <% @merchant.product_ids.each do |product| %> -
    • <%= link_to Product.find(product).name, product_path(product) %>
    • +
    • <%= link_to Product.find(product).name, product_path(product) if Product.find(product).active? %>
    • <% end %>
    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index f676c3ae96..cacf9b7ee6 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,4 +1,3 @@ -# erased product name

    <%= @product.name %>

    @@ -63,11 +62,3 @@ <%= link_to "Back to all products", products_path %> -<% if @product.merchant_id == session[:merchant_id]%> - <%= link_to "Edit product", edit_product_path(@product.id), class: "btn btn-outline-primary" %> - <% if @product.active? %> - <%= link_to "Retire product", { action: "toggle_inactive", id: @product.id }, method: :patch, class: "btn btn-outline-primary" %> - <% else %> - <%= link_to "Activate product", { action: "toggle_inactive", id: @product.id }, method: :patch, class: "btn btn-outline-primary" %> -<% end %> - From 7972f36713bf25c46c75ba42be254dbf91cd5e13 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 18:31:36 -0700 Subject: [PATCH 194/260] sorted products table on merchant dash by active or retired --- app/views/merchants/current.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index a3ad06e7ba..37365dc2c0 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -57,7 +57,7 @@ <%end%> <%end%> -<% @products = Product.where(merchant_id: @login_merchant.id)%> +<% @products = Product.where(merchant_id: @login_merchant.id).order(:active).reverse %>

    All Products

    From 7b2a13a26f4a1a79d40dbbde41a3e3a1a9e9dcd5 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 18:39:46 -0700 Subject: [PATCH 195/260] added funtionality to reactivate a product and changed language of flash to reflect that --- app/controllers/products_controller.rb | 13 ++++++------- app/views/merchants/current.html.erb | 1 + 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index ce0085d023..2ce6672931 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -86,21 +86,20 @@ def toggle_inactive @product = Product.find_by(id: params[:id]) if @login_merchant if @product.merchant_id == @login_merchant.id - if @product.active - @product.toggle(:active) - end + @product.active? + @product.toggle(:active) is_successful = @product.save if is_successful - flash[:success] = "Product retired successfully" + flash[:success] = "Product status changed successfully" else - flash[:error] = "Product not retired successfully" + flash[:error] = "Product status not changed successfully" end else - flash[:error] = "You may only retire your own products" + flash[:error] = "You may only change the status of your own products" end else - flash[:error] = "You must be logged in to retire a product" + flash[:error] = "You must be logged in to change the status of a product" end redirect_to current_merchant_path end diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index 37365dc2c0..fb1f006f20 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -79,6 +79,7 @@ <%end%> From b88de077357b73cb4a30ee4bddd5f0d7565399d9 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 18:59:17 -0700 Subject: [PATCH 196/260] tests for logged in user --- test/controllers/products_controller_test.rb | 43 ++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index 52753e1ddb..a2ea554cde 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -196,4 +196,47 @@ # I think this is covered in the edit tests since users cannot get to the edit page if they are not logged in. Let me know if I need to test this. end end + + describe "toggle inactive" do + describe "logged in merchant" do + it "changes active from true to false and false to true" do + # Change from true to false + perform_login(merchants(:merchant_2)) + product = products(:product_1) + + patch toggle_inactive_path(product.id) + product.reload + + expect(product.active).must_equal false + must_redirect_to current_merchant_path + expect(flash[:success]).must_equal "Product status changed successfully" + + # Change back from false back to true + patch toggle_inactive_path(product.id) + + product.reload + + expect(product.active).must_equal true + must_redirect_to current_merchant_path + expect(flash[:success]).must_equal "Product status changed successfully" + end + + # it "changes active from false to true" do + # # Arrange + # product = products(:product_1) + # patch toggle_inactive_path(product.id) + + # # Act + # product.reload + + # # Assert + # expect(product.active).must_equal true + # must_redirect_to current_merchant_path + # expect(flash[:success]).must_equal "Product updated successfully" + # end + end + + describe "logged out" do + end + end end From d22cacfd2cdbd43d5bd84385ded796c8b9645231 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 19:04:25 -0700 Subject: [PATCH 197/260] finished tests for toggle_inactive --- test/controllers/products_controller_test.rb | 37 +++++++++++++------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index a2ea554cde..ee2bfa7c28 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -199,7 +199,7 @@ describe "toggle inactive" do describe "logged in merchant" do - it "changes active from true to false and false to true" do + it "can change status for their products active from true to false and false to true" do # Change from true to false perform_login(merchants(:merchant_2)) product = products(:product_1) @@ -208,6 +208,7 @@ product.reload expect(product.active).must_equal false + must_respond_with :redirect must_redirect_to current_merchant_path expect(flash[:success]).must_equal "Product status changed successfully" @@ -217,26 +218,38 @@ product.reload expect(product.active).must_equal true + must_respond_with :redirect must_redirect_to current_merchant_path expect(flash[:success]).must_equal "Product status changed successfully" end - # it "changes active from false to true" do - # # Arrange - # product = products(:product_1) - # patch toggle_inactive_path(product.id) + it "cannot change status of another merchants product" do + perform_login(merchants(:merchant_1)) #not the creator of product_1 + product = products(:product_1) - # # Act - # product.reload + patch toggle_inactive_path(product.id) + product.reload - # # Assert - # expect(product.active).must_equal true - # must_redirect_to current_merchant_path - # expect(flash[:success]).must_equal "Product updated successfully" - # end + expect(product.active).must_equal true + must_respond_with :redirect + must_redirect_to current_merchant_path + expect(flash[:error]).must_equal "You may only change the status of your own products" + end end describe "logged out" do + it "cannot change status from true to false" do + # do not perform login + product = products(:product_1) + + patch toggle_inactive_path(product.id) + product.reload + + expect(product.active).must_equal true + must_respond_with :redirect + must_redirect_to current_merchant_path + expect(flash[:error]).must_equal "You must be logged in to change the status of a product" + end end end end From ef24fe94264ab9cef77cf65c902a56de8a74b6d4 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 19:06:33 -0700 Subject: [PATCH 198/260] removed add product from products page since its in the merchant dash now --- app/views/products/index.html.erb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 3f2af2e606..2cda55eedf 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,7 +1,5 @@

    Products

    -<%= link_to "Add new product", new_product_path %> -
      <% Product.where(active: true).each do |product| %>
    • From 046579fd0d979162185c3eaa9e15f2e176da1f9b Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 19:32:18 -0700 Subject: [PATCH 199/260] fixed type in show, made sure all prices are showing like money should on mech dash --- app/views/merchants/current.html.erb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index fb1f006f20..ab115d6320 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -9,15 +9,15 @@

      Paid orders

      • Total number of paid orders: <%= item_hash["paid"].count %>
      • -
      • Revenue for paid orders: $<%= Order.status_revenue(item_hash["paid"])%>
      • +
      • Revenue for paid orders: $<%= "%.2f" % Order.status_revenue(item_hash["paid"])%>

      Complete orders

        -
      • Total number of paid orders: <%= item_hash["complete"].count %>
      • -
      • Revenue for paid orders: $<%= Order.status_revenue(item_hash["complete"])%>
      • +
      • Total number of complete orders: <%= item_hash["complete"].count %>
      • +
      • Revenue for complete orders: $<%= "%.2f" % Order.status_revenue(item_hash["complete"])%>

      Total revenue

      -

      $<%= Order.status_revenue(item_hash["paid"]) + Order.status_revenue(item_hash["completed"])%>

      +

      $<%= "%.2f" % ( Order.status_revenue(item_hash["paid"]) + Order.status_revenue(item_hash["completed"]))%>

      Orders by status

      <%["paid", "complete"].each do |status|%> @@ -26,7 +26,7 @@
    <%=product.description %> <%=product.active? ? "Active" : "Retired" %> <%=link_to "Retire product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary" if product.active?%> + <%=link_to "Activate product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary" if product.active? == false%>
    - + @@ -75,7 +75,7 @@ - + + @@ -79,8 +80,8 @@ + <%=link_to "Activate product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary" if product.active? == false%> + <%end%> diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb index a075f43368..42d3e59dcf 100644 --- a/app/views/products/edit.html.erb +++ b/app/views/products/edit.html.erb @@ -1,4 +1,4 @@ -

    Form for editing a new product

    +

    Form for editing a product

    <%= render partial: "form", locals: { From 5b94a1c3a63bda667e8ca63e978205f1b5269407 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 19:46:12 -0700 Subject: [PATCH 201/260] made sure money displayed with 2 places after the decimal on order confirmation --- app/views/orders/confirmation.html.erb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/orders/confirmation.html.erb b/app/views/orders/confirmation.html.erb index b96abaf248..fb77cd481d 100644 --- a/app/views/orders/confirmation.html.erb +++ b/app/views/orders/confirmation.html.erb @@ -21,15 +21,15 @@ - - + + <%end%> <%# REMOVE h3, temp added to get a feel for style%> - +
    Order ID: <%= order %> <%= link_to "Order ID: #{Order.find(order).id}", order_path(Order.find(order).id) %> Date & Time of order: <%= Order.find(order).created_at.strftime("%B %d, %T")%> Order Status: <%= Order.find(order).status %>
    <%=product.id%> <%=link_to product.name, product_path(product.id) %>$<%=product.price / 100.0%>$<%= "%.2f" % (product.price / 100.0)%> <%=product.description %> <%=product.active? ? "Active" : "Retired" %> <%=link_to "Retire product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary" if product.active?%> From 7d6ace8c23690187164bcf11edab9a621f1d8c31 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 19:42:16 -0700 Subject: [PATCH 200/260] added link to update a product from the merchant dashboard, fixed typo in edit product form --- app/views/merchants/current.html.erb | 5 +++-- app/views/products/edit.html.erb | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index ab115d6320..9b23cd5362 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -68,6 +68,7 @@ Description Active Retire ProductEdit Product
    <%=product.description %> <%=product.active? ? "Active" : "Retired" %> <%=link_to "Retire product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary" if product.active?%> - <%=link_to "Activate product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary" if product.active? == false%> - <%=link_to "Edit product", edit_product_path(product.id), class: "btn btn-outline-primary" if product.active?%>
    <%=item.quantity%> <%=link_to item.product.name, product_path(item.product.id) %>$<%=item.product.price / 100.0%>$<%=item.subtotal %>$<%= "%.2f" % (item.product.price / 100.0)%>$<%= "%.2f" % item.subtotal %>

    Total:

    $<%=@order.total%>

    $<%= "%.2f" % @order.total%>

    \ No newline at end of file From 7e8b29830206c4e6a39b196f95137cc001b52e22 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 19:55:58 -0700 Subject: [PATCH 202/260] added link to category page from categories on product page --- app/views/products/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index cacf9b7ee6..2b9660a0ed 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -25,7 +25,7 @@
      <% @product.categories.each do |category| %> -
    • <%= category.name %>
    • +
    • <%= link_to category.name, category_path(category.id) %>
    • <% end %>
    From 7b3f990c864f385899adc16cd4c3467edaee2c97 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Wed, 8 May 2019 20:16:12 -0700 Subject: [PATCH 203/260] added test for merchant cannot update prodcut that is not theirs --- test/controllers/products_controller_test.rb | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index ee2bfa7c28..9e05272172 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -190,6 +190,30 @@ must_respond_with :bad_request expect(flash[:name]).must_include "can't be blank" end + + it "can only update their own products" do + merchant = perform_login(merchants(:merchant_1)) + product_to_update = products(:product_1) #does not belong to merchant 1 + + test_input = { + "product": { + name: "A really nice new thing", + merchant_id: merchant.id, + description: "nice stuff wooowza", + photo_url: "https://yeahforsure.org", + stock: 100, + price: 999, + }, + } + + expect { + patch product_path(product_to_update.id), params: test_input + }.wont_change "Product.count" + + must_respond_with :redirect + must_redirect_to products_path + expect(flash[:error]).must_equal "You can only update your own products" + end end describe "not logged in" do From cf7c4cf8167d27e882865a934776973dcb005888 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 21:43:03 -0700 Subject: [PATCH 204/260] created button on dashboard that sends info, creating update controller for orders --- app/controllers/orders_controller.rb | 5 ++++- app/views/merchants/current.html.erb | 2 +- config/routes.rb | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index b56fbe8749..463b6d83b4 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -15,6 +15,9 @@ def show end end + def update + end + def view_cart end @@ -60,6 +63,6 @@ def purchase # only partial params, update if more attributes are required. def order_params - params.require(:order).permit(:shopper_name, :shopper_email, :shopper_address, :cc_exp) + params.require(:order).permit(:shopper_name, :shopper_email, :shopper_address, :cc_exp, :status) end end diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index 9b23cd5362..50a522ccd7 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -49,7 +49,7 @@ <%=link_to item.product.name, product_path(item.product.id) %> $<%=item.product.price / 100.0%> $<%=item.subtotal %> - placeholder for ship button + <%=link_to "SHIP ORDER", order_path(order.to_i, status: "complete"), method: :patch, class: "btn btn-sm btn-danger"%> <%end%> diff --git a/config/routes.rb b/config/routes.rb index 0be643a2e6..56de6b6f60 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,7 +4,7 @@ resources :categories, only: [:new, :create, :index, :show] resources :items, only: [:create, :update, :destroy] resources :merchants, only: [:index, :create, :show] - resources :orders, only: [:show] + resources :orders, only: [:show, :update] get "/cart", to: "orders#view_cart", as: "cart" get "/cart/checkout", to: "orders#checkout", as: "checkout_cart" From ec275e52433eaf4d4158c6589106e367d0c2641a Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 22:09:10 -0700 Subject: [PATCH 205/260] fixed patch verb for purchase (sidetracked) --- app/controllers/orders_controller.rb | 11 ++++++++++- app/views/merchants/current.html.erb | 2 +- config/routes.rb | 2 +- test/controllers/orders_controller_test.rb | 22 +++++++++++----------- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 463b6d83b4..a436ebea8c 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,6 +1,6 @@ class OrdersController < ApplicationController before_action :find_cart_order, except: [:show, :index] - before_action :find_logged_in_merchant, only: [:show] + before_action :find_logged_in_merchant, only: [:show, :update] def show if @login_merchant @@ -16,6 +16,15 @@ def show end def update + @order = Order.find_by(id: params[:id]) + raise + if !@login_merchant || !@order || !@order.items.any? { |item| item.product.merchant_id == @login_merchant.id } || @order.update(status: params[:status]) + flash[:error] = "Can not update order" + redirect_to root_path + else + flash[:sucess] = "Order updated" + redirect_to current_merchant_path + end end def view_cart diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index 50a522ccd7..a34b922bc1 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -49,7 +49,7 @@ <%=link_to item.product.name, product_path(item.product.id) %> $<%=item.product.price / 100.0%> $<%=item.subtotal %> - <%=link_to "SHIP ORDER", order_path(order.to_i, status: "complete"), method: :patch, class: "btn btn-sm btn-danger"%> + <%=link_to "SHIP ORDER", order_path(order.to_i, {order: {status: "complete"}}), method: :patch, class: "btn btn-sm btn-danger"%> <%end%> diff --git a/config/routes.rb b/config/routes.rb index 56de6b6f60..bff3b320f5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,7 +8,7 @@ get "/cart", to: "orders#view_cart", as: "cart" get "/cart/checkout", to: "orders#checkout", as: "checkout_cart" - post "/cart", to: "orders#purchase", as: "purchase_cart" + patch "/cart", to: "orders#purchase", as: "purchase_cart" get "/cart/:id", to: "orders#confirmation", as: "order_confirmation" # Is this correct? -mf diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 1e2fb75896..d3d0ef4012 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -86,7 +86,7 @@ end describe "following succesful purchase of cart" do before do - post purchase_cart_path, params: cart_params + patch purchase_cart_path, params: cart_params end it "will respond with success" do get order_confirmation_path(@order.id) @@ -153,7 +153,7 @@ expect(session[:cart_id]).wont_be_nil expect { - post purchase_cart_path, params: cart_params + patch purchase_cart_path, params: cart_params }.wont_change "Order.count" expect(session[:cart_id]).must_be_nil @@ -164,7 +164,7 @@ order_id = session[:cart_id] expect { - post purchase_cart_path, params: cart_params + patch purchase_cart_path, params: cart_params }.wont_change "Order.count" expect(session[:confirmation]).must_equal order_id @@ -175,7 +175,7 @@ expect(order.status).must_equal "pending" expect { - post purchase_cart_path, params: cart_params + patch purchase_cart_path, params: cart_params }.wont_change "Order.count" order.reload expect(order.status).must_equal "paid" @@ -185,7 +185,7 @@ product_stock = product.stock + product2.stock expect { - post purchase_cart_path, params: cart_params + patch purchase_cart_path, params: cart_params }.wont_change "Order.count" product.reload product2.reload @@ -194,7 +194,7 @@ it "will have flash message and redirect to correct page if valid cart purchase" do expect { - post purchase_cart_path, params: cart_params + patch purchase_cart_path, params: cart_params }.wont_change "Order.count" order = Order.find_by(shopper_address: "44550 mailing address") @@ -222,7 +222,7 @@ it "will have flash message and redirect to correct page if invalid cart purchase" do expect { - post purchase_cart_path, params: cart_params + patch purchase_cart_path, params: cart_params }.wont_change "Order.count" expect(flash[:error]).must_equal "Unable to checkout cart" @@ -236,7 +236,7 @@ expect(order.status).must_equal "pending" expect { - post purchase_cart_path, params: cart_params + patch purchase_cart_path, params: cart_params }.wont_change "Order.count" expect(order.status).must_equal "pending" @@ -246,7 +246,7 @@ product_stock = product.stock + product2.stock expect { - post purchase_cart_path, params: cart_params + patch purchase_cart_path, params: cart_params }.wont_change "Order.count" product.reload @@ -257,7 +257,7 @@ it "will not change cart in session if invalid cart" do expect(session[:cart_id]).wont_be_nil expect { - post purchase_cart_path, params: cart_params + patch purchase_cart_path, params: cart_params }.wont_change "Order.count" expect(session[:cart_id]).wont_be_nil end @@ -266,7 +266,7 @@ expect(session[:confirmation]).must_be_nil expect { - post purchase_cart_path, params: cart_params + patch purchase_cart_path, params: cart_params }.wont_change "Order.count" expect(session[:confirmation]).must_be_nil From 33ca49f27a35ac26b6335f76259423effa59232e Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 23:11:25 -0700 Subject: [PATCH 206/260] finished shipping button with tests for merchant dashboard --- app/controllers/orders_controller.rb | 11 ++-- app/views/merchants/current.html.erb | 10 ++-- app/views/orders/_order_form.html.erb | 2 +- test/controllers/orders_controller_test.rb | 58 ++++++++++++++++++++++ 4 files changed, 72 insertions(+), 9 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index a436ebea8c..3a5c50223b 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -17,8 +17,7 @@ def show def update @order = Order.find_by(id: params[:id]) - raise - if !@login_merchant || !@order || !@order.items.any? { |item| item.product.merchant_id == @login_merchant.id } || @order.update(status: params[:status]) + if !@login_merchant || !@order || !@order.items.any? { |item| item.product.merchant_id == @login_merchant.id } || !@order.update(order_params) flash[:error] = "Can not update order" redirect_to root_path else @@ -48,9 +47,8 @@ def checkout end def purchase - if @order && @order.update(order_params) && @order.cart_errors.empty? + if @order && @order.update(order_params) && @order.cart_errors.empty? && @order.update(status: "paid") @order.cart_checkout - @order.update(status: "paid", cc_four: params[:order][:cc_all][-4..-1]) # front end valid. on form for min 4 chars session[:confirmation] = session[:cart_id] session[:cart_id] = nil flash[:success] = "Purchase Successful" @@ -72,6 +70,9 @@ def purchase # only partial params, update if more attributes are required. def order_params - params.require(:order).permit(:shopper_name, :shopper_email, :shopper_address, :cc_exp, :status) + if params[:order][:cc_all] + params[:order][:cc_four] = params[:order][:cc_all][-4..-1] # front-end validation requires min 4 char input. + end + params.require(:order).permit(:shopper_name, :shopper_email, :shopper_address, :cc_exp, :cc_four, :status) end end diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index a34b922bc1..0c5435139e 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -39,7 +39,9 @@ Product Name Unit Price Subtotal - Mark as Shipped + <% if status == "paid"%> + Mark as Shipped + <%end%> @@ -48,8 +50,10 @@ <%=item.quantity%> <%=link_to item.product.name, product_path(item.product.id) %> $<%=item.product.price / 100.0%> - $<%=item.subtotal %> - <%=link_to "SHIP ORDER", order_path(order.to_i, {order: {status: "complete"}}), method: :patch, class: "btn btn-sm btn-danger"%> + $<%=item.subtotal %> + <% if status == "paid"%> + <%=link_to "SHIP ORDER", order_path(order.to_i, {order: {status: "complete"}}), method: :patch, class: "btn btn-sm btn-danger"%> + <%end%> <%end%> diff --git a/app/views/orders/_order_form.html.erb b/app/views/orders/_order_form.html.erb index 36edb7791f..c5276dcc37 100644 --- a/app/views/orders/_order_form.html.erb +++ b/app/views/orders/_order_form.html.erb @@ -28,7 +28,7 @@ -<%= form_with model: @order, url: cart_path, method: :post do |f|%> +<%= form_with model: @order, url: cart_path(), method: :patch do |f|%>
    <%=f.label "Name on Credit Card"%> diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index d3d0ef4012..ebcd668270 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -51,6 +51,64 @@ end end end + + describe "update" do + let(:order) { orders(:order_2) } + let(:order_params) { { order: { status: "complete" } } } + describe "not logged in user" do + it "will redirect home with flash and NOT update order" do + expect(order.status).must_equal "paid" + expect { + patch order_path(order.id), params: order_params + }.wont_change "Order.count" + order.reload + expect(order.status).must_equal "paid" + must_respond_with :redirect + must_redirect_to root_path + end + end + + describe "as a loggedd in merchant" do + before do + perform_login(merchants(:merchant_2)) + end + it "will update order if merchant has items on order and order is valid" do + expect(order.status).must_equal "paid" + expect { + patch order_path(order.id), params: order_params + }.wont_change "Order.count" + order.reload + expect(order.status).must_equal "complete" + must_respond_with :redirect + must_redirect_to current_merchant_path + end + + it "will not update if merchant does not have items on order" do + perform_login + expect(order.status).must_equal "paid" + + expect { + patch order_path(order.id), params: order_params + }.wont_change "Order.count" + + order.reload + + expect(order.status).must_equal "paid" + must_respond_with :redirect + must_redirect_to root_path + end + + it "will redriect home with flash if order is not valid" do + invalid_id = -1 + expect { + patch order_path(-1), params: order_params + }.wont_change "Order.count" + + must_respond_with :redirect + must_redirect_to root_path + end + end + end describe "view_cart" do it "will respond with success if no cart is stored in session" do get cart_path From 78fc6d333bb550f956f82cb2f26ee2e63ac8fcaa Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 23:18:17 -0700 Subject: [PATCH 207/260] added tests for flash msgs --- app/controllers/orders_controller.rb | 2 +- test/controllers/orders_controller_test.rb | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 3a5c50223b..00c117e5ab 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -21,7 +21,7 @@ def update flash[:error] = "Can not update order" redirect_to root_path else - flash[:sucess] = "Order updated" + flash[:success] = "Order updated" redirect_to current_merchant_path end end diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index ebcd668270..01fe211566 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -58,11 +58,16 @@ describe "not logged in user" do it "will redirect home with flash and NOT update order" do expect(order.status).must_equal "paid" + expect { patch order_path(order.id), params: order_params }.wont_change "Order.count" + order.reload + expect(order.status).must_equal "paid" + expect(flash[:error]).must_equal "Can not update order" + must_respond_with :redirect must_redirect_to root_path end @@ -77,7 +82,10 @@ expect { patch order_path(order.id), params: order_params }.wont_change "Order.count" + order.reload + + expect(flash[:success]).must_equal "Order updated" expect(order.status).must_equal "complete" must_respond_with :redirect must_redirect_to current_merchant_path @@ -94,6 +102,7 @@ order.reload expect(order.status).must_equal "paid" + expect(flash[:error]).must_equal "Can not update order" must_respond_with :redirect must_redirect_to root_path end @@ -103,7 +112,7 @@ expect { patch order_path(-1), params: order_params }.wont_change "Order.count" - + expect(flash[:error]).must_equal "Can not update order" must_respond_with :redirect must_redirect_to root_path end From cc9eb76513fc132d689c4377a4a9a41bebbaaf0f Mon Sep 17 00:00:00 2001 From: qqdipps Date: Wed, 8 May 2019 23:42:30 -0700 Subject: [PATCH 208/260] added boot strap to in pg show product form for add to cart and reviews --- app/views/items/_item_form.html.erb | 9 +++++---- app/views/reviews/_review_form.html.erb | 24 +++++++++++++----------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/app/views/items/_item_form.html.erb b/app/views/items/_item_form.html.erb index 18d5855834..1b727368ad 100644 --- a/app/views/items/_item_form.html.erb +++ b/app/views/items/_item_form.html.erb @@ -1,10 +1,11 @@ <%=form_with model: Item.new() , url: product_items_path(@product.id) do |f| %> -
    + +
    <%= f.label :Quantity%> - <%= f.number_field :quantity, required: true, in: 1..@product.stock%> + <%= f.number_field :quantity, required: true, in: 1..@product.stock, class: "form-control"%>
    -
    - <%= f.submit "Add To Cart" %> +
    + <%= f.submit "Add To Cart", class: "btn btn-sm btn-primary" %>
    <%end%> \ No newline at end of file diff --git a/app/views/reviews/_review_form.html.erb b/app/views/reviews/_review_form.html.erb index 5df367d2f5..aa0a57a40c 100644 --- a/app/views/reviews/_review_form.html.erb +++ b/app/views/reviews/_review_form.html.erb @@ -1,14 +1,16 @@ <%=form_with model: Review.new() , url: product_reviews_path(@product.id) do |f| %> -
    - <%= f.label :rating%> - <%= f.number_field :rating, required: true, in: 1..5%> -
    -
    - <%= f.label :comment%> - <%=f.text_area :comment%> -
    -
    - <%= f.submit %> -
    +<%#
    %> +
    + <%= f.label :rating%> + <%= f.number_field :rating, required: true, in: 1..5, class: "form-control"%> +
    +
    + <%= f.label :comment%> + <%=f.text_area :comment, class: "form-control"%> +
    +
    + <%= f.submit class:"btn btn-sm btn-primary" %> +
    +<%#
    %> <%end%> \ No newline at end of file From a9a4afbee252a6b014a48b8c7a9c08db9261c544 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 9 May 2019 00:01:14 -0700 Subject: [PATCH 209/260] refactored partial form item_form to be adated for update action in cart --- app/views/items/_item_form.html.erb | 4 ++-- app/views/orders/view_cart.html.erb | 4 +++- app/views/products/create.html.erb | 2 -- app/views/products/show.html.erb | 4 ++-- app/views/products/update.html.erb | 2 -- 5 files changed, 7 insertions(+), 9 deletions(-) delete mode 100644 app/views/products/create.html.erb delete mode 100644 app/views/products/update.html.erb diff --git a/app/views/items/_item_form.html.erb b/app/views/items/_item_form.html.erb index 18d5855834..14466564e1 100644 --- a/app/views/items/_item_form.html.erb +++ b/app/views/items/_item_form.html.erb @@ -1,10 +1,10 @@ -<%=form_with model: Item.new() , url: product_items_path(@product.id) do |f| %> +<%=form_with model: item , url: product_items_path(@product.id), method: method_verb do |f| %>
    <%= f.label :Quantity%> <%= f.number_field :quantity, required: true, in: 1..@product.stock%>
    - <%= f.submit "Add To Cart" %> + <%= f.submit action %>
    <%end%> \ No newline at end of file diff --git a/app/views/orders/view_cart.html.erb b/app/views/orders/view_cart.html.erb index fa3514c821..186bb514f2 100644 --- a/app/views/orders/view_cart.html.erb +++ b/app/views/orders/view_cart.html.erb @@ -7,7 +7,9 @@

    <%=item.product.description%>

    quantity: <%=item.quantity%>

    subtotal: $<%=item.subtotal%> - <%= link_to "Remove item", item_path(item.id), method: :delete, class: "btn btn-outline-danger btn-sm"%> + <% @product = item.product %> + <%= render partial: "/items/item_form", locals: {item: item, method_verb: :patch, action: "Update Quantity"} %> + <%= link_to "Remove item", item_path(item.id), method: :delete, class: "btn btn-secondary btn-sm"%> <%end%> <%= link_to "Check Out", checkout_cart_path, class: "btn btn-primary"%> diff --git a/app/views/products/create.html.erb b/app/views/products/create.html.erb deleted file mode 100644 index d546021001..0000000000 --- a/app/views/products/create.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -

    Products#create

    -

    Find me in app/views/products/create.html.erb

    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 2b9660a0ed..7047ec2908 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -54,10 +54,10 @@ <% end %>

- <%= render "/reviews/review_form"%> + <%= render partial: "/reviews/review_form"%>
- <%= render "/items/item_form"%> + <%= render partial: "/items/item_form", locals: {item: Item.new, method_verb: :post, action: "Add to Cart"} %>
<%= link_to "Back to all products", products_path %> diff --git a/app/views/products/update.html.erb b/app/views/products/update.html.erb deleted file mode 100644 index 039889ac02..0000000000 --- a/app/views/products/update.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -

Products#update

-

Find me in app/views/products/update.html.erb

From 6fa5aab02f0bb7bee882e60a8adc4e0e8dcbb578 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 9 May 2019 00:05:26 -0700 Subject: [PATCH 210/260] refactored routes --- app/controllers/items_controller.rb | 1 + app/views/orders/view_cart.html.erb | 2 +- config/routes.rb | 11 +++-------- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index b1764fd622..1d4577e9ef 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -45,6 +45,7 @@ def create end def update + raise end def destroy diff --git a/app/views/orders/view_cart.html.erb b/app/views/orders/view_cart.html.erb index 186bb514f2..5ca1ada937 100644 --- a/app/views/orders/view_cart.html.erb +++ b/app/views/orders/view_cart.html.erb @@ -8,7 +8,7 @@

quantity: <%=item.quantity%>

subtotal: $<%=item.subtotal%> <% @product = item.product %> - <%= render partial: "/items/item_form", locals: {item: item, method_verb: :patch, action: "Update Quantity"} %> + <%= render partial: "/items/item_form", locals: {item: item, method_verb: :patch, action: "Update"} %> <%= link_to "Remove item", item_path(item.id), method: :delete, class: "btn btn-secondary btn-sm"%> <%end%> diff --git a/config/routes.rb b/config/routes.rb index 0be643a2e6..2588e9457d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,7 +2,7 @@ get "/merchants/current", to: "merchants#current", as: "current_merchant" get "homepages/index" resources :categories, only: [:new, :create, :index, :show] - resources :items, only: [:create, :update, :destroy] + resources :items, only: [:destroy] resources :merchants, only: [:index, :create, :show] resources :orders, only: [:show] @@ -11,16 +11,11 @@ post "/cart", to: "orders#purchase", as: "purchase_cart" get "/cart/:id", to: "orders#confirmation", as: "order_confirmation" - # Is this correct? -mf - resources :categories do - resources :products, only: [:index] - end - resources :products, except: [:destroy] do resources :reviews, only: [:create] - resources :items, only: [:create] + resources :items, only: [:create, :update] end - + root to: "homepages#index" get "/auth/github", as: "github_login" get "/auth/:provider/callback", to: "merchants#create", as: "auth_callback" From 17166529e6ffbc03a476e63301f4a1f60700d9ae Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 9 May 2019 00:19:16 -0700 Subject: [PATCH 211/260] set up test scaffolding and logic for controller --- app/controllers/items_controller.rb | 9 ++++++++- app/views/items/_item_form.html.erb | 2 +- app/views/orders/view_cart.html.erb | 2 +- app/views/products/show.html.erb | 3 ++- config/routes.rb | 5 +++-- test/controllers/items_controller_test.rb | 16 ++++++++++++++++ 6 files changed, 31 insertions(+), 6 deletions(-) diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index 1d4577e9ef..37476c53b3 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -45,7 +45,14 @@ def create end def update - raise + item = Item.find_by(id: params[:id]) + if item && item.update(item_params) && item.available_for_purchase? + flash[:success] = "#{item.product.name} successfully updated" + redirect_to cart_path + else + flash[:error] = "Unable to update item" + redirect_to cart_path + end end def destroy diff --git a/app/views/items/_item_form.html.erb b/app/views/items/_item_form.html.erb index 14466564e1..4303396638 100644 --- a/app/views/items/_item_form.html.erb +++ b/app/views/items/_item_form.html.erb @@ -1,5 +1,5 @@ -<%=form_with model: item , url: product_items_path(@product.id), method: method_verb do |f| %> +<%=form_with model: item , url: url_path, method: method_verb do |f| %>

<%= f.label :Quantity%> <%= f.number_field :quantity, required: true, in: 1..@product.stock%> diff --git a/app/views/orders/view_cart.html.erb b/app/views/orders/view_cart.html.erb index 5ca1ada937..70895334c4 100644 --- a/app/views/orders/view_cart.html.erb +++ b/app/views/orders/view_cart.html.erb @@ -8,7 +8,7 @@

quantity: <%=item.quantity%>

subtotal: $<%=item.subtotal%> <% @product = item.product %> - <%= render partial: "/items/item_form", locals: {item: item, method_verb: :patch, action: "Update"} %> + <%= render partial: "/items/item_form", locals: {item: item, method_verb: :patch, action: "Update", url_path: item_path(item.id)} %> <%= link_to "Remove item", item_path(item.id), method: :delete, class: "btn btn-secondary btn-sm"%> <%end%> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 7047ec2908..168f11faf8 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -57,7 +57,8 @@ <%= render partial: "/reviews/review_form"%>

- <%= render partial: "/items/item_form", locals: {item: Item.new, method_verb: :post, action: "Add to Cart"} %> + <%= render partial: "/items/item_form", locals: {item: Item.new, method_verb: :post, + action: "Add to Cart", url_path: product_items_path(@product.id)} %>
<%= link_to "Back to all products", products_path %> diff --git a/config/routes.rb b/config/routes.rb index 2588e9457d..fe215a41b9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,8 +1,9 @@ Rails.application.routes.draw do get "/merchants/current", to: "merchants#current", as: "current_merchant" get "homepages/index" + resources :categories, only: [:new, :create, :index, :show] - resources :items, only: [:destroy] + resources :items, only: [:update, :destroy] resources :merchants, only: [:index, :create, :show] resources :orders, only: [:show] @@ -15,7 +16,7 @@ resources :reviews, only: [:create] resources :items, only: [:create, :update] end - + root to: "homepages#index" get "/auth/github", as: "github_login" get "/auth/:provider/callback", to: "merchants#create", as: "auth_callback" diff --git a/test/controllers/items_controller_test.rb b/test/controllers/items_controller_test.rb index a726b408cc..922a35a522 100644 --- a/test/controllers/items_controller_test.rb +++ b/test/controllers/items_controller_test.rb @@ -92,6 +92,22 @@ end end + describe "update" do + let(:item) { items(:item_1) } + let(:item_params) { { item: { quantity: 2 } } } + it "will update a valid item if product has enough stock" do + expect{ + patch item_path(item.id) + } + end + + it "will not update a product if update of quantity exceeds product stock" do + end + + it "will show flash message and redirect updated item is invalid/ item not found" do + end + end + describe "destroy" do let(:item) { items(:item_1) } it "will destroy a valid item" do From a7a9ce95ab3a087cc2fede5190584de477318bb8 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 9 May 2019 00:25:51 -0700 Subject: [PATCH 212/260] finished testing for items update --- test/controllers/items_controller_test.rb | 36 ++++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/test/controllers/items_controller_test.rb b/test/controllers/items_controller_test.rb index 922a35a522..1b902738b5 100644 --- a/test/controllers/items_controller_test.rb +++ b/test/controllers/items_controller_test.rb @@ -96,15 +96,43 @@ let(:item) { items(:item_1) } let(:item_params) { { item: { quantity: 2 } } } it "will update a valid item if product has enough stock" do - expect{ - patch item_path(item.id) - } + expect { + patch item_path(item.id), params: item_params + }.wont_change "Item.count" + must_respond_with :redirect + must_redirect_to cart_path + expect(flash[:success]).must_equal "#{item.product.name} successfully updated" end it "will not update a product if update of quantity exceeds product stock" do + products(:product_1).update(stock: 1) + + expect { + patch item_path(item.id), params: item_params + }.wont_change "Item.count" + must_respond_with :redirect + must_redirect_to cart_path + expect(flash[:error]).must_equal "Unable to update item" + end + + it "will show flash message and redirect updated item is invalid" do + item_params[:item][:quantity] = -1 + expect { + patch item_path(item.id), params: item_params + }.wont_change "Item.count" + must_respond_with :redirect + must_redirect_to cart_path + expect(flash[:error]).must_equal "Unable to update item" end - it "will show flash message and redirect updated item is invalid/ item not found" do + it "will show flash message and redirect if item is not found " do + invalid_id = -1 + expect { + patch item_path(invalid_id), params: item_params + }.wont_change "Item.count" + must_respond_with :redirect + must_redirect_to cart_path + expect(flash[:error]).must_equal "Unable to update item" end end From 1493820b19e1ed8e098a8822e97f24d05f11cedb Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 9 May 2019 09:32:18 -0700 Subject: [PATCH 213/260] changed shipping location --- app/views/merchants/current.html.erb | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index 0c5435139e..1b097b36cf 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -30,7 +30,11 @@ Date & Time of order: <%= Order.find(order).created_at.strftime("%B %d, %T")%> Order Status: <%= Order.find(order).status %> - + <% if status == "paid"%> + <%=link_to "SHIP ORDER", order_path(order.to_i, {order: {status: "complete"}}), method: :patch, class: "btn btn-sm btn-danger"%> + <%else%> + + <%end%> @@ -39,9 +43,7 @@ Product Name Unit Price Subtotal - <% if status == "paid"%> - Mark as Shipped - <%end%> + @@ -51,9 +53,6 @@ <%=link_to item.product.name, product_path(item.product.id) %> $<%=item.product.price / 100.0%> $<%=item.subtotal %> - <% if status == "paid"%> - <%=link_to "SHIP ORDER", order_path(order.to_i, {order: {status: "complete"}}), method: :patch, class: "btn btn-sm btn-danger"%> - <%end%> <%end%> From 296e4cff052344f3493aa5487f0375dd01b7ae2f Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Thu, 9 May 2019 10:30:50 -0700 Subject: [PATCH 214/260] updated form to add a little view logic --- app/views/products/_form.html.erb | 2 +- app/views/products/edit.html.erb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb index 88522e8b0b..2a6339b6a0 100644 --- a/app/views/products/_form.html.erb +++ b/app/views/products/_form.html.erb @@ -7,7 +7,7 @@
<%=f.label "Price" %> - <%=f.number_field :price, in: 1.0..1000.0, step: 0.01, required: true, class: "form-control" %> + <%=f.number_field :price, :value => math, in: 1.0..1000.0, step: 0.01, required: true, class: "form-control" %>
diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb index 42d3e59dcf..624db2c31d 100644 --- a/app/views/products/edit.html.erb +++ b/app/views/products/edit.html.erb @@ -5,6 +5,6 @@ form_class: "edit-product", intro_text: "Use this form to edit a product", action_name: "Edit product", - # price_math: @product.price.nil? ? 0 : @product.price * 100.0 #tried making a variable in _form called price_math + math: @product.price / 100.0 #tried making a variable in _form called price_math } %> From aa26486a17b229555693d36b34960864b539e237 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Thu, 9 May 2019 12:51:00 -0700 Subject: [PATCH 215/260] Fixed merchant path on nav bar. --- app/views/layouts/application.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 86b870a651..1bc3b755cb 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -37,7 +37,7 @@ <% if session[:merchant_id] %> <% merchant = Merchant.find_by(id: session[:merchant_id]) %> - <%= link_to merchant.username, merchant_path(merchant.id), class: "nav-link"%> + <%= link_to merchant.username, current_merchant_path, class: "nav-link"%> <%= link_to "Log Out", logout_path, method: "delete", class: "btn btn-outline-success my-2 my-sm-0" %> <% else %> <%= link_to "Log In", github_login_path, class: "btn btn-outline-success my-2 my-sm-0" %> From 7de8e5336fd54aaf015d244f36aedb1ede64fb83 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Thu, 9 May 2019 14:19:19 -0700 Subject: [PATCH 216/260] fixed the new view for product (added math variable back in), removed find merchant and merchant params private methods from controller --- app/controllers/merchants_controller.rb | 12 ++++++------ app/views/products/edit.html.erb | 2 +- app/views/products/new.html.erb | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 3ccf28548e..1592de06d9 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -96,10 +96,10 @@ def current private -def find_merchant - @merchant = Merchant.find_by_id(merchant_params[:id]) -end +# def find_merchant +# @merchant = Merchant.find_by_id(merchant_params[:id]) +# end -def merchant_params - return params.require(:merchant).permit(:username, :email, :uid, :provider) -end +# def merchant_params +# return params.require(:merchant).permit(:username, :email, :uid, :provider) +# end diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb index 624db2c31d..dad69e40b3 100644 --- a/app/views/products/edit.html.erb +++ b/app/views/products/edit.html.erb @@ -5,6 +5,6 @@ form_class: "edit-product", intro_text: "Use this form to edit a product", action_name: "Edit product", - math: @product.price / 100.0 #tried making a variable in _form called price_math + math: @product.price / 100.0 } %> diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index ef442fe2e8..eba9b959f2 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -5,5 +5,5 @@ form_class: "new-product", intro_text: "Use this form to create a new product", action_name: "Create product", - # price_math: @product.price.nil? ? 0 : @product.price / 100.0 #tried making a variable in _form called price_math + math: nil } %> From e1883848c6c28e648777c6c467502497066ce7ce Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Thu, 9 May 2019 14:40:29 -0700 Subject: [PATCH 217/260] refactored product controller --- app/controllers/application_controller.rb | 2 +- app/controllers/merchants_controller.rb | 59 +---------------------- app/controllers/products_controller.rb | 33 ++++++------- 3 files changed, 18 insertions(+), 76 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ae400532fe..1ac9dd4dc7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,7 +2,7 @@ class ApplicationController < ActionController::Base private def find_logged_in_merchant - if session[:merchant_id] #if session[:merchant_id] is not nil + if session[:merchant_id] @login_merchant = Merchant.find_by(id: session[:merchant_id]) end end diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 1592de06d9..95bd0a096f 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -18,71 +18,24 @@ def create auth_hash = request.env["omniauth.auth"] merchant = Merchant.find_by(uid: auth_hash[:uid], provider: "github") if merchant - # merchant was found in the database flash[:success] = "Logged in as returning merchant #{merchant.username}" else - # merchant doesn't match anything in the DB - # Attempt to create a new merchant merchant = Merchant.build_from_github(auth_hash) if merchant.save flash[:success] = "Logged in as new merchant #{merchant.username}" else - # Couldn't save the merchant for some reason. If we - # hit this it probably means there's a bug with the - # way we've configured GitHub. Our strategy will - # be to display error messages to make future - # debugging easier. flash[:error] = "Could not create new merchant account: #{merchant.errors.messages}" return redirect_to root_path end end - # If we get here, we have a valid merchant instance session[:merchant_id] = merchant.id return redirect_to root_path end - def login_form - @merchant = Merchant.new # do we need this line? -Elle - end - - # MATCHED THIS TO MARGARET'S - # def login - # username = merchant_params[:username] - - # if username and merchant = Merchant.find_by(username: username) - # session[:merchant_id] = merchant.id - # flash[:status] = :success - # flash[:result_text] = "Successfully logged in as existing merchant #{merchant.username}" - # else - # merchant = Merchant.new(username: username) - # if merchant.save - # session[:merchant_id] = merchant.id - # flash[:status] = :success - # flash[:result_text] = "Successfully created new merchant #{merchant.username} with ID #{merchant.id}" - # else - # flash.now[:status] = :failure - # flash.now[:result_text] = "Could not log in" - # flash.now[:messages] = merchant.errors.messages - # render "login_form", status: :bad_request - # return - # end - # end - - # # alternative syntax for flash message: - # # flash[:success] = flash_msg - # # For testing, does the status return success? - - # redirect_to root_path - # end - - # ^^^^^^^^^^^^^^^^^^^^^^^^^^^ def logout - merchant = Merchant.find_by(id: session[:merchant_id]) - # raise - # merchant_username = merchant.username session[:merchant_id] = nil - flash[:success] = "Successfully logged out." #{merchant_username}" + flash[:success] = "Successfully logged out." redirect_to root_path end @@ -93,13 +46,3 @@ def current end end end - -private - -# def find_merchant -# @merchant = Merchant.find_by_id(merchant_params[:id]) -# end - -# def merchant_params -# return params.require(:merchant).permit(:username, :email, :uid, :provider) -# end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 2ce6672931..649def2630 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,5 +1,6 @@ class ProductsController < ApplicationController - before_action :find_logged_in_merchant, only: [:new, :create, :update, :edit, :toggle_inactive] + before_action :find_logged_in_merchant, except: [:index, :show] + before_action :find_product, except: [:new, :create, :index] def new if @login_merchant @@ -11,13 +12,12 @@ def new end def create - if @login_merchant # if merchant is logged in + if @login_merchant @product = Product.new(product_params) @product.merchant_id = session[:merchant_id] - @product.price = params[:product][:price].to_f * 100.0 - is_successful = @product.save + @product.save - if is_successful + if @product.valid? flash[:success] = "Product added successfully" redirect_to product_path(@product.id) else @@ -38,9 +38,7 @@ def index end def show - @product = Product.find_by(id: params[:id]) - - if @product.nil? || @product.active? == false # if product does not exist or it is not active (aka it is retired) + if @product.nil? || !@product.active flash[:error] = "Unknown product" redirect_to products_path end @@ -48,9 +46,7 @@ def show def edit if @login_merchant - @product = Product.find_by(id: params[:id]) - - if @product.nil? || !@product.active #don't show if product is inactive/retired + if @product.nil? || !@product.active flash[:error] = "Unknown product" redirect_to products_path end @@ -61,18 +57,15 @@ def edit end def update - @product = Product.find_by(id: params[:id]) if @product.merchant_id == @login_merchant.id @product.update(product_params) - @product.price = product_params[:price].to_f * 100.0 - is_successful = @product.save - if is_successful + if @product.valid? flash[:success] = "Product updated successfully" redirect_to product_path(@product.id) else @product.errors.messages.each do |label, message| - flash.now[label.to_sym] = message #this flash msg is working + flash.now[label.to_sym] = message end render :edit, status: :bad_request end @@ -83,7 +76,6 @@ def update end def toggle_inactive - @product = Product.find_by(id: params[:id]) if @login_merchant if @product.merchant_id == @login_merchant.id @product.active? @@ -106,7 +98,14 @@ def toggle_inactive private + def find_product + @product = Product.find_by(id: params[:id]) + end + def product_params + if params[:product][:price] + params[:product][:price] = params[:product][:price].to_f * 100.0 + end return params.require(:product).permit(:name, :price, :description, :photo_url, :stock, :merchant_id, category_ids: []) end end From a9c260380e29dbfaf9b01b36eb6669d3e025189e Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Thu, 9 May 2019 14:49:28 -0700 Subject: [PATCH 218/260] removed raise --- app/controllers/products_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 649def2630..382ce5a81c 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -76,10 +76,10 @@ def update end def toggle_inactive - if @login_merchant + if @login_merchant && @product.valid? if @product.merchant_id == @login_merchant.id - @product.active? @product.toggle(:active) + # raise is_successful = @product.save if is_successful From df29a6c2643509d8aa55ac6ee96e9cbbf96740fc Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Thu, 9 May 2019 15:19:38 -0700 Subject: [PATCH 219/260] Clean up controllers --- app/controllers/application_controller.rb | 1 + app/controllers/categories_controller.rb | 2 +- app/controllers/items_controller.rb | 4 ++-- app/controllers/orders_controller.rb | 3 +-- app/controllers/products_controller.rb | 12 ++---------- app/controllers/reviews_controller.rb | 3 +-- test/controllers/items_controller_test.rb | 10 +++++----- 7 files changed, 13 insertions(+), 22 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1ac9dd4dc7..ca8ed0532c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -10,4 +10,5 @@ def find_logged_in_merchant def find_cart_order @order = Order.find_by(id: session[:cart_id]) end + end diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 63957b4bfd..025a424249 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -11,7 +11,7 @@ def new end def create - if @login_merchant # if merchant is logged in + if @login_merchant @category = Category.new(category_params) is_successful = @category.save diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index 37476c53b3..f1d1bba360 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -21,7 +21,7 @@ def create flash.now[:error] = "Could Not Add To Cart: product not available" redirect_to products_path - # check if requested quanitity is available + # check if requested quantity is available elsif item.quantity && @product.stock < item.quantity flash.now[:error] = "Could Not Add To Cart: quantity selected is more than available stock" render "products/show", status: :bad_request @@ -32,7 +32,7 @@ def create @order.items << item if item.valid? - flash[:success] = "#{@product.name} (quantity: #{item.quantity}) Successfully Added To Cart" + flash[:success] = "#{@product.name} (total quantity: #{item.quantity}) Successfully Added To Cart" redirect_to product_path(@product.id) else flash.now[:error] = "Could Not Add To Cart" diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 00c117e5ab..007d3fce5e 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -68,10 +68,9 @@ def purchase private - # only partial params, update if more attributes are required. def order_params if params[:order][:cc_all] - params[:order][:cc_four] = params[:order][:cc_all][-4..-1] # front-end validation requires min 4 char input. + params[:order][:cc_four] = params[:order][:cc_all].length <= 4 ? params[:order][:cc_all] : params[:order][:cc_all][-4..-1] end params.require(:order).permit(:shopper_name, :shopper_email, :shopper_address, :cc_exp, :cc_four, :status) end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 382ce5a81c..14b778c911 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -77,16 +77,8 @@ def update def toggle_inactive if @login_merchant && @product.valid? - if @product.merchant_id == @login_merchant.id - @product.toggle(:active) - # raise - is_successful = @product.save - - if is_successful - flash[:success] = "Product status changed successfully" - else - flash[:error] = "Product status not changed successfully" - end + if @product.merchant_id == @login_merchant.id && @product.toggle(:active).save + flash[:success] = "Product status changed successfully" else flash[:error] = "You may only change the status of your own products" end diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index 89f02e75b5..41950e63e5 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -1,8 +1,7 @@ class ReviewsController < ApplicationController def create @product = Product.find(params[:product_id]) - # Checks if merchant signed in that they are not reviewing their own product. - if @product.merchant_id == session[:merchant_id] + if !@product || @product.merchant_id == session[:merchant_id] flash.now[:error] = "Merchants cannot review their own product." render "products/show", status: :bad_request else diff --git a/test/controllers/items_controller_test.rb b/test/controllers/items_controller_test.rb index 1b902738b5..809dc786c0 100644 --- a/test/controllers/items_controller_test.rb +++ b/test/controllers/items_controller_test.rb @@ -3,13 +3,13 @@ describe ItemsController do describe "create" do let(:product) { products(:product_1) } - let(:item_params) { { item: { quantity: 2 } } } + let(:item_params) { {item: {quantity: 2}} } it "will create a new item" do expect { post product_items_path(product.id), params: item_params }.must_change "Item.count", 1 - expect(flash[:success]).must_equal "#{product.name} (quantity: #{item_params[:item][:quantity]}) Successfully Added To Cart" + expect(flash[:success]).must_equal "#{product.name} (total quantity: #{item_params[:item][:quantity]}) Successfully Added To Cart" must_respond_with :redirect must_redirect_to product_path(product.id) @@ -20,7 +20,7 @@ post product_items_path(product.id), params: item_params }.must_change "Order.count", 1 - expect(flash[:success]).must_equal "#{product.name} (quantity: #{item_params[:item][:quantity]}) Successfully Added To Cart" + expect(flash[:success]).must_equal "#{product.name} (total quantity: #{item_params[:item][:quantity]}) Successfully Added To Cart" must_respond_with :redirect must_redirect_to product_path(product.id) @@ -35,7 +35,7 @@ post product_items_path(product.id), params: item_params }.must_change "Order.count", 0 - expect(flash[:success]).must_equal "#{product.name} (quantity: #{item_params[:item][:quantity]}) Successfully Added To Cart" + expect(flash[:success]).must_equal "#{product.name} (total quantity: #{item_params[:item][:quantity]}) Successfully Added To Cart" must_respond_with :redirect must_redirect_to product_path(product.id) @@ -94,7 +94,7 @@ describe "update" do let(:item) { items(:item_1) } - let(:item_params) { { item: { quantity: 2 } } } + let(:item_params) { {item: {quantity: 2}} } it "will update a valid item if product has enough stock" do expect { patch item_path(item.id), params: item_params From d09a5d64f14537c8cede295ad214c54f227716a1 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Thu, 9 May 2019 15:26:47 -0700 Subject: [PATCH 220/260] moved link to create new product from products page --- app/controllers/application_controller.rb | 1 - app/views/products/index.html.erb | 3 --- 2 files changed, 4 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ca8ed0532c..1ac9dd4dc7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -10,5 +10,4 @@ def find_logged_in_merchant def find_cart_order @order = Order.find_by(id: session[:cart_id]) end - end diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 8882888ed3..c27c388473 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,7 +1,4 @@

Products

- -<%= link_to "Add new product", new_product_path %> -
<% Product.where(active: true).each do |product| %> From 25de1e9561115ceba67fd4457abfd82ef8448aed Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 9 May 2019 15:30:06 -0700 Subject: [PATCH 221/260] time udpate in config --- config/application.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/application.rb b/config/application.rb index 5c09a3eefc..3e37da83c1 100644 --- a/config/application.rb +++ b/config/application.rb @@ -21,5 +21,7 @@ class Application < Rails::Application # Application configuration can go into files in config/initializers # -- all .rb files in that directory are automatically loaded after loading # the framework and any gems in your application. + + config.time_zone = "Pacific Time (US & Canada)" end end From e641960155a1ec3edf22640344c0f20118b0f65f Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Thu, 9 May 2019 15:34:11 -0700 Subject: [PATCH 222/260] fixed some buttons on dashboard --- app/views/merchants/current.html.erb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index 1b097b36cf..f443fd5ddd 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -26,7 +26,7 @@ - + @@ -82,9 +82,9 @@ - + + <%end%> From 1cb4e1cfb5ca7a4ced342b71ce8ace4403d1810c Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 9 May 2019 15:59:55 -0700 Subject: [PATCH 223/260] added bootstrap to dashboard --- app/views/merchants/current.html.erb | 41 +++++++++++++++++++--------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index f443fd5ddd..b622b16ed0 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -1,23 +1,38 @@

Merchant Dashboard

-

Welcome <%= @login_merchant.username %>

+

Welcome <%= @login_merchant.username.capitalize%>

<%= link_to "Add new product", new_product_path, class: "btn btn-outline-primary" %> <%= link_to "Add new category", new_category_path, class: "btn btn-outline-primary" %> <% item_hash = Order.find_merchant_order_items(@login_merchant) %> -

Paid orders

-
    -
  • Total number of paid orders: <%= item_hash["paid"].count %>
  • -
  • Revenue for paid orders: $<%= "%.2f" % Order.status_revenue(item_hash["paid"])%>
  • -
-

Complete orders

-
    -
  • Total number of complete orders: <%= item_hash["complete"].count %>
  • -
  • Revenue for complete orders: $<%= "%.2f" % Order.status_revenue(item_hash["complete"])%>
  • -
-

Total revenue

-

$<%= "%.2f" % ( Order.status_revenue(item_hash["paid"]) + Order.status_revenue(item_hash["completed"]))%>

+

Merchant Metrics

+
<%= link_to "Order ID: #{Order.find(order).id}", order_path(Order.find(order).id) %> <%= link_to "Order ID: #{Order.find(order).id}", order_path(Order.find(order).id), class: "btn btn-outline-primary btn-sm" %> Date & Time of order: <%= Order.find(order).created_at.strftime("%B %d, %T")%> Order Status: <%= Order.find(order).status %> $<%= "%.2f" % (product.price / 100.0)%> <%=product.description %> <%=product.active? ? "Active" : "Retired" %> - <%=link_to "Retire product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary" if product.active?%> - <%=link_to "Activate product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary" if product.active? == false%><%=link_to "Edit product", edit_product_path(product.id), class: "btn btn-outline-primary" if product.active?%><%=link_to "Retire product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary btn-sm" if product.active?%> + <%=link_to "Activate product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary btn-sm" if product.active? == false%><%=link_to "Edit product", edit_product_path(product.id), class: "btn btn-outline-primary btn-sm" if product.active?%>
+ + + + + + + + + + + + + + + + + + + + + + + + +
StatusNumber of OrdersRevenue
Paid<%= item_hash["paid"].count %>$<%= "%.2f" % Order.status_revenue(item_hash["paid"])%>
Complete<%= item_hash["complete"].count %>$<%= "%.2f" % Order.status_revenue(item_hash["complete"])%>
Total<%= item_hash["complete"].count + item_hash["paid"].count%>$<%= "%.2f" % ( Order.status_revenue(item_hash["paid"]) + Order.status_revenue(item_hash["completed"]))%>

Orders by status

<%["paid", "complete"].each do |status|%> From 263a5ad7a825615d83fb41ddd7782bab526766cd Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 9 May 2019 16:01:47 -0700 Subject: [PATCH 224/260] fixed layout of table --- app/views/merchants/current.html.erb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index b622b16ed0..b142ff0420 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -68,6 +68,7 @@ <%=link_to item.product.name, product_path(item.product.id) %> $<%=item.product.price / 100.0%> $<%=item.subtotal %> + <%end%> From 5f3f4b0166937d38fe9d502aed52ecd5002b95ea Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Thu, 9 May 2019 16:02:56 -0700 Subject: [PATCH 225/260] added moeny formatting to current --- app/views/merchants/current.html.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index b622b16ed0..3a566bb2bc 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -66,8 +66,8 @@ <%=item.quantity%> <%=link_to item.product.name, product_path(item.product.id) %> - $<%=item.product.price / 100.0%> - $<%=item.subtotal %> + $<%= "%.2f" % (item.product.price / 100.0)%> + $<%="%.2f" % (item.subtotal) %> <%end%> From 212ed3210061aab7fe6a60ec9b87d4f365e364fc Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 9 May 2019 16:10:32 -0700 Subject: [PATCH 226/260] fixed this column --- app/views/merchants/current.html.erb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index 3a566bb2bc..69bf0a39da 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -68,6 +68,7 @@ <%=link_to item.product.name, product_path(item.product.id) %> $<%= "%.2f" % (item.product.price / 100.0)%> $<%="%.2f" % (item.subtotal) %> + <%end%> From fa6c638a85abf295422f27c9b444ac6dd37c7232 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Thu, 9 May 2019 16:17:53 -0700 Subject: [PATCH 227/260] Worked on unifying styling. --- app/assets/stylesheets/homepages.scss | 46 ++++++++++++++----- app/assets/stylesheets/products.scss | 5 ++ app/views/homepages/index.html.erb | 2 +- app/views/merchants/current.html.erb | 13 +++--- app/views/products/show.html.erb | 31 ++++--------- db/products_data.csv | 8 ++-- .../controllers/categories_controller_test.rb | 3 ++ 7 files changed, 65 insertions(+), 43 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 014bcc9e4e..9415755930 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -3,12 +3,22 @@ // You can use Sass (SCSS) here: http://sass-lang.com/ body { font-family: Helvetica, Arial, sans-serif; + +} +.centered { + text-align: center; +} + +main { + margin-left: 2.5em; + margin-right: 2.5em; + margin-bottom: 5vw; } h1 { font-family: 'League Script', Helvetica, Arial, sans-serif; font-weight:bold; - font-size: 100px; + font-size: 10em; color: rgb(198, 158, 255); text-align: center; } @@ -24,8 +34,8 @@ h2 { h3 { font-family: 'Raleway Dots', Arial, sans-serif; font-weight:bold; - font-size: 50px; - text-align: center; + font-size: 2.4em; + margin-top: 1em; color: rgb(255, 157, 255); } @@ -59,6 +69,7 @@ a:hover { .greybg { background-color: rgb(255, 255, 255); + } .whitebg { @@ -81,6 +92,7 @@ a:hover { font-size: 4em; color: rgba(131, 11, 142, 0.842); text-align: center; + margin: 10px; } @@ -105,17 +117,29 @@ a:hover { padding: 5em; } -p { - font-family: 'Raleway Dots', Arial, sans-serif; +.centered-arial { + font-family: helvetica, Arial, sans-serif; + color:rgb(87, 87, 87); font-size: 1.3em; - margin: 1em; + margin: 3em; + text-align: center; +} + +.jumbotron { + display: grid; + grid-template: 3fr / 1fr 1fr; } -#footer { - position: absolute; - bottom: 0; - width: 100%; - height: 2.5rem; +.jumbotron h3 { + grid-column: 1 / 3; + } +// #footer { +// position: absolute; +// bottom: 0; +// width: 100%; +// height: 2.5rem; +// } + diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss index ee8ca35a33..6ee30b39a5 100644 --- a/app/assets/stylesheets/products.scss +++ b/app/assets/stylesheets/products.scss @@ -16,6 +16,11 @@ img { align-items: flex-start; } + img.detail { + max-width: 35vw; + max-height: 200px; + } + // div.flex-item { // display: flex; // flex-flow: column wrap; diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index f07e797e94..0f8b9369c9 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -4,7 +4,7 @@ <% if session[:merchant_id] %> <% merchant = Merchant.find_by(id: session[:merchant_id]) %> -

<%= "You are currently logged in as #{merchant.username}" %>

+

<%= "You are currently logged in as #{merchant.username}" %>

<%# wrap in class for footer %> <% end %>
\ No newline at end of file diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index 1b097b36cf..d7bf29bd62 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -1,8 +1,9 @@

Merchant Dashboard

-

Welcome <%= @login_merchant.username %>

- -<%= link_to "Add new product", new_product_path, class: "btn btn-outline-primary" %> -<%= link_to "Add new category", new_category_path, class: "btn btn-outline-primary" %> +
+

Welcome <%= @login_merchant.username %>

+ <%= link_to "Add new product", new_product_path, class: "btn btn-outline-primary" %> + <%= link_to "Add new category", new_category_path, class: "btn btn-outline-primary" %> +
<% item_hash = Order.find_merchant_order_items(@login_merchant) %> @@ -19,9 +20,9 @@

Total revenue

$<%= "%.2f" % ( Order.status_revenue(item_hash["paid"]) + Order.status_revenue(item_hash["completed"]))%>

-

Orders by status

+

Orders by status

<%["paid", "complete"].each do |status|%> -

Status: <%=status.capitalize%>

+

Status: <%=status.capitalize%>

<% item_hash[status].each do |order, items| %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 1d265ab0b2..07ebc2cdf3 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,26 +1,18 @@ +
+

<%= @product.name %>

-

- <%= @product.name %> -

+ <%= image_tag @product.photo_url, alt: "Image of the product", class: "detail" %> -<%= image_tag @product.photo_url, alt: "Image of the product" %> +
<%= @product.description%>
-

-<%= @product.description%> -

+
Price: $ <%= "%.2f" % (@product.price / 100.0) %>
-

- Price: $ <%= "%.2f" % (@product.price / 100.0) %> -

+
In-Stock: <%= @product.stock%>
-

- Stock: <%= @product.stock%> -

+ <%= render partial: "/items/item_form", locals: {item: Item.new, method_verb: :post, + action: "Add to Cart", url_path: product_items_path(@product.id)} %> -
-

- Categories -

+
Categories
<% if @product.categories.any? %>
    @@ -57,10 +49,7 @@
    <%= render partial: "/reviews/review_form"%>
    -
    - <%= render partial: "/items/item_form", locals: {item: Item.new, method_verb: :post, - action: "Add to Cart", url_path: product_items_path(@product.id)} %> -
    + <%= link_to "Back to all products", products_path %> diff --git a/db/products_data.csv b/db/products_data.csv index c646979085..ef006052cd 100644 --- a/db/products_data.csv +++ b/db/products_data.csv @@ -7,10 +7,10 @@ relaxation,3361,8,there’s an infinite number of monkeys outside who want to ta energy,1131,6,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/qW7q6PW/maria-fernanda-gonzalez-461521-unsplash.jpg a good hair day,637,7,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/ZhfmGX8/bruno-nascimento-149663-unsplash.jpg pause time,1758,4,take time to study for the test,https://i.ibb.co/RzHDBvx/ahmadreza-sajadi-10140-unsplash.jpg -freshly showered,4963,8,Parts of the inside of her head screamed at other parts of the inside of her head.,https://i.ibb.co/RzHDBvx/ahmadreza-sajadi-10140-unsplash.jpg +freshly showered,4963,8,Parts of the inside of her head screamed at other parts of the inside of her head.,https://i.ibb.co/0D9th8Z/michael-podger-252489-unsplash.jpg teleport into bed,3216,6,if you’ve never been through a matter transference beam before you’ve probably lost some salt and protein. The beer you had should have cushioned your system a bit.,https://i.ibb.co/nk5FkwV/diego-ph-493991-unsplash.jpg -ada starter kit,2397,5,"Whatever your tastes, Magrathea can cater for you. We are not proud.",https://photos.app.goo.gl/EjCZFqdH32peKLVD8 -ada best seller pack,4517,8,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/vLcVmkY/ishan-seefromthesky-277746-unsplash.jpg +ada starter kit,2397,5,"Whatever your tastes, Magrathea can cater for you. We are not proud.",https://i.ibb.co/ssgbQqH/ishan-seefromthesky-277746-unsplash.jpg +ada best seller pack,4517,8,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/XCc7kxc/recal-media-83365-unsplash.jpg cup of rainbows,4282,4,"It’s only half completed, I’m afraid – we haven’t even finished burying the artificial dinosaur skeletons in the crust yet.",https://i.ibb.co/LprTnc8/alistair-macrobert-633034-unsplash.jpg puppy play pack,2803,8,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/M1xGDJ0/bharathi-kannan-1260953-unsplash.jpg kitten cuddles,4928,7,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/GdT7fWn/kote-puerto-771605-unsplash.jpg @@ -18,4 +18,4 @@ giggle party,3250,3,"It seemed to me that any civilization that had so far lost bestfriend time,2332,11,"According to the legends, the Magratheans lived most of their lives underground.",https://i.ibb.co/Jd4nkWQ/ian-schneider-64307-unsplash.jpg juicy secret,1170,5,"Evolution? they said to themselves, Who needs it?",https://i.ibb.co/pP0xbMM/dan-cook-508166-unsplash.jpg inside joke moment,4141,4,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://i.ibb.co/PN6tfQY/marcela-rogante-432403-unsplash.jpg -bondfire time,2976,4,its a nice time,hhttps://i.ibb.co/JR78YWq/mike-erskine-144525-unsplash.jpg \ No newline at end of file +bondfire time,2976,4,its a nice time,https://i.ibb.co/JR78YWq/mike-erskine-144525-unsplash.jpg \ No newline at end of file diff --git a/test/controllers/categories_controller_test.rb b/test/controllers/categories_controller_test.rb index 81b8468d5e..8c0cae5de4 100644 --- a/test/controllers/categories_controller_test.rb +++ b/test/controllers/categories_controller_test.rb @@ -61,6 +61,9 @@ expect { post categories_path, params: new_category }.must_change "Category.count", 1 + # Elle's note: + # For syntax helping to understand strings vs symbols as keys + # expect({ post categories_path, params: new_category }).must_change("Category.count", 1) expect(flash[:success]).must_equal "Category added successfully" must_respond_with :redirect From baab88ddb19a04547b721f353b030665a2dbb8ab Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Thu, 9 May 2019 18:35:07 -0700 Subject: [PATCH 228/260] Made more styling updates to product details. Also a few other styling things. --- app/assets/stylesheets/homepages.scss | 19 +++++++++- app/assets/stylesheets/items.scss | 9 +++++ app/assets/stylesheets/products.scss | 10 ++++-- app/views/items/_item_form.html.erb | 7 ++-- app/views/products/show.html.erb | 50 ++++++++++++++------------- 5 files changed, 65 insertions(+), 30 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 9415755930..d11f1a06c2 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -9,6 +9,11 @@ body { text-align: center; } +.bold { + font-weight: 900; + -webkit-text-stroke: #ff9dff 1px; +} + main { margin-left: 2.5em; margin-right: 2.5em; @@ -127,15 +132,27 @@ a:hover { } .jumbotron { + margin-top: 36px; + padding-top: 36px; + padding-bottom: 36px; display: grid; grid-template: 3fr / 1fr 1fr; + grid-gap: 3vw; } .jumbotron h3 { grid-column: 1 / 3; - + margin-bottom: 1em; + margin-top: 0; } +// .jumbotron img { +// margin-bottom: 1em; +// } + +.jumbotron form { + display: inline; +} // #footer { // position: absolute; // bottom: 0; diff --git a/app/assets/stylesheets/items.scss b/app/assets/stylesheets/items.scss index a3a147ad0b..776c74a33d 100644 --- a/app/assets/stylesheets/items.scss +++ b/app/assets/stylesheets/items.scss @@ -1,3 +1,12 @@ // 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/ + +.jumbotron li { + margin-left: 0px; + +} + +.jumbotron p { + +} \ No newline at end of file diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss index 6ee30b39a5..6a5211056a 100644 --- a/app/assets/stylesheets/products.scss +++ b/app/assets/stylesheets/products.scss @@ -17,10 +17,16 @@ img { } img.detail { - max-width: 35vw; - max-height: 200px; + max-width: 40vw; + max-height: 300px; } +h4 { + margin-top: 1em; +} + + + // div.flex-item { // display: flex; // flex-flow: column wrap; diff --git a/app/views/items/_item_form.html.erb b/app/views/items/_item_form.html.erb index a958b4392a..f5f3b00da8 100644 --- a/app/views/items/_item_form.html.erb +++ b/app/views/items/_item_form.html.erb @@ -1,10 +1,11 @@ <%=form_with model: item , url: url_path, method: method_verb do |f| %> -
    + +
    <%= f.label :Quantity%> - <%= f.number_field :quantity, required: true, in: 1..@product.stock, class: "form-control"%> + <%= f.number_field :quantity, required: true, in: 1..@product.stock %>
    -
    +
    <%= f.submit action, class: "btn btn-sm btn-primary" %>
    <%end%> \ No newline at end of file diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 07ebc2cdf3..dce857e396 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,47 +1,50 @@
    -

    <%= @product.name %>

    +

    <%= @product.name %>

    <%= image_tag @product.photo_url, alt: "Image of the product", class: "detail" %> -
    <%= @product.description%>
    +

    <%= @product.description%>

    -
    Price: $ <%= "%.2f" % (@product.price / 100.0) %>
    +
    +
    Price: $ <%= "%.2f" % (@product.price / 100.0) %>
    -
    In-Stock: <%= @product.stock%>
    +
    In-Stock: <%= @product.stock%>
    - <%= render partial: "/items/item_form", locals: {item: Item.new, method_verb: :post, - action: "Add to Cart", url_path: product_items_path(@product.id)} %> + <%= render partial: "/items/item_form", locals: {item: Item.new, method_verb: :post, + action: "Add to Cart", url_path: product_items_path(@product.id)} %> -
    Categories
    +
    +
    +
    Categories
    - <% if @product.categories.any? %> -
      + <% if @product.categories.any? %> - <% @product.categories.each do |category| %> -
    • <%= link_to category.name, category_path(category.id) %>
    • - <% end %> + <% @product.categories.each do |category| %> + <%= link_to category.name, category_path(category.id) %> +
      + <% end %> -
    - <% else %> -

    There are no categories assigned to this product

    - <% end %> + <% else %> +

    There are no categories assigned to this product

    + <% end %> +
    +<%= link_to "Back to all products", products_path, class: "btn btn-outline-success" %> +

    Reviews

    <% reviews = Review.where(product_id: @product.id)%> <% if reviews.any? %> -
      - - <% reviews.each do |review| %> -
    • Rating: <%= review.rating%>
    • -
    • Comment: <%= review.comment%>
    • + <% reviews.each do |review| %> +

      Rating: <%= review.rating%> +
      + Comment: <%= review.comment%>

      +
      <% end %> - -
    <% else %>

    There are no reviews for this product

    <% end %> @@ -51,5 +54,4 @@
    -<%= link_to "Back to all products", products_path %> From 5384020ed19966a252d621372b5ee8ac57270af5 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 9 May 2019 20:51:13 -0700 Subject: [PATCH 229/260] added cart icon --- app/assets/stylesheets/application.scss | 40 +++++++++++++++++++++++++ app/views/layouts/application.html.erb | 20 ++++++++++--- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index afa576a0fa..14d755b5ce 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -27,3 +27,43 @@ padding: 20px 10px; margin: 0; } + +.btn-outline-success { + color: rgba(131, 11, 142, 0.842); + background-color: transparent; + background-image: none; + border-color: rgba(131, 11, 142, 0.842); +} + +.btn-outline-success:hover{ + background-color: rgba(131, 11, 142, 0.842); + border-color: rgba(131, 11, 142, 0.842); +} + +.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-success.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(131, 11, 142, 0.842); +} + +.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active, .show > .btn-outline-success.dropdown-toggle { + color: #fff; + background-color: rgba(131, 11, 142, 0.842); + border-color: rgba(131, 11, 142, 0.295); +} + +.btn-outline-success:focus, .btn-outline-success.focus { + box-shadow: 0 0 0 0.2rem rgba(131, 11, 142, 0.842); +} + +#cart { + margin-right: 10px; +} + +.dash-link { + margin-left: 0px; + margin-right: 10px; +} + +.log-in { + margin-left: 15px; + margin-right: 10px; +} \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 1bc3b755cb..829a88d899 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -34,15 +34,27 @@ <%= link_to "Merchants", merchants_path, class: "nav-link" %>
- + <% if session[:merchant_id] %> <% merchant = Merchant.find_by(id: session[:merchant_id]) %> - <%= link_to merchant.username, current_merchant_path, class: "nav-link"%> + <%= link_to merchant.username, current_merchant_path, class: "dash-link nav-link"%> <%= link_to "Log Out", logout_path, method: "delete", class: "btn btn-outline-success my-2 my-sm-0" %> <% else %> - <%= link_to "Log In", github_login_path, class: "btn btn-outline-success my-2 my-sm-0" %> + <%= link_to "Log In", github_login_path, class: "log-in btn btn-outline-success my-2 my-sm-0" %> <% end %> - <%= link_to "Cart", cart_path, class: "nav-link"%> + <%# From 64b747dc37016317c014f85bc567e9ee9f484056 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Thu, 9 May 2019 21:07:15 -0700 Subject: [PATCH 230/260] Finalized the product show page. Moved some page-specific styling into the page-specific .scss file. --- app/assets/stylesheets/homepages.scss | 25 +-------------------- app/assets/stylesheets/items.scss | 32 ++++++++++++++++++++++++++- app/views/products/show.html.erb | 5 +++-- 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index d11f1a06c2..1bcb274130 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -104,14 +104,6 @@ a:hover { .nav-link { color: rgba(0, 0, 0, 0.5); } -// .nav_bar { -// list-style: none; -// display: flex; -// flex-wrap: wrap; -// justify-content: center; -// padding: 20px 10px; -// margin: 0; -// } .nav_bar_header ul li { padding: 20px 30px; @@ -140,23 +132,8 @@ a:hover { grid-gap: 3vw; } -.jumbotron h3 { - grid-column: 1 / 3; - margin-bottom: 1em; - margin-top: 0; -} - -// .jumbotron img { -// margin-bottom: 1em; -// } - .jumbotron form { display: inline; } -// #footer { -// position: absolute; -// bottom: 0; -// width: 100%; -// height: 2.5rem; -// } + diff --git a/app/assets/stylesheets/items.scss b/app/assets/stylesheets/items.scss index 776c74a33d..a9b4bb9d1a 100644 --- a/app/assets/stylesheets/items.scss +++ b/app/assets/stylesheets/items.scss @@ -6,7 +6,37 @@ margin-left: 0px; } +.jumbotron h3 { + grid-column: 1 / 3; + margin-bottom: 0; + margin-top: 0; + } + +// .jumbotron img { +// grid-row: 2 / 4; +// } .jumbotron p { - + margin-bottom: 0; + grid-column: 1 / 3; +} + +.col-md-4 { + padding: 0px; +} + +.inner-flex { + display: flex; + flex-wrap: wrap; + flex-direction: row; + justify-content: flex-start; + align-items: flex-start; +} + +.inner-flex div { + margin-right: 2em; +} + +.btn-sm { + margin-bottom: 1.3em; } \ No newline at end of file diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index dce857e396..69f608043e 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -3,8 +3,7 @@ <%= image_tag @product.photo_url, alt: "Image of the product", class: "detail" %> -

<%= @product.description%>

- +
Price: $ <%= "%.2f" % (@product.price / 100.0) %>
@@ -28,6 +27,8 @@

There are no categories assigned to this product

<% end %>
+
+

<%= @product.description%>

From 9709c9a05e9e229a01f69397574c21a007473824 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Thu, 9 May 2019 21:12:35 -0700 Subject: [PATCH 231/260] styled merchant dash --- app/assets/stylesheets/merchants.scss | 4 ++++ app/views/merchants/current.html.erb | 22 ++++++++++++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/app/assets/stylesheets/merchants.scss b/app/assets/stylesheets/merchants.scss index f4c164d600..0f62e62bf3 100644 --- a/app/assets/stylesheets/merchants.scss +++ b/app/assets/stylesheets/merchants.scss @@ -1,3 +1,7 @@ // Place all the styles related to the Merchants controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ + +.merchant-dashboard td a:hover { + color: rgb(255, 157, 255); +} \ No newline at end of file diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index 4c76ce650b..49b0eebcc9 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -1,3 +1,4 @@ +

Merchant Dashboard

Welcome <%= @login_merchant.username %>

@@ -7,8 +8,8 @@ <% item_hash = Order.find_merchant_order_items(@login_merchant) %> -

Merchant Metrics

-
+

✨Merchant Metrics

+
@@ -30,16 +31,16 @@ - +
Status
Total <%= item_hash["complete"].count + item_hash["paid"].count%>$<%= "%.2f" % ( Order.status_revenue(item_hash["paid"]) + Order.status_revenue(item_hash["completed"]))%> $<%= "%.2f" % (Order.status_revenue(item_hash["paid"]) + Order.status_revenue(item_hash["complete"]))%>
-

Orders by status

+

✨Orders by status

<%["paid", "complete"].each do |status|%> -

Status: <%=status.capitalize%>

+

<%=status.capitalize%> Orders

<% item_hash[status].each do |order, items| %> - +
@@ -78,11 +79,11 @@ <%end%> <% @products = Product.where(merchant_id: @login_merchant.id).order(:active).reverse %> -

All Products

-
<%= link_to "Order ID: #{Order.find(order).id}", order_path(Order.find(order).id), class: "btn btn-outline-primary btn-sm" %>
+

✨All Products

+
- + @@ -105,4 +106,5 @@ <%end%> -
IDItem ID Name Price Description
\ No newline at end of file + + \ No newline at end of file From 316a134ae0e81735947d10ab5ad3f735bacb5e6f Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 9 May 2019 21:40:47 -0700 Subject: [PATCH 232/260] added favicon --- app/assets/images/favicon.png | Bin 0 -> 59711 bytes app/assets/images/intangible.png | Bin 0 -> 31784 bytes app/assets/stylesheets/application.scss | 20 ++++++++++++-------- app/views/layouts/application.html.erb | 20 +++++++++----------- 4 files changed, 21 insertions(+), 19 deletions(-) create mode 100755 app/assets/images/favicon.png create mode 100755 app/assets/images/intangible.png diff --git a/app/assets/images/favicon.png b/app/assets/images/favicon.png new file mode 100755 index 0000000000000000000000000000000000000000..ba3294c56cef4d8899ff98355a0cddd626193827 GIT binary patch literal 59711 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 bde{F6WvC0XmD0Rf00000NkvXXu0mjfK<61) literal 0 HcmV?d00001 diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 14d755b5ce..4179475bd3 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -19,14 +19,18 @@ .nav-item { color: rgba(131, 11, 142, 0.842); } - .nav_bar { - list-style: none; - display: flex; - flex-wrap: wrap; - justify-content: center; - padding: 20px 10px; - margin: 0; - } + +.navbar-brand:hover{ + font-family: 'League Script', Helvetica, Arial, sans-serif; +} +.nav_bar { + list-style: none; + display: flex; + flex-wrap: wrap; + justify-content: center; + padding: 20px 10px; + margin: 0; +} .btn-outline-success { color: rgba(131, 11, 142, 0.842); diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 829a88d899..1d992b2dcd 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,19 +1,17 @@ - - - - SECRETS + Intangibly <%= csrf_meta_tags %> <%= csp_meta_tag %> + + + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> + <%= favicon_link_tag asset_path('intangible.png') %>

@@ -37,13 +35,13 @@ From c081a846e440dc1ff91bd0d3a97e5cbaa69d909d Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 9 May 2019 22:03:57 -0700 Subject: [PATCH 233/260] adjusted margins so hover on logo does not push out other items on nav --- app/assets/stylesheets/application.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 4179475bd3..7381d87f98 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -22,6 +22,11 @@ .navbar-brand:hover{ font-family: 'League Script', Helvetica, Arial, sans-serif; + margin-right: 11px; +} + +.navbar-brand { + margin-right: 20px; } .nav_bar { list-style: none; From f9d1a928bf55a8ee0efa2c91f8f584c65f7beaf2 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Thu, 9 May 2019 22:13:44 -0700 Subject: [PATCH 234/260] updating buttons, alert --- app/views/categories/create.html.erb | 2 -- app/views/items/_item_form.html.erb | 2 +- app/views/layouts/application.html.erb | 2 +- app/views/merchants/current.html.erb | 12 ++++++------ 4 files changed, 8 insertions(+), 10 deletions(-) delete mode 100644 app/views/categories/create.html.erb diff --git a/app/views/categories/create.html.erb b/app/views/categories/create.html.erb deleted file mode 100644 index 63069b0005..0000000000 --- a/app/views/categories/create.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -

Categories#create

-

Find me in app/views/categories/create.html.erb

diff --git a/app/views/items/_item_form.html.erb b/app/views/items/_item_form.html.erb index a958b4392a..efdbc86193 100644 --- a/app/views/items/_item_form.html.erb +++ b/app/views/items/_item_form.html.erb @@ -5,6 +5,6 @@ <%= f.number_field :quantity, required: true, in: 1..@product.stock, class: "form-control"%>
- <%= f.submit action, class: "btn btn-sm btn-primary" %> + <%= f.submit action, class: "btn btn-sm btn-outline-success" %>
<%end%> \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 1d992b2dcd..c7e8b358fb 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -61,7 +61,7 @@
<% if flash[:success] %> -
+
<%= flash[:success] %>
diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index 4c76ce650b..ac23e61e9c 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -1,8 +1,8 @@

Merchant Dashboard

Welcome <%= @login_merchant.username %>

- <%= link_to "Add new product", new_product_path, class: "btn btn-outline-primary" %> - <%= link_to "Add new category", new_category_path, class: "btn btn-outline-primary" %> + <%= link_to "Add new product", new_product_path, class: "btn btn-outline-info" %> + <%= link_to "Add new category", new_category_path, class: "btn btn-outline-info" %>
<% item_hash = Order.find_merchant_order_items(@login_merchant) %> @@ -42,7 +42,7 @@ - + @@ -99,9 +99,9 @@ - + + <%end%> From cdc85f64b789ca48a7068b498aa95a5a7422116e Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 00:07:30 -0700 Subject: [PATCH 235/260] cart page is styled --- app/assets/stylesheets/application.scss | 5 ----- app/assets/stylesheets/orders.scss | 19 +++++++++++++++++++ app/views/items/_item_form.html.erb | 2 +- app/views/orders/view_cart.html.erb | 24 +++++++++++++++--------- app/views/reviews/_review_form.html.erb | 2 -- 5 files changed, 35 insertions(+), 17 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index d19471e537..245b2caab6 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -63,11 +63,6 @@ box-shadow: 0 0 0 0.2rem rgba(131, 11, 142, 0.842); } -.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active, .show > .btn-outline-success.dropdown-toggle { - color: #fff; - background-color: rgba(131, 11, 142, 0.842); - border-color: rgba(131, 11, 142, 0.842); -} #cart { margin-right: 10px; diff --git a/app/assets/stylesheets/orders.scss b/app/assets/stylesheets/orders.scss index 741506954d..0e0c3f87d9 100644 --- a/app/assets/stylesheets/orders.scss +++ b/app/assets/stylesheets/orders.scss @@ -1,3 +1,22 @@ // 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/ + +.item.card { + width: 300px; + +} + +.flex { + display: flex; + flex-flow: row wrap; + justify-content: space-around; +} + +.checkout { + margin-top: 2em; +} + +.remove{ + margin-top: 1em; +} \ No newline at end of file diff --git a/app/views/items/_item_form.html.erb b/app/views/items/_item_form.html.erb index 14a27c3ac2..6e2d3a0f69 100644 --- a/app/views/items/_item_form.html.erb +++ b/app/views/items/_item_form.html.erb @@ -6,6 +6,6 @@ <%= f.number_field :quantity, required: true, in: 1..@product.stock %>
- <%= f.submit action, class: "btn btn-info" %> + <%= f.submit action, class: "btn btn-info sm_margin" %>
<%end%> \ No newline at end of file diff --git a/app/views/orders/view_cart.html.erb b/app/views/orders/view_cart.html.erb index 70895334c4..bfcc046b5e 100644 --- a/app/views/orders/view_cart.html.erb +++ b/app/views/orders/view_cart.html.erb @@ -1,21 +1,27 @@
<%if @order && @order.items.any? %>

<%=@order.items.count%> item<%="s" if @order.items.count != 1%> in cart

+
<%@order.items.each do |item| %> -
-

<%=item.product.name%>

-

<%=item.product.description%> -

quantity: <%=item.quantity%>

-

subtotal: $<%=item.subtotal%> +

+
+

<%=item.product.name%>

+

quantity: <%=item.quantity%>

+

subtotal: $<%=item.subtotal%> +

<%=item.product.description%> <% @product = item.product %> <%= render partial: "/items/item_form", locals: {item: item, method_verb: :patch, action: "Update", url_path: item_path(item.id)} %> - <%= link_to "Remove item", item_path(item.id), method: :delete, class: "btn btn-secondary btn-sm"%> + <%= link_to "Remove item", item_path(item.id), method: :delete, class: "btn btn-outline-secondary remove"%> +

<%end%> - <%= link_to "Check Out", checkout_cart_path, class: "btn btn-primary"%> - <%=link_to "Keep shopping", products_path %> +
<%else%>

0 items in cart

-

<%= link_to "Discover something intangible to fill it up", products_path %>

+

<%= link_to "Discover something intangible to fill it up", products_path%>

<%end%>
+
+<%= link_to "Check Out", checkout_cart_path, class: "btn btn-outline-success btn-block"%> +<%=link_to "Keep shopping", products_path, class: "btn btn-info btn-block" %> +
\ No newline at end of file diff --git a/app/views/reviews/_review_form.html.erb b/app/views/reviews/_review_form.html.erb index c1d09d4e63..79ece48736 100644 --- a/app/views/reviews/_review_form.html.erb +++ b/app/views/reviews/_review_form.html.erb @@ -1,6 +1,5 @@ <%=form_with model: Review.new() , url: product_reviews_path(@product.id) do |f| %> -<%#
%>
<%= f.label :rating%> <%= f.number_field :rating, required: true, in: 1..5, class: "form-control"%> @@ -12,5 +11,4 @@
<%= f.submit class:"btn btn-sm btn-info" %>
-<%#
%> <%end%> \ No newline at end of file From f63ace20d0bda93cacd8862804e4a9f237ef0875 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 01:12:10 -0700 Subject: [PATCH 236/260] fiddling, overrode form bootstrap atcive colors --- app/assets/stylesheets/application.scss | 18 ++++++++++++++++ app/assets/stylesheets/homepages.scss | 28 +++++++++++++++---------- app/assets/stylesheets/orders.scss | 2 +- app/assets/stylesheets/products.scss | 3 +++ app/views/homepages/index.html.erb | 4 +++- app/views/items/_item_form.html.erb | 2 +- app/views/layouts/application.html.erb | 3 +-- app/views/orders/_order_form.html.erb | 2 +- app/views/orders/checkout.html.erb | 2 +- app/views/orders/view_cart.html.erb | 14 ++++++------- app/views/products/_form.html.erb | 6 +++--- app/views/products/new.html.erb | 2 +- 12 files changed, 56 insertions(+), 30 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 245b2caab6..3b1d04c211 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -37,6 +37,20 @@ margin: 0; } + +.form-control:focus { + color: #495057; + background-color: #fff; + color: rgb(255, 157, 255); + border-color: rgb(255, 157, 255); + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(255, 157, 255, 0.25); +} + +.categories input { + margin-left: 20px; +} + .btn-outline-success { color: rgba(131, 11, 142, 0.842); background-color: transparent; @@ -76,4 +90,8 @@ .log-in { margin-left: 15px; margin-right: 10px; +} + +.sm-margin { + margin-top: 1em; } \ No newline at end of file diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 1bcb274130..9415755930 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -9,11 +9,6 @@ body { text-align: center; } -.bold { - font-weight: 900; - -webkit-text-stroke: #ff9dff 1px; -} - main { margin-left: 2.5em; margin-right: 2.5em; @@ -104,6 +99,14 @@ a:hover { .nav-link { color: rgba(0, 0, 0, 0.5); } +// .nav_bar { +// list-style: none; +// display: flex; +// flex-wrap: wrap; +// justify-content: center; +// padding: 20px 10px; +// margin: 0; +// } .nav_bar_header ul li { padding: 20px 30px; @@ -124,16 +127,19 @@ a:hover { } .jumbotron { - margin-top: 36px; - padding-top: 36px; - padding-bottom: 36px; display: grid; grid-template: 3fr / 1fr 1fr; - grid-gap: 3vw; } -.jumbotron form { - display: inline; +.jumbotron h3 { + grid-column: 1 / 3; + } +// #footer { +// position: absolute; +// bottom: 0; +// width: 100%; +// height: 2.5rem; +// } diff --git a/app/assets/stylesheets/orders.scss b/app/assets/stylesheets/orders.scss index 0e0c3f87d9..c758695fbf 100644 --- a/app/assets/stylesheets/orders.scss +++ b/app/assets/stylesheets/orders.scss @@ -17,6 +17,6 @@ margin-top: 2em; } -.remove{ +.sm_margin { margin-top: 1em; } \ No newline at end of file diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss index 6a5211056a..62308dee3e 100644 --- a/app/assets/stylesheets/products.scss +++ b/app/assets/stylesheets/products.scss @@ -33,3 +33,6 @@ h4 { // max-width: 25vw; // } +.categories input { + margin-left: 20px; +} \ No newline at end of file diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index 0f8b9369c9..09993b8542 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -7,4 +7,6 @@

<%= "You are currently logged in as #{merchant.username}" %>

<%# wrap in class for footer %> <% end %> - \ No newline at end of file + + + diff --git a/app/views/items/_item_form.html.erb b/app/views/items/_item_form.html.erb index 6e2d3a0f69..ae8fbc7980 100644 --- a/app/views/items/_item_form.html.erb +++ b/app/views/items/_item_form.html.erb @@ -6,6 +6,6 @@ <%= f.number_field :quantity, required: true, in: 1..@product.stock %>
- <%= f.submit action, class: "btn btn-info sm_margin" %> + <%= f.submit action, class: "btn btn-info sm-margin" %>
<%end%> \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 17f2c8e82b..52f048aeb0 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -64,9 +64,8 @@
<%= flash[:success] %>
- <% elsif flash[:error] %> -
+
<%= flash[:error] %>
    <%flash.each do |label, problems|%> diff --git a/app/views/orders/_order_form.html.erb b/app/views/orders/_order_form.html.erb index c5276dcc37..db0c50b7b2 100644 --- a/app/views/orders/_order_form.html.erb +++ b/app/views/orders/_order_form.html.erb @@ -62,7 +62,7 @@
- <%=f.submit "Purchase", class:"btn btn-primary"%> + <%=f.submit "Purchase", class:"btn btn-outline-info sm-margin btn-block"%>
<%end%> diff --git a/app/views/orders/checkout.html.erb b/app/views/orders/checkout.html.erb index ff100e5d57..ada0b4d646 100644 --- a/app/views/orders/checkout.html.erb +++ b/app/views/orders/checkout.html.erb @@ -1,2 +1,2 @@ <%=render "order_form"%> -<%= link_to "Back to Cart", cart_path, class: "btn btn-outline-primary"%> \ No newline at end of file +<%= link_to "Back to Cart", cart_path, class: "btn btn-outline-secondary sm-margin"%> \ No newline at end of file diff --git a/app/views/orders/view_cart.html.erb b/app/views/orders/view_cart.html.erb index bfcc046b5e..51ac77ea53 100644 --- a/app/views/orders/view_cart.html.erb +++ b/app/views/orders/view_cart.html.erb @@ -11,17 +11,15 @@

<%=item.product.description%> <% @product = item.product %> <%= render partial: "/items/item_form", locals: {item: item, method_verb: :patch, action: "Update", url_path: item_path(item.id)} %> - <%= link_to "Remove item", item_path(item.id), method: :delete, class: "btn btn-outline-secondary remove"%> + <%= link_to "Remove item", item_path(item.id), method: :delete, class: "btn btn-outline-secondary sm_margin"%> <%end%> + <%= link_to "Check Out", checkout_cart_path, class: "btn btn-outline-info btn-block"%> + <%=link_to "Keep shopping", products_path, class: "btn btn-secondary btn-block" %> <%else%> -

0 items in cart

-

<%= link_to "Discover something intangible to fill it up", products_path%>

+

0 items in cart

+

<%= link_to "Discover something intangible to fill it up", products_path%>

<%end%> - -
-<%= link_to "Check Out", checkout_cart_path, class: "btn btn-outline-success btn-block"%> -<%=link_to "Keep shopping", products_path, class: "btn btn-info btn-block" %> -
\ No newline at end of file + \ No newline at end of file diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb index 2a6339b6a0..e180c7d17c 100644 --- a/app/views/products/_form.html.erb +++ b/app/views/products/_form.html.erb @@ -11,8 +11,8 @@
-
- <%=f.label "Categories"%> +
+ <%=f.label "Categories", class: ""%> <%= collection_check_boxes(:product, :category_ids, Category.all, :id, :name)%>
@@ -34,6 +34,6 @@
- <%=f.submit action_name, class:"btn btn-primary"%> + <%=f.submit action_name, class:"btn btn-info"%>
<% end %> \ No newline at end of file diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index eba9b959f2..a417e78cc1 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -1,4 +1,4 @@ -

Form for creating a new product

+

New Product Form

<%= render partial: "form", locals: { From 33dcdc15eb9563e6f1a1dbca688a8f06d83d6b82 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 01:14:16 -0700 Subject: [PATCH 237/260] missed change --- app/assets/stylesheets/orders.scss | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/assets/stylesheets/orders.scss b/app/assets/stylesheets/orders.scss index c758695fbf..e2d9820a63 100644 --- a/app/assets/stylesheets/orders.scss +++ b/app/assets/stylesheets/orders.scss @@ -15,8 +15,4 @@ .checkout { margin-top: 2em; -} - -.sm_margin { - margin-top: 1em; } \ No newline at end of file From cd284d9acd9b65e228b086343186901fd82877ca Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 01:22:05 -0700 Subject: [PATCH 238/260] fixed lost margin --- app/assets/stylesheets/homepages.scss | 2 +- app/views/items/_item_form.html.erb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 9415755930..c3d5047e29 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -10,6 +10,7 @@ body { } main { + margin-top: 2.0em; margin-left: 2.5em; margin-right: 2.5em; margin-bottom: 5vw; @@ -133,7 +134,6 @@ a:hover { .jumbotron h3 { grid-column: 1 / 3; - } // #footer { diff --git a/app/views/items/_item_form.html.erb b/app/views/items/_item_form.html.erb index ae8fbc7980..6eb45236da 100644 --- a/app/views/items/_item_form.html.erb +++ b/app/views/items/_item_form.html.erb @@ -6,6 +6,6 @@ <%= f.number_field :quantity, required: true, in: 1..@product.stock %>
- <%= f.submit action, class: "btn btn-info sm-margin" %> + <%= f.submit action, class: "btn btn-info btn-sm sm-margin" %>
<%end%> \ No newline at end of file From 8a068157c49b2b9fb26128c14121404fbbe2a24d Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 01:27:09 -0700 Subject: [PATCH 239/260] fixed bug for add items with 0 quantity to cart --- app/views/items/_item_form.html.erb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/views/items/_item_form.html.erb b/app/views/items/_item_form.html.erb index 6eb45236da..e2c5c12ac5 100644 --- a/app/views/items/_item_form.html.erb +++ b/app/views/items/_item_form.html.erb @@ -3,9 +3,13 @@
<%= f.label :Quantity%> + <% if @product.stock > 0%> <%= f.number_field :quantity, required: true, in: 1..@product.stock %> + <% else %> + <%= f.number_field :quantity, required: true, in: 0..1 %> + <%end%>
- <%= f.submit action, class: "btn btn-info btn-sm sm-margin" %> + <%= f.submit action, class: "btn btn-info sm-margin" %>
<%end%> \ No newline at end of file From e185319b10dc94512ea4711e3e0ce444c0cdab42 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 01:31:01 -0700 Subject: [PATCH 240/260] fixed money precison on order form total page --- app/views/orders/_order_form.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/orders/_order_form.html.erb b/app/views/orders/_order_form.html.erb index db0c50b7b2..6dee80b655 100644 --- a/app/views/orders/_order_form.html.erb +++ b/app/views/orders/_order_form.html.erb @@ -23,7 +23,7 @@
<%# REMOVE h3, temp added to get a feel for style%> - +
<%= link_to "Order ID: #{Order.find(order).id}", order_path(Order.find(order).id), class: "btn btn-outline-primary btn-sm" %> <%= link_to "Order ID: #{Order.find(order).id}", order_path(Order.find(order).id), class: "btn btn-outline-success btn-sm" %> Date & Time of order: <%= Order.find(order).created_at.strftime("%B %d, %T")%> Order Status: <%= Order.find(order).status %> $<%= "%.2f" % (product.price / 100.0)%> <%=product.description %> <%=product.active? ? "Active" : "Retired" %> - <%=link_to "Retire product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary btn-sm" if product.active?%> - <%=link_to "Activate product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-primary btn-sm" if product.active? == false%><%=link_to "Edit product", edit_product_path(product.id), class: "btn btn-outline-primary btn-sm" if product.active?%><%=link_to "Retire product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-success btn-sm" if product.active?%> + <%=link_to "Activate product", toggle_inactive_path(product.id), method: :patch, class: "btn btn-outline-success btn-sm" if product.active? == false%><%=link_to "Edit product", edit_product_path(product.id), class: "btn btn-outline-success btn-sm" if product.active?%>

Total:

$<%=@order.total%>

$<%="%0.2f" % [@order.total]%>

From db18050a978e37d9013c7fcdf66ae655cb4abe5d Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 01:33:41 -0700 Subject: [PATCH 241/260] updated class name --- app/views/orders/view_cart.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/orders/view_cart.html.erb b/app/views/orders/view_cart.html.erb index 51ac77ea53..98ad360adb 100644 --- a/app/views/orders/view_cart.html.erb +++ b/app/views/orders/view_cart.html.erb @@ -11,7 +11,7 @@

<%=item.product.description%> <% @product = item.product %> <%= render partial: "/items/item_form", locals: {item: item, method_verb: :patch, action: "Update", url_path: item_path(item.id)} %> - <%= link_to "Remove item", item_path(item.id), method: :delete, class: "btn btn-outline-secondary sm_margin"%> + <%= link_to "Remove item", item_path(item.id), method: :delete, class: "btn btn-outline-secondary sm-margin"%>

<%end%> From 925733855bcca33d9da9905a1e79dded84f755de Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 02:00:16 -0700 Subject: [PATCH 242/260] animation home pg, short --- app/assets/stylesheets/homepages.scss | 53 +++++++++++++++++++++++++++ app/views/homepages/index.html.erb | 3 +- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index c3d5047e29..2a6872b1f3 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -143,3 +143,56 @@ a:hover { // height: 2.5rem; // } +.img { + border: none; + margin-top: -10px; +} + + +/* ---------------------------------------------- + * Generated by Animista on 2019-5-10 1:57:28 + * w: http://animista.net, t: @cssanimista + * ---------------------------------------------- */ + +/** + * ---------------------------------------- + * animation roll-in-blurred-left + * ---------------------------------------- + */ + @-webkit-keyframes roll-in-blurred-left { + 0% { + -webkit-transform: translateX(-1000px) rotate(-720deg); + transform: translateX(-1000px) rotate(-720deg); + -webkit-filter: blur(50px); + filter: blur(50px); + opacity: 0; + } + 100% { + -webkit-transform: translateX(0) rotate(0deg); + transform: translateX(0) rotate(0deg); + -webkit-filter: blur(0); + filter: blur(0); + opacity: 1; + } +} +@keyframes roll-in-blurred-left { + 0% { + -webkit-transform: translateX(-1000px) rotate(-720deg); + transform: translateX(-1000px) rotate(-720deg); + -webkit-filter: blur(50px); + filter: blur(50px); + opacity: 0; + } + 100% { + -webkit-transform: translateX(0) rotate(0deg); + transform: translateX(0) rotate(0deg); + -webkit-filter: blur(0); + filter: blur(0); + opacity: 1; + } +} + +.roll-in-blurred-left { + -webkit-animation: roll-in-blurred-left 0.65s cubic-bezier(0.230, 1.000, 0.320, 1.000) both; + animation: roll-in-blurred-left 0.65s cubic-bezier(0.230, 1.000, 0.320, 1.000) both; +} \ No newline at end of file diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index 09993b8542..b073627c14 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -1,7 +1,6 @@

Intangibly

-

find your magic

- +

<%= image_tag "intangible.png", class: "img" %>find your magic

<% if session[:merchant_id] %> <% merchant = Merchant.find_by(id: session[:merchant_id]) %>

<%= "You are currently logged in as #{merchant.username}" %>

From f0b2ddcb8cf0fe8b7aef5edfb30347731d529d7b Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Fri, 10 May 2019 07:03:36 -0700 Subject: [PATCH 243/260] On products index page, added price and added card look. Adjusted spacing. --- app/assets/stylesheets/homepages.scss | 4 ++++ app/assets/stylesheets/products.scss | 27 +++++++++++++++++++-------- app/views/products/index.html.erb | 7 ++++--- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 1bcb274130..099f326c94 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -14,6 +14,10 @@ body { -webkit-text-stroke: #ff9dff 1px; } +.pink { + color: #ff9dff; +} + main { margin-left: 2.5em; margin-right: 2.5em; diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss index 6a5211056a..e9bdba4c5b 100644 --- a/app/assets/stylesheets/products.scss +++ b/app/assets/stylesheets/products.scss @@ -3,7 +3,7 @@ // You can use Sass (SCSS) here: http://sass-lang.com/ img { - border: .1em #333333 solid; + border-bottom: .1em #333333 solid; max-width: 200px; max-height: 200px; } @@ -16,6 +16,21 @@ img { align-items: flex-start; } + + +.flex-item-products { + background-color: #e6e6fa; + border: #333333 .1em solid; + text-align: center; + margin-bottom: 1em; + margin-left: .4em; + margin-right: .4em; + } + + .flex-item-products p { + margin: .3em; + } + img.detail { max-width: 40vw; max-height: 300px; @@ -25,11 +40,7 @@ h4 { margin-top: 1em; } - - -// div.flex-item { -// display: flex; -// flex-flow: column wrap; -// max-width: 25vw; -// } +.strong { + font-weight: bolder; +} diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 8882888ed3..30bc7f4b29 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -6,10 +6,11 @@ <% Product.where(active: true).each do |product| %> - +
<%= link_to image_tag(product.photo_url), product_path(product.id) %> -

<%= link_to product.name, product_path(product.id) %>

- +

<%= link_to product.name, product_path(product.id) %>

+

Price: $ <%= "%.2f" % (product.price / 100.0) %>

+
<% end %>
\ No newline at end of file From 73d4f1f1ae016978797eb777529b9e4c09419a17 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Fri, 10 May 2019 07:30:37 -0700 Subject: [PATCH 244/260] Removed helvetica font. Styled the merchant and categories pages. --- app/assets/stylesheets/application.scss | 17 +++++++++-------- app/assets/stylesheets/homepages.scss | 12 +++++++----- app/assets/stylesheets/products.scss | 2 ++ app/views/categories/index.html.erb | 4 ++-- app/views/merchants/index.html.erb | 4 ++-- 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index afa576a0fa..f21cee66ea 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -19,11 +19,12 @@ .nav-item { color: rgba(131, 11, 142, 0.842); } - .nav_bar { - list-style: none; - display: flex; - flex-wrap: wrap; - justify-content: center; - padding: 20px 10px; - margin: 0; - } + +.nav_bar { + list-style: none; + display: flex; + flex-wrap: wrap; + justify-content: center; + padding: 20px 10px; + margin: 0; +} diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 099f326c94..4e53d5d311 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -2,9 +2,11 @@ // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ body { - font-family: Helvetica, Arial, sans-serif; - + font-family: Arial, sans-serif; } + +// possible new fonts: +// font-family: Verdana, Geneva .centered { text-align: center; } @@ -25,7 +27,7 @@ main { } h1 { - font-family: 'League Script', Helvetica, Arial, sans-serif; + font-family: 'League Script', Arial, sans-serif; font-weight:bold; font-size: 10em; color: rgb(198, 158, 255); @@ -33,7 +35,7 @@ h1 { } h2 { - font-family: 'League Script', Helvetica, Arial, sans-serif; + font-family: 'League Script', Arial, sans-serif; font-size: 70px; color: rgb(198, 158, 255); text-align: center; @@ -119,7 +121,7 @@ a:hover { } .centered-arial { - font-family: helvetica, Arial, sans-serif; + font-family: Arial, sans-serif; color:rgb(87, 87, 87); font-size: 1.3em; diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss index e9bdba4c5b..32f6927f5d 100644 --- a/app/assets/stylesheets/products.scss +++ b/app/assets/stylesheets/products.scss @@ -14,6 +14,8 @@ img { flex-direction: row; justify-content: space-around; align-items: flex-start; + margin-top: 1.5em; + margin-left: 0; } diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index 76433d1a82..0acc18e91e 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -1,8 +1,8 @@

Categories

-
    +
      <% @categories.each do |category| %>
    • - <%= link_to category.name, category_path(category.id) %> +

      <%= link_to category.name, category_path(category.id) %>

    • <% end %>
    diff --git a/app/views/merchants/index.html.erb b/app/views/merchants/index.html.erb index 506d977c65..13921b9b85 100644 --- a/app/views/merchants/index.html.erb +++ b/app/views/merchants/index.html.erb @@ -1,8 +1,8 @@

    Merchants

    -
      +
        <% @merchants.each do |merchant| %>
      • - <%= link_to merchant.username, merchant_path(merchant.id) %> +

        <%= link_to merchant.username, merchant_path(merchant.id) %>

      • <% end %>
      \ No newline at end of file From b6c5004ec9aa4a6f0c1c3f2529fc704e92d83a92 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Fri, 10 May 2019 07:55:46 -0700 Subject: [PATCH 245/260] Minor code cleanups. Also image suggestion currently commented out. --- app/assets/stylesheets/homepages.scss | 10 +++++----- app/views/categories/show.html.erb | 2 +- app/views/homepages/index.html.erb | 3 ++- app/views/layouts/application.html.erb | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 4e53d5d311..424a02dd4b 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -2,6 +2,7 @@ // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ body { + // background-image: url("https://picserio.com/data/out/166/winter-scenery-wallpaper-for-desktop_3829525.jpg"); font-family: Arial, sans-serif; } @@ -78,15 +79,14 @@ a:hover { text-decoration: none; } -.greybg { - background-color: rgb(255, 255, 255); - -} - .whitebg { background-color: #fff; } +#background-image-magical { + background-color: transparent; +} + .centered_grey_text { text-align: center; font-size: 2em; diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 9cdda4b355..47e81b3e18 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -1,4 +1,4 @@ -
      +

      Category: <%= @category.name %>

      diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index 0f8b9369c9..b3ea8eed46 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -1,4 +1,5 @@ -
      +
      +

      Intangibly

      find your magic

      diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 1bc3b755cb..c9c08cfffd 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -8,7 +8,7 @@ href= "https://fonts.googleapis.com/css?family=Raleway+Dots:regular;"/> - SECRETS + Intangibly <%= csrf_meta_tags %> <%= csp_meta_tag %> From 33d99f586909c2ec6314fff836a0c847b828e7a8 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 11:55:45 -0700 Subject: [PATCH 246/260] fixed item count display --- app/views/orders/view_cart.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/orders/view_cart.html.erb b/app/views/orders/view_cart.html.erb index 98ad360adb..5bb80d5c58 100644 --- a/app/views/orders/view_cart.html.erb +++ b/app/views/orders/view_cart.html.erb @@ -1,6 +1,6 @@
      <%if @order && @order.items.any? %> -

      <%=@order.items.count%> item<%="s" if @order.items.count != 1%> in cart

      +

      <%=@order.items.sum {|item| item.quantity}%> item<%="s" if @order.items.count != 1%> in cart

      <%@order.items.each do |item| %>
      From b8f9cc7b1f9ca9912e341764e8264663c0c4509a Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 12:02:57 -0700 Subject: [PATCH 247/260] fixed margin --- app/assets/stylesheets/application.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index ec2d586e06..86c45ae9a7 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -53,6 +53,10 @@ margin-left: 20px; } +.btn-sm, .btn-group-sm > .btn { + margin-bottom: 0em; +} + .btn-outline-success { color: rgba(131, 11, 142, 0.842); background-color: transparent; From ee4185d08d64be5ac87f1baae945468cf4ab5adb Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Fri, 10 May 2019 12:04:29 -0700 Subject: [PATCH 248/260] Styled the Merchant Products page. Centered the back-to buttons at the bottom. --- app/views/categories/show.html.erb | 9 +++++---- app/views/merchants/show.html.erb | 24 ++++++++++++++---------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 5785d6c8ca..71a05e536c 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -1,5 +1,5 @@
      -

      <%= @category.name %>

      +

      Shop <%= @category.name %>

      <% if @category.product_ids.any? %>
      @@ -19,6 +19,7 @@ <% end %>
      -<%= link_to "Back to all products", products_path, class: "btn btn-outline-success btn-sm" %> - -<%= link_to "Back to all categories", categories_path, class: "btn btn-outline-success btn-sm" %> \ No newline at end of file +
      + <%= link_to "Back to all products", products_path, class: "btn btn-outline-success btn-sm" %> + <%= link_to "Back to all categories", categories_path, class: "btn btn-outline-success btn-sm" %> +
      \ No newline at end of file diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index 7a9a51d5fa..a7ba58c573 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -1,21 +1,25 @@
      -

      - Merchant: <%= @merchant.username %> -

      +

      Shop <%= @merchant.username %>

      -

      Products:

      <% if @merchant.product_ids.any? %> -
        +
        - <% @merchant.product_ids.each do |product| %> -
      • <%= link_to Product.find(product).name, product_path(product) if Product.find(product).active? %>
      • + <% @merchant.products.each do |product| %> +
        + <%= link_to image_tag(product.photo_url), product_path(product.id) %> +

        <%= link_to product.name, product_path(product) if product.active %>

        + +

        Price: $ <%= "%.2f" % (product.price / 100.0) %>

        +
        <% end %> -
      +
      <% else %>

      There are no products for this merchant

      <% end %>
      -<%= link_to "Back to all products", products_path %> -<%= link_to "Back to all merchants", merchants_path %> \ No newline at end of file +
      + <%= link_to "Back to all products", products_path, class: "btn btn-outline-success btn-sm" %> + <%= link_to "Back to all merchants", merchants_path, class: "btn btn-outline-success btn-sm" %> +
      \ No newline at end of file From 2fe6e0822246bf77f3e22b725d1308ae69c4948f Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Fri, 10 May 2019 12:07:49 -0700 Subject: [PATCH 249/260] added pink hover to categories and products --- app/assets/stylesheets/homepages.scss | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 503994cf75..df093f7db5 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -61,6 +61,13 @@ h4 { color:grey; } +h4 a:hover { + font-family: 'Raleway Dots', Arial, sans-serif; + font-weight:bold; + font-size: 30px; + color: rgb(255, 157, 255); +} + .bg-purple { background-color: lavender; } From 2149be910cc3c532a682503981df8067d0b85a40 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 12:15:09 -0700 Subject: [PATCH 250/260] fixed margins on toggle bar --- app/assets/stylesheets/application.scss | 15 +++++++++++---- app/views/layouts/application.html.erb | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 86c45ae9a7..6fe91010ea 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -85,19 +85,26 @@ #cart { - margin-right: 10px; + margin-bottom: 5px; + margin-right: 25px; + // margin-top: -5px; } .dash-link { - margin-left: 0px; - margin-right: 10px; + margin-left: -15px; + margin-right: 13px; } .log-in { - margin-left: 15px; + // margin-left: 15px; margin-right: 10px; } +.log-out { + margin-left: 0px; + +} + .sm-margin { margin-top: 1em; } diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 52f048aeb0..9e320b8c01 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -48,7 +48,7 @@ <% if session[:merchant_id] %> <% merchant = Merchant.find_by(id: session[:merchant_id]) %> <%= link_to merchant.username, current_merchant_path, class: "dash-link nav-link"%> - <%= link_to "Log Out", logout_path, method: "delete", class: "btn btn-outline-success my-2 my-sm-0" %> + <%= link_to "Log Out", logout_path, method: "delete", class: "log-out btn btn-outline-success my-2 my-sm-0" %> <% else %> <%= link_to "Log In", github_login_path, class: "log-in btn btn-outline-success my-2 my-sm-0" %> <% end %> From 2ce610dfcebcecf2ca76f890645344bd632c7b19 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Fri, 10 May 2019 12:21:32 -0700 Subject: [PATCH 251/260] upcase prod name on merchant and categories show, view cart, prod index, and prod show --- app/views/categories/show.html.erb | 2 +- app/views/merchants/show.html.erb | 2 +- app/views/orders/confirmation.html.erb | 2 +- app/views/orders/view_cart.html.erb | 2 +- app/views/products/index.html.erb | 2 +- app/views/products/show.html.erb | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 71a05e536c..a572910e7e 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -7,7 +7,7 @@ <% @category.products.each do |product| %>
      <%= link_to image_tag(product.photo_url), product_path(product.id) %> -

      <%= link_to product.name, product_path(product) if product.active %>

      +

      <%= link_to product.name.upcase, product_path(product) if product.active %>

      Price: $ <%= "%.2f" % (product.price / 100.0) %>

      diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index a7ba58c573..51a3a87d29 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -7,7 +7,7 @@ <% @merchant.products.each do |product| %>
      <%= link_to image_tag(product.photo_url), product_path(product.id) %> -

      <%= link_to product.name, product_path(product) if product.active %>

      +

      <%= link_to product.name.upcase, product_path(product) if product.active %>

      Price: $ <%= "%.2f" % (product.price / 100.0) %>

      diff --git a/app/views/orders/confirmation.html.erb b/app/views/orders/confirmation.html.erb index 872923e879..d3d0f8152e 100644 --- a/app/views/orders/confirmation.html.erb +++ b/app/views/orders/confirmation.html.erb @@ -20,7 +20,7 @@ <%@order.items.each_with_index do |item| %> <%=item.quantity%> - <%=link_to item.product.name, product_path(item.product.id) %> + <%=link_to item.product.name.upcase, product_path(item.product.id) %> $<%= "%.2f" % (item.product.price / 100.0)%> $<%= "%.2f" % item.subtotal %> diff --git a/app/views/orders/view_cart.html.erb b/app/views/orders/view_cart.html.erb index 5bb80d5c58..3b04a4c5ce 100644 --- a/app/views/orders/view_cart.html.erb +++ b/app/views/orders/view_cart.html.erb @@ -5,7 +5,7 @@ <%@order.items.each do |item| %>
      -

      <%=item.product.name%>

      +

      <%=item.product.name.upcase%>

      quantity: <%=item.quantity%>

      subtotal: $<%=item.subtotal%>

      <%=item.product.description%> diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 8e2a9bddd0..8e3ad96320 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -5,7 +5,7 @@

      <%= link_to image_tag(product.photo_url), product_path(product.id) %> -

      <%= link_to product.name, product_path(product.id) %>

      +

      <%= link_to product.name.upcase, product_path(product.id) %>

      Price: $ <%= "%.2f" % (product.price / 100.0) %>

      <% end %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 69f608043e..e3ef39f0a8 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,5 +1,5 @@
      -

      <%= @product.name %>

      +

      <%= @product.name.upcase %>

      <%= image_tag @product.photo_url, alt: "Image of the product", class: "detail" %> From 8e8276636b62cd12451fa4f5bfc116e769b402f9 Mon Sep 17 00:00:00 2001 From: Margaret Finnan Date: Fri, 10 May 2019 12:22:34 -0700 Subject: [PATCH 252/260] added upcase to merch dash --- app/views/merchants/current.html.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/merchants/current.html.erb b/app/views/merchants/current.html.erb index ccf5ad37e2..42bb62f610 100644 --- a/app/views/merchants/current.html.erb +++ b/app/views/merchants/current.html.erb @@ -67,7 +67,7 @@ <%items.each do |item| %> <%=item.quantity%> - <%=link_to item.product.name, product_path(item.product.id) %> + <%=link_to item.product.name.upcase, product_path(item.product.id) %> $<%= "%.2f" % (item.product.price / 100.0)%> $<%="%.2f" % (item.subtotal) %> @@ -96,7 +96,7 @@ <% @products.each do |product|%> <%=product.id%> - <%=link_to product.name, product_path(product.id) %> + <%=link_to product.name.upcase, product_path(product.id) %> $<%= "%.2f" % (product.price / 100.0)%> <%=product.description %> <%=product.active? ? "Active" : "Retired" %> From 439839434713d279deb3cd8d7230e04b979313a3 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 12:24:03 -0700 Subject: [PATCH 253/260] fixed bug --- app/views/categories/show.html.erb | 16 +++++++++------- app/views/merchants/show.html.erb | 14 ++++++++------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 71a05e536c..66026af05b 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -5,13 +5,15 @@
      <% @category.products.each do |product| %> -
      - <%= link_to image_tag(product.photo_url), product_path(product.id) %> -

      <%= link_to product.name, product_path(product) if product.active %>

      - -

      Price: $ <%= "%.2f" % (product.price / 100.0) %>

      -
      - <% end %> + <% if product.active %> +
      + <%= link_to image_tag(product.photo_url), product_path(product.id) %> +

      <%= link_to product.name, product_path(product)%>

      + +

      Price: $ <%= "%.2f" % (product.price / 100.0) %>

      +
      + <% end %> + <% end %>
      <% else %> diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index a7ba58c573..a9fabbb98d 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -5,12 +5,14 @@
      <% @merchant.products.each do |product| %> -
      - <%= link_to image_tag(product.photo_url), product_path(product.id) %> -

      <%= link_to product.name, product_path(product) if product.active %>

      - -

      Price: $ <%= "%.2f" % (product.price / 100.0) %>

      -
      + <% if product.active %> +
      + <%= link_to image_tag(product.photo_url), product_path(product.id) %> +

      <%= link_to product.name, product_path(product) %>

      + +

      Price: $ <%= "%.2f" % (product.price / 100.0) %>

      +
      + <% end %> <% end %>
      From 602014e0d971ac0209b4fffe9f18f94c0ea15230 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Fri, 10 May 2019 12:30:03 -0700 Subject: [PATCH 254/260] Made H4s on category and merchant pages thicker with a stroke, incl rollover. --- app/assets/stylesheets/homepages.scss | 5 +++++ app/views/categories/index.html.erb | 2 +- app/views/merchants/index.html.erb | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index df093f7db5..73230983f1 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -18,6 +18,10 @@ body { -webkit-text-stroke: #ff9dff 1px; } +.bold-grey { + -webkit-text-stroke: grey 1px; +} + .pink { color: #ff9dff; } @@ -66,6 +70,7 @@ h4 a:hover { font-weight:bold; font-size: 30px; color: rgb(255, 157, 255); + -webkit-text-stroke: rgb(255, 157, 255) 1px; } .bg-purple { diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index 9a2586682c..5a96857ab7 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -2,5 +2,5 @@ <% @categories.each do |category| %> -

      <%= link_to category.name, category_path(category.id) %>

      +

      <%= link_to category.name, category_path(category.id) %>

      <% end %> diff --git a/app/views/merchants/index.html.erb b/app/views/merchants/index.html.erb index 6a0bf3e0d1..36d6a2e7f9 100644 --- a/app/views/merchants/index.html.erb +++ b/app/views/merchants/index.html.erb @@ -2,6 +2,6 @@ <% @merchants.each do |merchant| %> -

      <%= link_to merchant.username, merchant_path(merchant.id) %>

      +

      <%= link_to merchant.username, merchant_path(merchant.id) %>

      <% end %> From 1c8ae9aa37b8521f90448573247168f306ed9ec6 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 12:38:02 -0700 Subject: [PATCH 255/260] added style for footer --- app/assets/stylesheets/application.scss | 10 ++++++++++ app/views/homepages/index.html.erb | 2 +- app/views/layouts/application.html.erb | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index c7dd9883b1..cfd8e11d01 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -108,3 +108,13 @@ .sm-margin { margin-top: 1em; } + +.footer { + background-color: lavender; +} + +.sm-img{ + width: 25px; + border: none; + margin-bottom: 4px; +} \ No newline at end of file diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index a8c9ef045c..bfed20db32 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -1,7 +1,7 @@

      Intangibly

      -

      <%= image_tag "intangible.png", class: "img" %>find your magic

      +

      <%= image_tag "intangible.png", alt: "logo", class: "img" %>find your magic

      <% if session[:merchant_id] %> <% merchant = Merchant.find_by(id: session[:merchant_id]) %>

      <%= "You are currently logged in as #{merchant.username}" %>

      diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 9e320b8c01..9651402eff 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -86,6 +86,9 @@
      <%= yield %>
      +
      +

      © Intangebelle Inc. 2019 <%= image_tag "intangible.png", alt: "logo", class: "sm-img"%>

      +
      From 336c9d7af5051da18b2b806e3f617de5323cd342 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Fri, 10 May 2019 12:55:07 -0700 Subject: [PATCH 256/260] Adjusted text on products index. --- app/assets/stylesheets/homepages.scss | 12 ++++-------- app/assets/stylesheets/products.scss | 2 +- app/views/products/index.html.erb | 4 ++-- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss index 73230983f1..9e97508988 100644 --- a/app/assets/stylesheets/homepages.scss +++ b/app/assets/stylesheets/homepages.scss @@ -26,6 +26,10 @@ body { color: #ff9dff; } +.geneva { + font-family: Geneva; +} + main { margin-top: 2.0em; @@ -125,14 +129,6 @@ a:hover { .nav-link { color: rgba(0, 0, 0, 0.5); } -// .nav_bar { -// list-style: none; -// display: flex; -// flex-wrap: wrap; -// justify-content: center; -// padding: 20px 10px; -// margin: 0; -// } .nav_bar_header ul li { padding: 20px 30px; diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss index 0b22b7b331..c150e2929a 100644 --- a/app/assets/stylesheets/products.scss +++ b/app/assets/stylesheets/products.scss @@ -43,7 +43,7 @@ h4 { } .strong { - font-weight: bolder; + font-weight: bold; } .categories input { diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 8e2a9bddd0..0dacaccaaa 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -3,9 +3,9 @@ <% Product.where(active: true).each do |product| %> -
      +
      <%= link_to image_tag(product.photo_url), product_path(product.id) %> -

      <%= link_to product.name, product_path(product.id) %>

      +

      <%= link_to product.name, product_path(product.id) %>

      Price: $ <%= "%.2f" % (product.price / 100.0) %>

      <% end %> From d44be3ae6775eeb83fcc990a24c8f43af29d0319 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 12:55:48 -0700 Subject: [PATCH 257/260] fixed min height on main --- app/assets/stylesheets/application.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index cfd8e11d01..04d97f45e0 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -117,4 +117,8 @@ width: 25px; border: none; margin-bottom: 4px; +} + +main { + min-height: 73vh; } \ No newline at end of file From f54fa5a40e9108904d93751830b53acc368d8718 Mon Sep 17 00:00:00 2001 From: Mello-Cello Date: Fri, 10 May 2019 13:04:43 -0700 Subject: [PATCH 258/260] Added margin to new product form categories check boxes. --- app/assets/stylesheets/products.scss | 10 ++++++++-- app/views/products/_form.html.erb | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss index c150e2929a..9ee9950608 100644 --- a/app/assets/stylesheets/products.scss +++ b/app/assets/stylesheets/products.scss @@ -47,5 +47,11 @@ h4 { } .categories input { - margin-left: 20px; -} \ No newline at end of file +// margin-left: 20px; + margin-right: .4em; + margin-bottom: 1.5em; +} + +.form-check.categories { + margin-left: 0%; +} diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb index e180c7d17c..896d4e946f 100644 --- a/app/views/products/_form.html.erb +++ b/app/views/products/_form.html.erb @@ -12,7 +12,7 @@
      - <%=f.label "Categories", class: ""%> + <%=f.label "Categories"%> <%= collection_check_boxes(:product, :category_ids, Category.all, :id, :name)%>
      From c49a4caacbe79f3683cbce2af04da9843bb944a5 Mon Sep 17 00:00:00 2001 From: Cloudy Lopez Date: Fri, 10 May 2019 13:29:37 -0700 Subject: [PATCH 259/260] descriptions done --- db/products_data.csv | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/db/products_data.csv b/db/products_data.csv index ef006052cd..a63a075b8c 100644 --- a/db/products_data.csv +++ b/db/products_data.csv @@ -1,21 +1,21 @@ name,price,stock,description,photo_url -high fives,3990,3,They’ve got as much sex appeal as a road accident.,https://i.ibb.co/jD3rcp0/camylla-battani-784361-unsplash.jpg -cup of sunshine,4277,6,"But Mr. Dent, the plans have been available in the local planning office for the last nine months.",https://i.ibb.co/16kjtyH/mi-pham-223464-unsplash.jpg -bucket of sunshine,2089,3,Don’t Panic.,https://i.ibb.co/SBcwL51/hemerson-coelho-1364589-unsplash.jpg -sleep revival,4799,5,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://i.ibb.co/qsyp1TL/isaac-davis-598918-unsplash.jpg -relaxation,3361,8,there’s an infinite number of monkeys outside who want to talk to us about this script for Hamlet they’ve worked out.,https://i.ibb.co/ZS6t12d/allef-vinicius-111554-unsplash.jpg -energy,1131,6,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/qW7q6PW/maria-fernanda-gonzalez-461521-unsplash.jpg -a good hair day,637,7,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/ZhfmGX8/bruno-nascimento-149663-unsplash.jpg -pause time,1758,4,take time to study for the test,https://i.ibb.co/RzHDBvx/ahmadreza-sajadi-10140-unsplash.jpg -freshly showered,4963,8,Parts of the inside of her head screamed at other parts of the inside of her head.,https://i.ibb.co/0D9th8Z/michael-podger-252489-unsplash.jpg -teleport into bed,3216,6,if you’ve never been through a matter transference beam before you’ve probably lost some salt and protein. The beer you had should have cushioned your system a bit.,https://i.ibb.co/nk5FkwV/diego-ph-493991-unsplash.jpg -ada starter kit,2397,5,"Whatever your tastes, Magrathea can cater for you. We are not proud.",https://i.ibb.co/ssgbQqH/ishan-seefromthesky-277746-unsplash.jpg -ada best seller pack,4517,8,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/XCc7kxc/recal-media-83365-unsplash.jpg -cup of rainbows,4282,4,"It’s only half completed, I’m afraid – we haven’t even finished burying the artificial dinosaur skeletons in the crust yet.",https://i.ibb.co/LprTnc8/alistair-macrobert-633034-unsplash.jpg -puppy play pack,2803,8,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/M1xGDJ0/bharathi-kannan-1260953-unsplash.jpg -kitten cuddles,4928,7,"Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.",https://i.ibb.co/GdT7fWn/kote-puerto-771605-unsplash.jpg -giggle party,3250,3,"It seemed to me that any civilization that had so far lost its head as to need to include a set of detailed instructions for use in a packet of toothpicks, was no longer a civilization in which I could live and stay sane.",https://i.ibb.co/7WNs7Y3/carlos-pimentel-1206339-unsplash.jpg -bestfriend time,2332,11,"According to the legends, the Magratheans lived most of their lives underground.",https://i.ibb.co/Jd4nkWQ/ian-schneider-64307-unsplash.jpg -juicy secret,1170,5,"Evolution? they said to themselves, Who needs it?",https://i.ibb.co/pP0xbMM/dan-cook-508166-unsplash.jpg -inside joke moment,4141,4,"On the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much—the wheel, New York, wars and so on—whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, the dolphins had always believed that they were far more intelligent than man—for precisely the same reasons.",https://i.ibb.co/PN6tfQY/marcela-rogante-432403-unsplash.jpg -bondfire time,2976,4,its a nice time,https://i.ibb.co/JR78YWq/mike-erskine-144525-unsplash.jpg \ No newline at end of file +High Fives,3990,3,Best highfives! When your down highfives will make you touch sky! ,https://i.ibb.co/jD3rcp0/camylla-battani-784361-unsplash.jpg +Cup of Sunshine,4277,6,Brighest sunshine overflowing the biggest cup.,https://i.ibb.co/16kjtyH/mi-pham-223464-unsplash.jpg +Bucket of Sunshine,2089,3,When the biggest cup is not enough grap a bucket of our brightest sunshine!,https://i.ibb.co/SBcwL51/hemerson-coelho-1364589-unsplash.jpg +Sleep Revival,4799,5,Kids? Work? Sleep revival is the cure all. Sleep 10 hrs in just 30 mins!,https://i.ibb.co/qsyp1TL/isaac-davis-598918-unsplash.jpg +Relaxation,3361,8,Relaxation not constipation. Calm those nerves and treat your self well.,https://i.ibb.co/ZS6t12d/allef-vinicius-111554-unsplash.jpg +Energy,1131,6,What!!!!! Lets GO! Engergy yo! On demand or in the sand.,https://i.ibb.co/qW7q6PW/maria-fernanda-gonzalez-461521-unsplash.jpg +A Good Hair Day,637,7,For that special occasion when you really do and need great hair.,https://i.ibb.co/ZhfmGX8/bruno-nascimento-149663-unsplash.jpg +Pause Time,1758,4,Stop time at the drop of a dime. This product is a gold mine,https://i.ibb.co/RzHDBvx/ahmadreza-sajadi-10140-unsplash.jpg +Freshly Showered,4963,8,Projects are hard, make your life easier by feeling freshly showered.,https://i.ibb.co/0D9th8Z/michael-podger-252489-unsplash.jpg +Teleport Into Bed,3216,6,Open incase of emergency.,https://i.ibb.co/nk5FkwV/diego-ph-493991-unsplash.jpg +Ada Starter Kit,2397,5,The ADA starter kit features the things that hardworking Adies need, relaxation, reflection, and a calm mind.,https://i.ibb.co/ssgbQqH/ishan-seefromthesky-277746-unsplash.jpg +Ada Best Seller Pack,4517,8,Take some time to yourself. Work hard and play hard.,https://i.ibb.co/XCc7kxc/recal-media-83365-unsplash.jpg +Cup of Rainbows,4282,4,Find something magical in your day and in yourself.,https://i.ibb.co/LprTnc8/alistair-macrobert-633034-unsplash.jpg +Puppy play Pack,2803,8,Unwind with Puppy Time. You'll thank us later.,https://i.ibb.co/M1xGDJ0/bharathi-kannan-1260953-unsplash.jpg +kitten cuddles,4928,7,Stop Kitten Yourself! Take some time to unwind and cuddle.,https://i.ibb.co/GdT7fWn/kote-puerto-771605-unsplash.jpg +Giggle Party,3250,3,Sometimes unwinding just means giggling...HARD.,https://i.ibb.co/pP0xbMM/dan-cook-508166-unsplash.jpg +Bestfriend Time,2332,11,Self care is important so take some time to catch up!,https://i.ibb.co/Jd4nkWQ/ian-schneider-64307-unsplash.jpg +Juicy Secret,1170,5,The Juciest Secret to put some pep in your step.,https://i.ibb.co/PN6tfQY/marcela-rogante-432403-unsplash.jpg +Inside Joke Moment,4141,4,Take a pause and lighten the mood with an inside joke moment,https://i.ibb.co/7WNs7Y3/carlos-pimentel-1206339-unsplash.jpg +Bondfire Time,2976,4,Sometimes all you need is a BONDfire to reconnect with friends.,https://i.ibb.co/JR78YWq/mike-erskine-144525-unsplash.jpg \ No newline at end of file From 206db2617d977d1ee529308077c9959dee99bc46 Mon Sep 17 00:00:00 2001 From: qqdipps Date: Fri, 10 May 2019 13:33:56 -0700 Subject: [PATCH 260/260] reseed data --- db/products_data.csv | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/db/products_data.csv b/db/products_data.csv index a63a075b8c..0015a49609 100644 --- a/db/products_data.csv +++ b/db/products_data.csv @@ -7,9 +7,9 @@ Relaxation,3361,8,Relaxation not constipation. Calm those nerves and treat your Energy,1131,6,What!!!!! Lets GO! Engergy yo! On demand or in the sand.,https://i.ibb.co/qW7q6PW/maria-fernanda-gonzalez-461521-unsplash.jpg A Good Hair Day,637,7,For that special occasion when you really do and need great hair.,https://i.ibb.co/ZhfmGX8/bruno-nascimento-149663-unsplash.jpg Pause Time,1758,4,Stop time at the drop of a dime. This product is a gold mine,https://i.ibb.co/RzHDBvx/ahmadreza-sajadi-10140-unsplash.jpg -Freshly Showered,4963,8,Projects are hard, make your life easier by feeling freshly showered.,https://i.ibb.co/0D9th8Z/michael-podger-252489-unsplash.jpg +Freshly Showered,4963,8,"Projects are hard, make your life easier by feeling freshly showered.",https://i.ibb.co/0D9th8Z/michael-podger-252489-unsplash.jpg Teleport Into Bed,3216,6,Open incase of emergency.,https://i.ibb.co/nk5FkwV/diego-ph-493991-unsplash.jpg -Ada Starter Kit,2397,5,The ADA starter kit features the things that hardworking Adies need, relaxation, reflection, and a calm mind.,https://i.ibb.co/ssgbQqH/ishan-seefromthesky-277746-unsplash.jpg +Ada Starter Kit,2397,5,"The ADA starter kit features the things that hardworking Adies need, relaxation, reflection, and a calm mind.",https://i.ibb.co/ssgbQqH/ishan-seefromthesky-277746-unsplash.jpg Ada Best Seller Pack,4517,8,Take some time to yourself. Work hard and play hard.,https://i.ibb.co/XCc7kxc/recal-media-83365-unsplash.jpg Cup of Rainbows,4282,4,Find something magical in your day and in yourself.,https://i.ibb.co/LprTnc8/alistair-macrobert-633034-unsplash.jpg Puppy play Pack,2803,8,Unwind with Puppy Time. You'll thank us later.,https://i.ibb.co/M1xGDJ0/bharathi-kannan-1260953-unsplash.jpg @@ -18,4 +18,5 @@ Giggle Party,3250,3,Sometimes unwinding just means giggling...HARD.,https://i.ib Bestfriend Time,2332,11,Self care is important so take some time to catch up!,https://i.ibb.co/Jd4nkWQ/ian-schneider-64307-unsplash.jpg Juicy Secret,1170,5,The Juciest Secret to put some pep in your step.,https://i.ibb.co/PN6tfQY/marcela-rogante-432403-unsplash.jpg Inside Joke Moment,4141,4,Take a pause and lighten the mood with an inside joke moment,https://i.ibb.co/7WNs7Y3/carlos-pimentel-1206339-unsplash.jpg -Bondfire Time,2976,4,Sometimes all you need is a BONDfire to reconnect with friends.,https://i.ibb.co/JR78YWq/mike-erskine-144525-unsplash.jpg \ No newline at end of file +Bondfire Time,2976,4,Sometimes all you need is a BONDfire to reconnect with friends.,https://i.ibb.co/JR78YWq/mike-erskine-144525-unsplash.jpg +"Hugs from Elle's Mom",1253, 752,"With over five decades of experience, Elle's Mom is an expert in filling her hugs with love.",https://lwm-a2.azureedge.net/uploads/2018/08/Jen-HatmakerFeat1.jpg \ No newline at end of file