From eddf28e44ec4ae59914e9dc07dea5ec4cd7aee69 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Wed, 18 Apr 2018 11:35:57 -0700 Subject: [PATCH 001/252] Created rails files. --- .gitignore | 19 + Gemfile | 72 ++ Gemfile.lock | 236 +++++ Rakefile | 6 + app/assets/config/manifest.js | 3 + app/assets/images/.keep | 0 app/assets/javascripts/application.js | 20 + app/assets/javascripts/cable.js | 13 + app/assets/javascripts/channels/.keep | 0 app/assets/stylesheets/_settings.scss | 869 ++++++++++++++++++ app/assets/stylesheets/application.css | 19 + app/assets/stylesheets/browserslist | 4 + .../stylesheets/foundation_and_overrides.scss | 61 ++ app/channels/application_cable/channel.rb | 4 + app/channels/application_cable/connection.rb | 4 + app/controllers/application_controller.rb | 3 + app/controllers/concerns/.keep | 0 app/helpers/application_helper.rb | 2 + app/jobs/application_job.rb | 2 + app/mailers/application_mailer.rb | 4 + app/models/application_record.rb | 3 + app/models/concerns/.keep | 0 app/views/layouts/application.html.erb | 19 + 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 | 38 + bin/spring | 17 + bin/update | 29 + bin/yarn | 11 + config.ru | 5 + config/application.rb | 25 + config/boot.rb | 3 + config/cable.yml | 10 + config/database.yml | 85 ++ config/environment.rb | 5 + config/environments/development.rb | 54 ++ config/environments/production.rb | 91 ++ config/environments/test.rb | 42 + .../application_controller_renderer.rb | 8 + config/initializers/assets.rb | 14 + config/initializers/backtrace_silencers.rb | 7 + config/initializers/cookies_serializer.rb | 5 + .../initializers/filter_parameter_logging.rb | 4 + config/initializers/inflections.rb | 16 + config/initializers/mime_types.rb | 4 + config/initializers/wrap_parameters.rb | 14 + config/locales/en.yml | 33 + config/puma.rb | 56 ++ config/routes.rb | 3 + config/secrets.yml | 32 + config/spring.rb | 6 + 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 + 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 | 26 + tmp/.keep | 0 vendor/.keep | 0 78 files changed, 2259 insertions(+) create mode 100644 .gitignore create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 Rakefile create mode 100644 app/assets/config/manifest.js create mode 100644 app/assets/images/.keep create mode 100644 app/assets/javascripts/application.js create mode 100644 app/assets/javascripts/cable.js create mode 100644 app/assets/javascripts/channels/.keep create mode 100644 app/assets/stylesheets/_settings.scss create mode 100644 app/assets/stylesheets/application.css create mode 100644 app/assets/stylesheets/browserslist create mode 100644 app/assets/stylesheets/foundation_and_overrides.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/database.yml create mode 100644 config/environment.rb create mode 100644 config/environments/development.rb create mode 100644 config/environments/production.rb create mode 100644 config/environments/test.rb create mode 100644 config/initializers/application_controller_renderer.rb create mode 100644 config/initializers/assets.rb create mode 100644 config/initializers/backtrace_silencers.rb create mode 100644 config/initializers/cookies_serializer.rb create mode 100644 config/initializers/filter_parameter_logging.rb create mode 100644 config/initializers/inflections.rb create mode 100644 config/initializers/mime_types.rb create mode 100644 config/initializers/wrap_parameters.rb create mode 100644 config/locales/en.yml create mode 100644 config/puma.rb create mode 100644 config/routes.rb create mode 100644 config/secrets.yml create mode 100644 config/spring.rb create mode 100644 db/seeds.rb create mode 100644 lib/assets/.keep create mode 100644 lib/tasks/.keep create mode 100644 log/.keep create mode 100644 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 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..82701fedc8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# 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 + +/node_modules +/yarn-error.log + +.byebug_history diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000000..8490d0efb5 --- /dev/null +++ b/Gemfile @@ -0,0 +1,72 @@ +source 'https://rubygems.org' + +git_source(:github) do |repo_name| + repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") + "https://github.com/#{repo_name}.git" +end + + +# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' +gem 'rails', '~> 5.1.6' +# Use postgresql as the database for Active Record +gem 'pg', '>= 0.18', '< 2.0' +# Use Puma as the app server +gem 'puma', '~> 3.7' +# Use SCSS for stylesheets +gem 'sass-rails', '~> 5.0' +# Use Uglifier as compressor for JavaScript assets +gem 'uglifier', '>= 1.3.0' +# See https://github.com/rails/execjs#readme for more supported runtimes +# gem 'therubyracer', platforms: :ruby + +# Use CoffeeScript for .coffee assets and views +# gem 'coffee-rails', '~> 4.2' +# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks +gem '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 Capistrano for deployment +# gem 'capistrano-rails', group: :development + +group :development, :test do + # Call 'byebug' anywhere in the code to stop execution and get a debugger console + gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] + # Adds support for Capybara system testing and selenium driver + gem 'capybara', '~> 2.13' + gem 'selenium-webdriver' +end + +group :development do + # Access an IRB console on exception pages or by using <%= console %> anywhere in the code. + gem 'web-console', '>= 3.3.0' + gem 'listen', '>= 3.0.5', '< 3.2' + # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring + gem 'spring' + gem 'spring-watcher-listen', '~> 2.0.0' +end + +# Windows does not include zoneinfo files, so bundle the tzinfo-data gem +gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] + +gem 'jquery-turbolinks' +gem 'jquery-rails' +gem 'foundation-rails' +gem 'normalize-rails' +group :development, :test do + gem 'pry-rails' +end + +group :development do + gem 'better_errors' + gem 'binding_of_caller' +end + +group :test do + gem 'minitest-rails' + gem 'minitest-reporters' +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000000..d528acb17a --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,236 @@ +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.1.6) + actionpack (= 5.1.6) + nio4r (~> 2.0) + websocket-driver (~> 0.6.1) + actionmailer (5.1.6) + actionpack (= 5.1.6) + actionview (= 5.1.6) + activejob (= 5.1.6) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.1.6) + actionview (= 5.1.6) + activesupport (= 5.1.6) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.1.6) + activesupport (= 5.1.6) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.1.6) + activesupport (= 5.1.6) + globalid (>= 0.3.6) + activemodel (5.1.6) + activesupport (= 5.1.6) + activerecord (5.1.6) + activemodel (= 5.1.6) + activesupport (= 5.1.6) + arel (~> 8.0) + activesupport (5.1.6) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + ansi (1.5.0) + arel (8.0.0) + babel-source (5.8.35) + babel-transpiler (0.7.0) + babel-source (>= 4.0, < 6) + execjs (~> 2.0) + better_errors (2.4.0) + coderay (>= 1.0.0) + erubi (>= 1.0.0) + rack (>= 0.9.0) + bindex (0.5.0) + binding_of_caller (0.8.0) + debug_inspector (>= 0.0.1) + builder (3.2.3) + byebug (10.0.2) + capybara (2.18.0) + addressable + mini_mime (>= 0.1.3) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (>= 2.0, < 4.0) + childprocess (0.9.0) + ffi (~> 1.0, >= 1.0.11) + coderay (1.1.2) + concurrent-ruby (1.0.5) + crass (1.0.4) + debug_inspector (0.0.3) + erubi (1.7.1) + execjs (2.7.0) + ffi (1.9.23) + foundation-rails (6.4.3.0) + railties (>= 3.1.0) + sass (>= 3.3.0, < 3.5) + sprockets-es6 (>= 0.9.0) + globalid (0.4.1) + activesupport (>= 4.2.0) + i18n (1.0.1) + concurrent-ruby (~> 1.0) + jbuilder (2.7.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.2) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.0) + mini_mime (>= 0.1.1) + method_source (0.9.0) + mini_mime (1.0.0) + mini_portile2 (2.3.0) + minitest (5.11.3) + minitest-rails (3.0.0) + minitest (~> 5.8) + railties (~> 5.0) + minitest-reporters (1.2.0) + ansi + builder + minitest (>= 5.0) + ruby-progressbar + multi_json (1.13.1) + nio4r (2.3.0) + nokogiri (1.8.2) + mini_portile2 (~> 2.3.0) + normalize-rails (4.1.1) + pg (1.0.0) + pry (0.11.3) + coderay (~> 1.1.0) + method_source (~> 0.9.0) + pry-rails (0.3.6) + pry (>= 0.10.4) + public_suffix (3.0.2) + puma (3.11.4) + rack (2.0.4) + rack-test (1.0.0) + rack (>= 1.0, < 3) + rails (5.1.6) + actioncable (= 5.1.6) + actionmailer (= 5.1.6) + actionpack (= 5.1.6) + actionview (= 5.1.6) + activejob (= 5.1.6) + activemodel (= 5.1.6) + activerecord (= 5.1.6) + activesupport (= 5.1.6) + bundler (>= 1.3.0) + railties (= 5.1.6) + 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.1.6) + actionpack (= 5.1.6) + activesupport (= 5.1.6) + method_source + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rake (12.3.1) + rb-fsevent (0.10.3) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) + ruby-progressbar (1.9.0) + ruby_dep (1.5.0) + rubyzip (1.2.1) + sass (3.4.25) + sass-rails (5.0.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.11.0) + childprocess (~> 0.5) + rubyzip (~> 1.2) + spring (2.0.2) + activesupport (>= 4.2) + spring-watcher-listen (2.0.1) + listen (>= 2.7, < 4.0) + spring (>= 1.2, < 3.0) + sprockets (3.7.1) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-es6 (0.9.2) + babel-source (>= 5.8.11) + babel-transpiler + sprockets (>= 3.0.0) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + thor (0.20.0) + thread_safe (0.3.6) + tilt (2.0.8) + turbolinks (5.1.1) + turbolinks-source (~> 5.1) + turbolinks-source (5.1.0) + tzinfo (1.2.5) + thread_safe (~> 0.1) + uglifier (4.1.9) + execjs (>= 0.3.0, < 3) + web-console (3.6.0) + actionview (>= 5.0) + activemodel (>= 5.0) + bindex (>= 0.4.0) + railties (>= 5.0) + websocket-driver (0.6.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.3) + xpath (3.0.0) + nokogiri (~> 1.8) + +PLATFORMS + ruby + +DEPENDENCIES + better_errors + binding_of_caller + byebug + capybara (~> 2.13) + foundation-rails + jbuilder (~> 2.5) + jquery-rails + jquery-turbolinks + listen (>= 3.0.5, < 3.2) + minitest-rails + minitest-reporters + normalize-rails + pg (>= 0.18, < 2.0) + pry-rails + puma (~> 3.7) + rails (~> 5.1.6) + 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) + +BUNDLED WITH + 1.16.1 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..f04673be81 --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,20 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's +// vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. JavaScript code in this file should be added after the last require_* statement. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +//= require jquery + +// +//= require rails-ujs +//= require foundation +//= require turbolinks +//= require_tree . + +$(function(){ $(document).foundation(); }); 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/_settings.scss b/app/assets/stylesheets/_settings.scss new file mode 100644 index 0000000000..26f74f9494 --- /dev/null +++ b/app/assets/stylesheets/_settings.scss @@ -0,0 +1,869 @@ +// Foundation for Sites Settings +// ----------------------------- +// +// Table of Contents: +// +// 1. Global +// 2. Breakpoints +// 3. The Grid +// 4. Base Typography +// 5. Typography Helpers +// 6. Abide +// 7. Accordion +// 8. Accordion Menu +// 9. Badge +// 10. Breadcrumbs +// 11. Button +// 12. Button Group +// 13. Callout +// 14. Card +// 15. Close Button +// 16. Drilldown +// 17. Dropdown +// 18. Dropdown Menu +// 19. Flexbox Utilities +// 20. Forms +// 21. Label +// 22. Media Object +// 23. Menu +// 24. Meter +// 25. Off-canvas +// 26. Orbit +// 27. Pagination +// 28. Progress Bar +// 29. Prototype Arrow +// 30. Prototype Border-Box +// 31. Prototype Border-None +// 32. Prototype Bordered +// 33. Prototype Display +// 34. Prototype Font-Styling +// 35. Prototype List-Style-Type +// 36. Prototype Overflow +// 37. Prototype Position +// 38. Prototype Rounded +// 39. Prototype Separator +// 40. Prototype Shadow +// 41. Prototype Sizing +// 42. Prototype Spacing +// 43. Prototype Text-Decoration +// 44. Prototype Text-Transformation +// 45. Prototype Text-Utilities +// 46. Responsive Embed +// 47. Reveal +// 48. Slider +// 49. Switch +// 50. Table +// 51. Tabs +// 52. Thumbnail +// 53. Title Bar +// 54. Tooltip +// 55. Top Bar +// 56. Xy Grid + +@import 'util/util'; + +// 1. Global +// --------- + +$global-font-size: 100%; +$global-width: rem-calc(1200); +$global-lineheight: 1.5; +$foundation-palette: ( + primary: #1779ba, + secondary: #767676, + success: #3adb76, + warning: #ffae00, + alert: #cc4b37, +); +$light-gray: #e6e6e6; +$medium-gray: #cacaca; +$dark-gray: #8a8a8a; +$black: #0a0a0a; +$white: #fefefe; +$body-background: $white; +$body-font-color: $black; +$body-font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; +$body-antialiased: true; +$global-margin: 1rem; +$global-padding: 1rem; +$global-position: 1rem; +$global-weight-normal: normal; +$global-weight-bold: bold; +$global-radius: 0; +$global-menu-padding: 0.7rem 1rem; +$global-menu-nested-margin: 1rem; +$global-text-direction: ltr; +$global-flexbox: true; +$global-prototype-breakpoints: false; +$global-button-cursor: auto; +$global-color-pick-contrast-tolerance: 0; +$print-transparent-backgrounds: true; + +@include add-foundation-colors; + +// 2. Breakpoints +// -------------- + +$breakpoints: ( + small: 0, + medium: 640px, + large: 1024px, + xlarge: 1200px, + xxlarge: 1440px, +); +$print-breakpoint: large; +$breakpoint-classes: (small medium large); + +// 3. The Grid +// ----------- + +$grid-row-width: $global-width; +$grid-column-count: 12; +$grid-column-gutter: ( + small: 20px, + medium: 30px, +); +$grid-column-align-edge: true; +$grid-column-alias: 'columns'; +$block-grid-max: 8; + +// 4. Base Typography +// ------------------ + +$header-font-family: $body-font-family; +$header-font-weight: $global-weight-normal; +$header-font-style: normal; +$font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace; +$header-color: inherit; +$header-lineheight: 1.4; +$header-margin-bottom: 0.5rem; +$header-styles: ( + small: ( + 'h1': ('font-size': 24), + 'h2': ('font-size': 20), + 'h3': ('font-size': 19), + 'h4': ('font-size': 18), + 'h5': ('font-size': 17), + 'h6': ('font-size': 16), + ), + medium: ( + 'h1': ('font-size': 48), + 'h2': ('font-size': 40), + 'h3': ('font-size': 31), + 'h4': ('font-size': 25), + 'h5': ('font-size': 20), + 'h6': ('font-size': 16), + ), +); +$header-text-rendering: optimizeLegibility; +$small-font-size: 80%; +$header-small-font-color: $medium-gray; +$paragraph-lineheight: 1.6; +$paragraph-margin-bottom: 1rem; +$paragraph-text-rendering: optimizeLegibility; +$code-color: $black; +$code-font-family: $font-family-monospace; +$code-font-weight: $global-weight-normal; +$code-background: $light-gray; +$code-border: 1px solid $medium-gray; +$code-padding: rem-calc(2 5 1); +$anchor-color: $primary-color; +$anchor-color-hover: scale-color($anchor-color, $lightness: -14%); +$anchor-text-decoration: none; +$anchor-text-decoration-hover: none; +$hr-width: $global-width; +$hr-border: 1px solid $medium-gray; +$hr-margin: rem-calc(20) auto; +$list-lineheight: $paragraph-lineheight; +$list-margin-bottom: $paragraph-margin-bottom; +$list-style-type: disc; +$list-style-position: outside; +$list-side-margin: 1.25rem; +$list-nested-side-margin: 1.25rem; +$defnlist-margin-bottom: 1rem; +$defnlist-term-weight: $global-weight-bold; +$defnlist-term-margin-bottom: 0.3rem; +$blockquote-color: $dark-gray; +$blockquote-padding: rem-calc(9 20 0 19); +$blockquote-border: 1px solid $medium-gray; +$cite-font-size: rem-calc(13); +$cite-color: $dark-gray; +$cite-pseudo-content: '\2014 \0020'; +$keystroke-font: $font-family-monospace; +$keystroke-color: $black; +$keystroke-background: $light-gray; +$keystroke-padding: rem-calc(2 4 0); +$keystroke-radius: $global-radius; +$abbr-underline: 1px dotted $black; + +// 5. Typography Helpers +// --------------------- + +$lead-font-size: $global-font-size * 1.25; +$lead-lineheight: 1.6; +$subheader-lineheight: 1.4; +$subheader-color: $dark-gray; +$subheader-font-weight: $global-weight-normal; +$subheader-margin-top: 0.2rem; +$subheader-margin-bottom: 0.5rem; +$stat-font-size: 2.5rem; + +// 6. Abide +// -------- + +$abide-inputs: true; +$abide-labels: true; +$input-background-invalid: get-color(alert); +$form-label-color-invalid: get-color(alert); +$input-error-color: get-color(alert); +$input-error-font-size: rem-calc(12); +$input-error-font-weight: $global-weight-bold; + +// 7. Accordion +// ------------ + +$accordion-background: $white; +$accordion-plusminus: true; +$accordion-title-font-size: rem-calc(12); +$accordion-item-color: $primary-color; +$accordion-item-background-hover: $light-gray; +$accordion-item-padding: 1.25rem 1rem; +$accordion-content-background: $white; +$accordion-content-border: 1px solid $light-gray; +$accordion-content-color: $body-font-color; +$accordion-content-padding: 1rem; + +// 8. Accordion Menu +// ----------------- + +$accordionmenu-padding: $global-menu-padding; +$accordionmenu-nested-margin: $global-menu-nested-margin; +$accordionmenu-submenu-padding: $accordionmenu-padding; +$accordionmenu-arrows: true; +$accordionmenu-arrow-color: $primary-color; +$accordionmenu-item-background: null; +$accordionmenu-border: null; +$accordionmenu-submenu-toggle-background: null; +$accordion-submenu-toggle-border: $accordionmenu-border; +$accordionmenu-submenu-toggle-width: 40px; +$accordionmenu-submenu-toggle-height: $accordionmenu-submenu-toggle-width; +$accordionmenu-arrow-size: 6px; + +// 9. Badge +// -------- + +$badge-background: $primary-color; +$badge-color: $white; +$badge-color-alt: $black; +$badge-palette: $foundation-palette; +$badge-padding: 0.3em; +$badge-minwidth: 2.1em; +$badge-font-size: 0.6rem; + +// 10. Breadcrumbs +// --------------- + +$breadcrumbs-margin: 0 0 $global-margin 0; +$breadcrumbs-item-font-size: rem-calc(11); +$breadcrumbs-item-color: $primary-color; +$breadcrumbs-item-color-current: $black; +$breadcrumbs-item-color-disabled: $medium-gray; +$breadcrumbs-item-margin: 0.75rem; +$breadcrumbs-item-uppercase: true; +$breadcrumbs-item-separator: true; +$breadcrumbs-item-separator-item: '/'; +$breadcrumbs-item-separator-item-rtl: '\\'; +$breadcrumbs-item-separator-color: $medium-gray; + +// 11. Button +// ---------- + +$button-font-family: inherit; +$button-padding: 0.85em 1em; +$button-margin: 0 0 $global-margin 0; +$button-fill: solid; +$button-background: $primary-color; +$button-background-hover: scale-color($button-background, $lightness: -15%); +$button-color: $white; +$button-color-alt: $black; +$button-radius: $global-radius; +$button-hollow-border-width: 1px; +$button-sizes: ( + tiny: 0.6rem, + small: 0.75rem, + default: 0.9rem, + large: 1.25rem, +); +$button-palette: $foundation-palette; +$button-opacity-disabled: 0.25; +$button-background-hover-lightness: -20%; +$button-hollow-hover-lightness: -50%; +$button-transition: background-color 0.25s ease-out, color 0.25s ease-out; + +// 12. Button Group +// ---------------- + +$buttongroup-margin: 1rem; +$buttongroup-spacing: 1px; +$buttongroup-child-selector: '.button'; +$buttongroup-expand-max: 6; +$buttongroup-radius-on-each: true; + +// 13. Callout +// ----------- + +$callout-background: $white; +$callout-background-fade: 85%; +$callout-border: 1px solid rgba($black, 0.25); +$callout-margin: 0 0 1rem 0; +$callout-padding: 1rem; +$callout-font-color: $body-font-color; +$callout-font-color-alt: $body-background; +$callout-radius: $global-radius; +$callout-link-tint: 30%; + +// 14. Card +// -------- + +$card-background: $white; +$card-font-color: $body-font-color; +$card-divider-background: $light-gray; +$card-border: 1px solid $light-gray; +$card-shadow: none; +$card-border-radius: $global-radius; +$card-padding: $global-padding; +$card-margin-bottom: $global-margin; + +// 15. Close Button +// ---------------- + +$closebutton-position: right top; +$closebutton-offset-horizontal: ( + small: 0.66rem, + medium: 1rem, +); +$closebutton-offset-vertical: ( + small: 0.33em, + medium: 0.5rem, +); +$closebutton-size: ( + small: 1.5em, + medium: 2em, +); +$closebutton-lineheight: 1; +$closebutton-color: $dark-gray; +$closebutton-color-hover: $black; + +// 16. Drilldown +// ------------- + +$drilldown-transition: transform 0.15s linear; +$drilldown-arrows: true; +$drilldown-padding: $global-menu-padding; +$drilldown-nested-margin: 0; +$drilldown-background: $white; +$drilldown-submenu-padding: $drilldown-padding; +$drilldown-submenu-background: $white; +$drilldown-arrow-color: $primary-color; +$drilldown-arrow-size: 6px; + +// 17. Dropdown +// ------------ + +$dropdown-padding: 1rem; +$dropdown-background: $body-background; +$dropdown-border: 1px solid $medium-gray; +$dropdown-font-size: 1rem; +$dropdown-width: 300px; +$dropdown-radius: $global-radius; +$dropdown-sizes: ( + tiny: 100px, + small: 200px, + large: 400px, +); + +// 18. Dropdown Menu +// ----------------- + +$dropdownmenu-arrows: true; +$dropdownmenu-arrow-color: $anchor-color; +$dropdownmenu-arrow-size: 6px; +$dropdownmenu-arrow-padding: 1.5rem; +$dropdownmenu-min-width: 200px; +$dropdownmenu-background: $white; +$dropdownmenu-submenu-background: $dropdownmenu-background; +$dropdownmenu-padding: $global-menu-padding; +$dropdownmenu-nested-margin: 0; +$dropdownmenu-submenu-padding: $dropdownmenu-padding; +$dropdownmenu-border: 1px solid $medium-gray; +$dropdown-menu-item-color-active: get-color(primary); +$dropdown-menu-item-background-active: transparent; + +// 19. Flexbox Utilities +// --------------------- + +$flex-source-ordering-count: 6; +$flexbox-responsive-breakpoints: true; + +// 20. Forms +// --------- + +$fieldset-border: 1px solid $medium-gray; +$fieldset-padding: rem-calc(20); +$fieldset-margin: rem-calc(18 0); +$legend-padding: rem-calc(0 3); +$form-spacing: rem-calc(16); +$helptext-color: $black; +$helptext-font-size: rem-calc(13); +$helptext-font-style: italic; +$input-prefix-color: $black; +$input-prefix-background: $light-gray; +$input-prefix-border: 1px solid $medium-gray; +$input-prefix-padding: 1rem; +$form-label-color: $black; +$form-label-font-size: rem-calc(14); +$form-label-font-weight: $global-weight-normal; +$form-label-line-height: 1.8; +$select-background: $white; +$select-triangle-color: $dark-gray; +$select-radius: $global-radius; +$input-color: $black; +$input-placeholder-color: $medium-gray; +$input-font-family: inherit; +$input-font-size: rem-calc(16); +$input-font-weight: $global-weight-normal; +$input-line-height: $global-lineheight; +$input-background: $white; +$input-background-focus: $white; +$input-background-disabled: $light-gray; +$input-border: 1px solid $medium-gray; +$input-border-focus: 1px solid $dark-gray; +$input-padding: $form-spacing / 2; +$input-shadow: inset 0 1px 2px rgba($black, 0.1); +$input-shadow-focus: 0 0 5px $medium-gray; +$input-cursor-disabled: not-allowed; +$input-transition: box-shadow 0.5s, border-color 0.25s ease-in-out; +$input-number-spinners: true; +$input-radius: $global-radius; +$form-button-radius: $global-radius; + +// 21. Label +// --------- + +$label-background: $primary-color; +$label-color: $white; +$label-color-alt: $black; +$label-palette: $foundation-palette; +$label-font-size: 0.8rem; +$label-padding: 0.33333rem 0.5rem; +$label-radius: $global-radius; + +// 22. Media Object +// ---------------- + +$mediaobject-margin-bottom: $global-margin; +$mediaobject-section-padding: $global-padding; +$mediaobject-image-width-stacked: 100%; + +// 23. Menu +// -------- + +$menu-margin: 0; +$menu-nested-margin: $global-menu-nested-margin; +$menu-items-padding: $global-menu-padding; +$menu-simple-margin: 1rem; +$menu-item-color-active: $white; +$menu-item-background-active: get-color(primary); +$menu-icon-spacing: 0.25rem; +$menu-item-background-hover: $light-gray; +$menu-state-back-compat: true; +$menu-centered-back-compat: true; +$menu-icons-back-compat: true; + +// 24. Meter +// --------- + +$meter-height: 1rem; +$meter-radius: $global-radius; +$meter-background: $medium-gray; +$meter-fill-good: $success-color; +$meter-fill-medium: $warning-color; +$meter-fill-bad: $alert-color; + +// 25. Off-canvas +// -------------- + +$offcanvas-sizes: ( + small: 250px, +); +$offcanvas-vertical-sizes: ( + small: 250px, +); +$offcanvas-background: $light-gray; +$offcanvas-shadow: 0 0 10px rgba($black, 0.7); +$offcanvas-inner-shadow-size: 20px; +$offcanvas-inner-shadow-color: rgba($black, 0.25); +$offcanvas-overlay-zindex: 11; +$offcanvas-push-zindex: 12; +$offcanvas-overlap-zindex: 13; +$offcanvas-reveal-zindex: 12; +$offcanvas-transition-length: 0.5s; +$offcanvas-transition-timing: ease; +$offcanvas-fixed-reveal: true; +$offcanvas-exit-background: rgba($white, 0.25); +$maincontent-class: 'off-canvas-content'; + +// 26. Orbit +// --------- + +$orbit-bullet-background: $medium-gray; +$orbit-bullet-background-active: $dark-gray; +$orbit-bullet-diameter: 1.2rem; +$orbit-bullet-margin: 0.1rem; +$orbit-bullet-margin-top: 0.8rem; +$orbit-bullet-margin-bottom: 0.8rem; +$orbit-caption-background: rgba($black, 0.5); +$orbit-caption-padding: 1rem; +$orbit-control-background-hover: rgba($black, 0.5); +$orbit-control-padding: 1rem; +$orbit-control-zindex: 10; + +// 27. Pagination +// -------------- + +$pagination-font-size: rem-calc(14); +$pagination-margin-bottom: $global-margin; +$pagination-item-color: $black; +$pagination-item-padding: rem-calc(3 10); +$pagination-item-spacing: rem-calc(1); +$pagination-radius: $global-radius; +$pagination-item-background-hover: $light-gray; +$pagination-item-background-current: $primary-color; +$pagination-item-color-current: $white; +$pagination-item-color-disabled: $medium-gray; +$pagination-ellipsis-color: $black; +$pagination-mobile-items: false; +$pagination-mobile-current-item: false; +$pagination-arrows: true; + +// 28. Progress Bar +// ---------------- + +$progress-height: 1rem; +$progress-background: $medium-gray; +$progress-margin-bottom: $global-margin; +$progress-meter-background: $primary-color; +$progress-radius: $global-radius; + +// 29. Prototype Arrow +// ------------------- + +$prototype-arrow-directions: ( + down, + up, + right, + left +); +$prototype-arrow-size: 0.4375rem; +$prototype-arrow-color: $black; + +// 30. Prototype Border-Box +// ------------------------ + +$prototype-border-box-breakpoints: $global-prototype-breakpoints; + +// 31. Prototype Border-None +// ------------------------- + +$prototype-border-none-breakpoints: $global-prototype-breakpoints; + +// 32. Prototype Bordered +// ---------------------- + +$prototype-bordered-breakpoints: $global-prototype-breakpoints; +$prototype-border-width: rem-calc(1); +$prototype-border-type: solid; +$prototype-border-color: $medium-gray; + +// 33. Prototype Display +// --------------------- + +$prototype-display-breakpoints: $global-prototype-breakpoints; +$prototype-display: ( + inline, + inline-block, + block, + table, + table-cell +); + +// 34. Prototype Font-Styling +// -------------------------- + +$prototype-font-breakpoints: $global-prototype-breakpoints; +$prototype-wide-letter-spacing: rem-calc(4); +$prototype-font-normal: $global-weight-normal; +$prototype-font-bold: $global-weight-bold; + +// 35. Prototype List-Style-Type +// ----------------------------- + +$prototype-list-breakpoints: $global-prototype-breakpoints; +$prototype-style-type-unordered: ( + disc, + circle, + square +); +$prototype-style-type-ordered: ( + decimal, + lower-alpha, + lower-latin, + lower-roman, + upper-alpha, + upper-latin, + upper-roman +); + +// 36. Prototype Overflow +// ---------------------- + +$prototype-overflow-breakpoints: $global-prototype-breakpoints; +$prototype-overflow: ( + visible, + hidden, + scroll +); + +// 37. Prototype Position +// ---------------------- + +$prototype-position-breakpoints: $global-prototype-breakpoints; +$prototype-position: ( + static, + relative, + absolute, + fixed +); +$prototype-position-z-index: 975; + +// 38. Prototype Rounded +// --------------------- + +$prototype-rounded-breakpoints: $global-prototype-breakpoints; +$prototype-border-radius: rem-calc(3); + +// 39. Prototype Separator +// ----------------------- + +$prototype-separator-breakpoints: $global-prototype-breakpoints; +$prototype-separator-align: center; +$prototype-separator-height: rem-calc(2); +$prototype-separator-width: 3rem; +$prototype-separator-background: $primary-color; +$prototype-separator-margin-top: $global-margin; + +// 40. Prototype Shadow +// -------------------- + +$prototype-shadow-breakpoints: $global-prototype-breakpoints; +$prototype-box-shadow: 0 2px 5px 0 rgba(0,0,0,.16), + 0 2px 10px 0 rgba(0,0,0,.12); + +// 41. Prototype Sizing +// -------------------- + +$prototype-sizing-breakpoints: $global-prototype-breakpoints; +$prototype-sizing: ( + width, + height +); +$prototype-sizes: ( + 25: 25%, + 50: 50%, + 75: 75%, + 100: 100% +); + +// 42. Prototype Spacing +// --------------------- + +$prototype-spacing-breakpoints: $global-prototype-breakpoints; +$prototype-spacers-count: 3; + +// 43. Prototype Text-Decoration +// ----------------------------- + +$prototype-decoration-breakpoints: $global-prototype-breakpoints; +$prototype-text-decoration: ( + overline, + underline, + line-through, +); + +// 44. Prototype Text-Transformation +// --------------------------------- + +$prototype-transformation-breakpoints: $global-prototype-breakpoints; +$prototype-text-transformation: ( + lowercase, + uppercase, + capitalize +); + +// 45. Prototype Text-Utilities +// ---------------------------- + +$prototype-utilities-breakpoints: $global-prototype-breakpoints; +$prototype-text-overflow: ellipsis; + +// 46. Responsive Embed +// -------------------- + +$responsive-embed-margin-bottom: rem-calc(16); +$responsive-embed-ratios: ( + default: 4 by 3, + widescreen: 16 by 9, +); + +// 47. Reveal +// ---------- + +$reveal-background: $white; +$reveal-width: 600px; +$reveal-max-width: $global-width; +$reveal-padding: $global-padding; +$reveal-border: 1px solid $medium-gray; +$reveal-radius: $global-radius; +$reveal-zindex: 1005; +$reveal-overlay-background: rgba($black, 0.45); + +// 48. Slider +// ---------- + +$slider-width-vertical: 0.5rem; +$slider-transition: all 0.2s ease-in-out; +$slider-height: 0.5rem; +$slider-background: $light-gray; +$slider-fill-background: $medium-gray; +$slider-handle-height: 1.4rem; +$slider-handle-width: 1.4rem; +$slider-handle-background: $primary-color; +$slider-opacity-disabled: 0.25; +$slider-radius: $global-radius; + +// 49. Switch +// ---------- + +$switch-background: $medium-gray; +$switch-background-active: $primary-color; +$switch-height: 2rem; +$switch-height-tiny: 1.5rem; +$switch-height-small: 1.75rem; +$switch-height-large: 2.5rem; +$switch-radius: $global-radius; +$switch-margin: $global-margin; +$switch-paddle-background: $white; +$switch-paddle-offset: 0.25rem; +$switch-paddle-radius: $global-radius; +$switch-paddle-transition: all 0.25s ease-out; + +// 50. Table +// --------- + +$table-background: $white; +$table-color-scale: 5%; +$table-border: 1px solid smart-scale($table-background, $table-color-scale); +$table-padding: rem-calc(8 10 10); +$table-hover-scale: 2%; +$table-row-hover: darken($table-background, $table-hover-scale); +$table-row-stripe-hover: darken($table-background, $table-color-scale + $table-hover-scale); +$table-is-striped: true; +$table-striped-background: smart-scale($table-background, $table-color-scale); +$table-stripe: even; +$table-head-background: smart-scale($table-background, $table-color-scale / 2); +$table-head-row-hover: darken($table-head-background, $table-hover-scale); +$table-foot-background: smart-scale($table-background, $table-color-scale); +$table-foot-row-hover: darken($table-foot-background, $table-hover-scale); +$table-head-font-color: $body-font-color; +$table-foot-font-color: $body-font-color; +$show-header-for-stacked: false; +$table-stack-breakpoint: medium; + +// 51. Tabs +// -------- + +$tab-margin: 0; +$tab-background: $white; +$tab-color: $primary-color; +$tab-background-active: $light-gray; +$tab-active-color: $primary-color; +$tab-item-font-size: rem-calc(12); +$tab-item-background-hover: $white; +$tab-item-padding: 1.25rem 1.5rem; +$tab-expand-max: 6; +$tab-content-background: $white; +$tab-content-border: $light-gray; +$tab-content-color: $body-font-color; +$tab-content-padding: 1rem; + +// 52. Thumbnail +// ------------- + +$thumbnail-border: solid 4px $white; +$thumbnail-margin-bottom: $global-margin; +$thumbnail-shadow: 0 0 0 1px rgba($black, 0.2); +$thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5); +$thumbnail-transition: box-shadow 200ms ease-out; +$thumbnail-radius: $global-radius; + +// 53. Title Bar +// ------------- + +$titlebar-background: $black; +$titlebar-color: $white; +$titlebar-padding: 0.5rem; +$titlebar-text-font-weight: bold; +$titlebar-icon-color: $white; +$titlebar-icon-color-hover: $medium-gray; +$titlebar-icon-spacing: 0.25rem; + +// 54. Tooltip +// ----------- + +$has-tip-cursor: help; +$has-tip-font-weight: $global-weight-bold; +$has-tip-border-bottom: dotted 1px $dark-gray; +$tooltip-background-color: $black; +$tooltip-color: $white; +$tooltip-padding: 0.75rem; +$tooltip-max-width: 10rem; +$tooltip-font-size: $small-font-size; +$tooltip-pip-width: 0.75rem; +$tooltip-pip-height: $tooltip-pip-width * 0.866; +$tooltip-radius: $global-radius; + +// 55. Top Bar +// ----------- + +$topbar-padding: 0.5rem; +$topbar-background: $light-gray; +$topbar-submenu-background: $topbar-background; +$topbar-title-spacing: 0.5rem 1rem 0.5rem 0; +$topbar-input-width: 200px; +$topbar-unstack-breakpoint: medium; + +// 56. Xy Grid +// ----------- + +$xy-grid: true; +$grid-container: $global-width; +$grid-columns: 12; +$grid-margin-gutters: ( + small: 20px, + medium: 30px +); +$grid-padding-gutters: $grid-margin-gutters; +$grid-container-padding: $grid-padding-gutters; +$grid-container-max: $global-width; +$xy-block-grid-max: 8; + diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css new file mode 100644 index 0000000000..3a38418320 --- /dev/null +++ b/app/assets/stylesheets/application.css @@ -0,0 +1,19 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's + * vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + *= require normalize-rails + + * + *= require_tree . + *= require_self + *= require foundation_and_overrides + + */ diff --git a/app/assets/stylesheets/browserslist b/app/assets/stylesheets/browserslist new file mode 100644 index 0000000000..6019618a9a --- /dev/null +++ b/app/assets/stylesheets/browserslist @@ -0,0 +1,4 @@ +last 2 versions +ie >= 9 +Android >= 2.3 +ios >= 7 diff --git a/app/assets/stylesheets/foundation_and_overrides.scss b/app/assets/stylesheets/foundation_and_overrides.scss new file mode 100644 index 0000000000..ed4c5a0ecf --- /dev/null +++ b/app/assets/stylesheets/foundation_and_overrides.scss @@ -0,0 +1,61 @@ +@charset 'utf-8'; + +@import 'settings'; +@import 'foundation'; + +// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package. +// +// @import 'motion-ui/motion-ui'; + +// We include everything by default. To slim your CSS, remove components you don't use. + +@include foundation-global-styles; +@include foundation-xy-grid-classes; +//@include foundation-grid; +//@include foundation-flex-grid; +@include foundation-flex-classes; +@include foundation-typography; +@include foundation-forms; +@include foundation-button; +@include foundation-accordion; +@include foundation-accordion-menu; +@include foundation-badge; +@include foundation-breadcrumbs; +@include foundation-button-group; +@include foundation-callout; +@include foundation-card; +@include foundation-close-button; +@include foundation-menu; +@include foundation-menu-icon; +@include foundation-drilldown-menu; +@include foundation-dropdown; +@include foundation-dropdown-menu; +@include foundation-responsive-embed; +@include foundation-label; +@include foundation-media-object; +@include foundation-off-canvas; +@include foundation-orbit; +@include foundation-pagination; +@include foundation-progress-bar; +@include foundation-slider; +@include foundation-sticky; +@include foundation-reveal; +@include foundation-switch; +@include foundation-table; +@include foundation-tabs; +@include foundation-thumbnail; +@include foundation-title-bar; +@include foundation-tooltip; +@include foundation-top-bar; +@include foundation-visibility-classes; +@include foundation-float-classes; + +// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package. +// +// @include motion-ui-transitions; +// @include motion-ui-animations; +@import 'motion-ui/motion-ui'; +@include motion-ui-transitions; +@include motion-ui-animations; + + 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..1c07694e9d --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,3 @@ +class ApplicationController < ActionController::Base + protect_from_forgery with: :exception +end diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep new file mode 100644 index 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..cd60004891 --- /dev/null +++ b/app/views/layouts/application.html.erb @@ -0,0 +1,19 @@ + + + + + + + <%= content_for?(:title) ? yield(:title) : "Untitled" %> + + <%= stylesheet_link_tag "application" %> + <%= javascript_include_tag "application", 'data-turbolinks-track' => true %> + <%= csrf_meta_tags %> + + + + + <%= 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..66e9889e8b --- /dev/null +++ b/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails new file mode 100755 index 0000000000..5badb2fde0 --- /dev/null +++ b/bin/rails @@ -0,0 +1,9 @@ +#!/usr/bin/env ruby +begin + load File.expand_path('../spring', __FILE__) +rescue LoadError => e + raise unless e.message.include?('spring') +end +APP_PATH = File.expand_path('../config/application', __dir__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/bin/rake b/bin/rake new file mode 100755 index 0000000000..d87d5f5781 --- /dev/null +++ b/bin/rake @@ -0,0 +1,9 @@ +#!/usr/bin/env ruby +begin + load File.expand_path('../spring', __FILE__) +rescue LoadError => e + raise unless e.message.include?('spring') +end +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/bin/setup b/bin/setup new file mode 100755 index 0000000000..78c4e861dc --- /dev/null +++ b/bin/setup @@ -0,0 +1,38 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + + # puts "\n== Copying sample files ==" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' + # end + + puts "\n== Preparing database ==" + system! 'bin/rails db:setup' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/bin/spring b/bin/spring new file mode 100755 index 0000000000..fb2ec2ebb4 --- /dev/null +++ b/bin/spring @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby + +# This file loads spring without using Bundler, in order to be fast. +# It gets overwritten when you run the `spring binstub` command. + +unless defined?(Spring) + require 'rubygems' + require 'bundler' + + lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read) + spring = lockfile.specs.detect { |spec| spec.name == "spring" } + if spring + Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path + gem 'spring', spring.version + require 'spring/binstub' + end +end diff --git a/bin/update b/bin/update new file mode 100755 index 0000000000..a8e4462f20 --- /dev/null +++ b/bin/update @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/bin/yarn b/bin/yarn new file mode 100755 index 0000000000..c2bacef836 --- /dev/null +++ b/bin/yarn @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +VENDOR_PATH = File.expand_path('..', __dir__) +Dir.chdir(VENDOR_PATH) do + begin + exec "yarnpkg #{ARGV.join(" ")}" + 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..5f6ca0f9b2 --- /dev/null +++ b/config/application.rb @@ -0,0 +1,25 @@ +require_relative 'boot' + +require 'rails/all' + +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) + +module Betsy + class Application < Rails::Application + config.generators do |g| + # Force new test files to be generated in the minitest-spec style + g.test_framework :minitest, spec: true + + # Always use .js files, never .coffee + g.javascript_engine :js + end + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 5.1 + + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + end +end diff --git a/config/boot.rb b/config/boot.rb new file mode 100644 index 0000000000..30f5120df6 --- /dev/null +++ b/config/boot.rb @@ -0,0 +1,3 @@ +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) + +require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 0000000000..3cba994bb2 --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: redis://localhost:6379/1 + channel_prefix: betsy_production diff --git a/config/database.yml b/config/database.yml new file mode 100644 index 0000000000..6903bb6083 --- /dev/null +++ b/config/database.yml @@ -0,0 +1,85 @@ +# PostgreSQL. Versions 9.1 and up are supported. +# +# Install the pg driver: +# gem install pg +# On OS X with Homebrew: +# gem install pg -- --with-pg-config=/usr/local/bin/pg_config +# On OS X with MacPorts: +# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config +# On Windows: +# gem install pg +# Choose the win32 build. +# Install PostgreSQL and put its /bin directory on your path. +# +# Configure Using Gemfile +# gem 'pg' +# +default: &default + adapter: postgresql + encoding: unicode + # For details on connection pooling, see Rails configuration guide + # http://guides.rubyonrails.org/configuring.html#database-pooling + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + +development: + <<: *default + database: betsy_development + + # The specified database role being used to connect to postgres. + # To create additional roles in postgres see `$ createuser --help`. + # When left blank, postgres will use the default role. This is + # the same name as the operating system user that initialized the database. + #username: betsy + + # The password associated with the postgres role (username). + #password: + + # Connect on a TCP socket. Omitted by default since the client uses a + # domain socket that doesn't need configuration. Windows does not have + # domain sockets, so uncomment these lines. + #host: localhost + + # The TCP port the server listens on. Defaults to 5432. + # If your server runs on a different port number, change accordingly. + #port: 5432 + + # Schema search path. The server defaults to $user,public + #schema_search_path: myapp,sharedapp,public + + # Minimum log levels, in increasing order: + # debug5, debug4, debug3, debug2, debug1, + # log, notice, warning, error, fatal, and panic + # Defaults to warning. + #min_messages: notice + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + <<: *default + database: betsy_test + +# As with config/secrets.yml, you never want to store sensitive information, +# like your database password, in your source code. If your source code is +# ever seen by anyone, they now have access to your database. +# +# Instead, provide the password as a unix environment variable when you boot +# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database +# for a full rundown on how to provide these environment variables in a +# production deployment. +# +# On Heroku and other platform providers, you may have a full connection URL +# available as an environment variable. For example: +# +# DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase" +# +# You can use this database configuration with: +# +# production: +# url: <%= ENV['DATABASE_URL'] %> +# +production: + <<: *default + database: betsy_production + username: betsy + password: <%= ENV['BETSY_DATABASE_PASSWORD'] %> diff --git a/config/environment.rb b/config/environment.rb new file mode 100644 index 0000000000..426333bb46 --- /dev/null +++ b/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require_relative 'application' + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb new file mode 100644 index 0000000000..5187e22186 --- /dev/null +++ b/config/environments/development.rb @@ -0,0 +1,54 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + if Rails.root.join('tmp/caching-dev.txt').exist? + config.action_controller.perform_caching = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. + config.assets.debug = true + + # Suppress logger output for asset requests. + config.assets.quiet = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true + + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + config.file_watcher = ActiveSupport::EventedFileUpdateChecker +end diff --git a/config/environments/production.rb b/config/environments/production.rb new file mode 100644 index 0000000000..9284f84839 --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,91 @@ +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 + + # Attempt to read encrypted secrets from `config/secrets.yml.enc`. + # Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or + # `config/secrets.yml.key`. + config.read_encrypted_secrets = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? + + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false + + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + + # Mount Action Cable outside main process or domain + # config.action_cable.mount_path = nil + # config.action_cable.url = 'wss://example.com/cable' + # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Use the lowest log level to ensure availability of diagnostic information + # when problems arise. + config.log_level = :debug + + # Prepend all log lines with the following tags. + config.log_tags = [ :request_id ] + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment) + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "betsy_#{Rails.env}" + config.action_mailer.perform_caching = false + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners. + config.active_support.deprecation = :notify + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Use a different logger for distributed setups. + # require 'syslog/logger' + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') + + if ENV["RAILS_LOG_TO_STDOUT"].present? + logger = ActiveSupport::Logger.new(STDOUT) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false +end diff --git a/config/environments/test.rb b/config/environments/test.rb new file mode 100644 index 0000000000..8e5cbde533 --- /dev/null +++ b/config/environments/test.rb @@ -0,0 +1,42 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Do not eager load code on boot. This avoids loading your whole application + # just for the purpose of running a single test. If you are using a tool that + # preloads Rails for running tests, you may have to set it to true. + config.eager_load = false + + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{1.hour.seconds.to_i}" + } + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates. + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + config.action_mailer.perform_caching = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb new file mode 100644 index 0000000000..89d2efab2b --- /dev/null +++ b/config/initializers/application_controller_renderer.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# ActiveSupport::Reloader.to_prepare do +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) +# end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 0000000000..4b828e80cb --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = '1.0' + +# Add additional assets to the asset load path. +# Rails.application.config.assets.paths << Emoji.images_path +# Add Yarn node_modules folder to the asset load path. +Rails.application.config.assets.paths << Rails.root.join('node_modules') + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in the app/assets +# folder are already added. +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000000..59385cdf37 --- /dev/null +++ b/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb new file mode 100644 index 0000000000..5a6a32d371 --- /dev/null +++ b/config/initializers/cookies_serializer.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Specify a serializer for the signed and encrypted cookie jars. +# Valid options are :json, :marshal, and :hybrid. +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb new file mode 100644 index 0000000000..4a994e1e7b --- /dev/null +++ b/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Configure sensitive parameters which will be filtered from the log file. +Rails.application.config.filter_parameters += [:password] diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb new file mode 100644 index 0000000000..ac033bf9dc --- /dev/null +++ b/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb new file mode 100644 index 0000000000..dc1899682b --- /dev/null +++ b/config/initializers/mime_types.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb new file mode 100644 index 0000000000..bbfc3961bf --- /dev/null +++ b/config/initializers/wrap_parameters.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. + +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] +end + +# To enable root element in JSON for ActiveRecord objects. +# ActiveSupport.on_load(:active_record) do +# self.include_root_in_json = true +# end diff --git a/config/locales/en.yml b/config/locales/en.yml new file mode 100644 index 0000000000..decc5a8573 --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,33 @@ +# Files in the config/locales directory are used for internationalization +# and are automatically loaded by Rails. If you want to use locales other +# than English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t 'hello' +# +# In views, this is aliased to just `t`: +# +# <%= t('hello') %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# The following keys must be escaped otherwise they will not be retrieved by +# the default I18n backend: +# +# true, false, on, off, yes, no +# +# Instead, surround them with single quotes. +# +# en: +# 'true': 'foo' +# +# To learn more, please read the Rails Internationalization guide +# available at http://guides.rubyonrails.org/i18n.html. + +en: + hello: "Hello world" diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 0000000000..1e19380dcb --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,56 @@ +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. If you use this option +# you need to make sure to reconnect any threads in the `on_worker_boot` +# block. +# +# preload_app! + +# If you are preloading your application and using Active Record, it's +# recommended that you close any connections to the database before workers +# are forked to prevent connection leakage. +# +# before_fork do +# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord) +# end + +# The code in the `on_worker_boot` will be called if you are using +# clustered mode by specifying a number of `workers`. After each worker +# process is booted, this block will be run. If you are using the `preload_app!` +# option, you will want to use this block to reconnect to any threads +# or connections that may have been created at application boot, as Ruby +# cannot share connections between processes. +# +# on_worker_boot do +# ActiveRecord::Base.establish_connection if defined?(ActiveRecord) +# end +# + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000000..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/secrets.yml b/config/secrets.yml new file mode 100644 index 0000000000..eb90581133 --- /dev/null +++ b/config/secrets.yml @@ -0,0 +1,32 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key is used for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! + +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +# You can use `rails secret` to generate a secure secret key. + +# Make sure the secrets in this file are kept private +# if you're sharing your code publicly. + +# Shared secrets are available across all environments. + +# shared: +# api_key: a1B2c3D4e5F6 + +# Environmental secrets are only available for that specific environment. + +development: + secret_key_base: a3d19a60db31633f2b176227bba686e9175d9a98c0fd174d31723278ff75d6b4a495d0799015a338f8e5df7faf751ce88cde3636b2d854a829a3127094d45508 + +test: + secret_key_base: 1169903cd667218af71f0af11e4d89150c8b326bfeb08f17d2d2361593c8498d777a8e5bcd0032a9c97ffabc77daaeab30f512e3cf559e791d7b9c2192e75606 + +# Do not keep production secrets in the unencrypted secrets file. +# Instead, either read values from the environment. +# Or, use `bin/rails secrets:setup` to configure encrypted secrets +# and move the `production:` environment over there. + +production: + secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/config/spring.rb b/config/spring.rb new file mode 100644 index 0000000000..c9119b40c0 --- /dev/null +++ b/config/spring.rb @@ -0,0 +1,6 @@ +%w( + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +).each { |path| Spring.watch(path) } diff --git a/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/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..10594a3248 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,26 @@ +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 7cf962b1fd3ff826d718d275abe8503c59e0038c Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 19 Apr 2018 11:17:31 -0700 Subject: [PATCH 002/252] created models --- app/models/category.rb | 2 + app/models/merchant.rb | 2 + app/models/order.rb | 2 + app/models/product.rb | 2 + app/models/review.rb | 2 + db/migrate/20180419180503_create_products.rb | 12 ++++ .../20180419180623_create_categories.rb | 9 +++ db/migrate/20180419180719_create_reviews.rb | 10 +++ db/migrate/20180419180745_create_merchants.rb | 10 +++ db/migrate/20180419180904_create_orders.rb | 17 +++++ .../20180419181117_add_description_to.rb | 6 ++ .../20180419181359_rename_zip_to_order.rb | 5 ++ db/schema.rb | 62 +++++++++++++++++++ test/fixtures/categories.yml | 7 +++ test/fixtures/merchants.yml | 9 +++ test/fixtures/orders.yml | 23 +++++++ test/fixtures/products.yml | 13 ++++ test/fixtures/reviews.yml | 9 +++ test/models/category_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 +++ 23 files changed, 247 insertions(+) create mode 100644 app/models/category.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/20180419180503_create_products.rb create mode 100644 db/migrate/20180419180623_create_categories.rb create mode 100644 db/migrate/20180419180719_create_reviews.rb create mode 100644 db/migrate/20180419180745_create_merchants.rb create mode 100644 db/migrate/20180419180904_create_orders.rb create mode 100644 db/migrate/20180419181117_add_description_to.rb create mode 100644 db/migrate/20180419181359_rename_zip_to_order.rb create mode 100644 db/schema.rb create mode 100644 test/fixtures/categories.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/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/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/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/20180419180503_create_products.rb b/db/migrate/20180419180503_create_products.rb new file mode 100644 index 0000000000..1483bc8533 --- /dev/null +++ b/db/migrate/20180419180503_create_products.rb @@ -0,0 +1,12 @@ +class CreateProducts < ActiveRecord::Migration[5.1] + def change + create_table :products do |t| + t.string :name + t.integer :price + t.string :category + t.integer :quantity + + t.timestamps + end + end +end diff --git a/db/migrate/20180419180623_create_categories.rb b/db/migrate/20180419180623_create_categories.rb new file mode 100644 index 0000000000..5bef4913b8 --- /dev/null +++ b/db/migrate/20180419180623_create_categories.rb @@ -0,0 +1,9 @@ +class CreateCategories < ActiveRecord::Migration[5.1] + def change + create_table :categories do |t| + t.string :name + + t.timestamps + end + end +end diff --git a/db/migrate/20180419180719_create_reviews.rb b/db/migrate/20180419180719_create_reviews.rb new file mode 100644 index 0000000000..f4e13a726d --- /dev/null +++ b/db/migrate/20180419180719_create_reviews.rb @@ -0,0 +1,10 @@ +class CreateReviews < ActiveRecord::Migration[5.1] + def change + create_table :reviews do |t| + t.integer :rating + t.string :comment + + t.timestamps + end + end +end diff --git a/db/migrate/20180419180745_create_merchants.rb b/db/migrate/20180419180745_create_merchants.rb new file mode 100644 index 0000000000..64a57c904c --- /dev/null +++ b/db/migrate/20180419180745_create_merchants.rb @@ -0,0 +1,10 @@ +class CreateMerchants < ActiveRecord::Migration[5.1] + def change + create_table :merchants do |t| + t.string :username + t.string :email + + t.timestamps + end + end +end diff --git a/db/migrate/20180419180904_create_orders.rb b/db/migrate/20180419180904_create_orders.rb new file mode 100644 index 0000000000..d751011765 --- /dev/null +++ b/db/migrate/20180419180904_create_orders.rb @@ -0,0 +1,17 @@ +class CreateOrders < ActiveRecord::Migration[5.1] + def change + create_table :orders do |t| + t.string :status + t.string :email + t.string :address + t.string :card_name + t.string :string + t.string :cc_number + t.date :cc_expiration + t.string :cvv + t.string :zip + + t.timestamps + end + end +end diff --git a/db/migrate/20180419181117_add_description_to.rb b/db/migrate/20180419181117_add_description_to.rb new file mode 100644 index 0000000000..ffcf813fda --- /dev/null +++ b/db/migrate/20180419181117_add_description_to.rb @@ -0,0 +1,6 @@ +class AddDescriptionTo < ActiveRecord::Migration[5.1] + def change + add_column :products, :description, :string + + end +end diff --git a/db/migrate/20180419181359_rename_zip_to_order.rb b/db/migrate/20180419181359_rename_zip_to_order.rb new file mode 100644 index 0000000000..e4957bd78d --- /dev/null +++ b/db/migrate/20180419181359_rename_zip_to_order.rb @@ -0,0 +1,5 @@ +class RenameZipToOrder < ActiveRecord::Migration[5.1] + def change + rename_column :orders, :zip, :zip_code + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000000..1bc4c86179 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,62 @@ +# 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: 20180419181359) 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 "merchants", force: :cascade do |t| + t.string "username" + t.string "email" + 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 "email" + t.string "address" + t.string "card_name" + t.string "string" + t.string "cc_number" + t.date "cc_expiration" + t.string "cvv" + t.string "zip_code" + 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 "category" + t.integer "quantity" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "description" + 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 + end + +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/merchants.yml b/test/fixtures/merchants.yml new file mode 100644 index 0000000000..7af41d4fbe --- /dev/null +++ b/test/fixtures/merchants.yml @@ -0,0 +1,9 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + username: MyString + email: MyString + +two: + username: MyString + email: MyString diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml new file mode 100644 index 0000000000..1b9f2d6fd3 --- /dev/null +++ b/test/fixtures/orders.yml @@ -0,0 +1,23 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + status: MyString + email: MyString + address: MyString + card_name: MyString + string: MyString + cc_number: MyString + cc_expiration: 2018-04-19 + cvv: MyString + zip: MyString + +two: + status: MyString + email: MyString + address: MyString + card_name: MyString + string: MyString + cc_number: MyString + cc_expiration: 2018-04-19 + cvv: MyString + zip: MyString diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml new file mode 100644 index 0000000000..077f7f80d4 --- /dev/null +++ b/test/fixtures/products.yml @@ -0,0 +1,13 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + price: 1 + category: MyString + quantity: 1 + +two: + name: MyString + price: 1 + category: MyString + quantity: 1 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/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 71f18465307028d1d05f9928e4370f5d4f223a6b Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 19 Apr 2018 11:38:14 -0700 Subject: [PATCH 003/252] created join tables for categorie/product and order/product --- app/models/category.rb | 3 +++ ...0180419183334_create_category_product_join.rb | 8 ++++++++ .../20180419183612_create_order_product_join.rb | 8 ++++++++ db/schema.rb | 16 +++++++++++++++- 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20180419183334_create_category_product_join.rb create mode 100644 db/migrate/20180419183612_create_order_product_join.rb diff --git a/app/models/category.rb b/app/models/category.rb index 54cb6aee3f..83898ed0d1 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,2 +1,5 @@ class Category < ApplicationRecord + has_many :products, through :categoryproduct + + validates :name, presence: true, uniqueness: true end diff --git a/db/migrate/20180419183334_create_category_product_join.rb b/db/migrate/20180419183334_create_category_product_join.rb new file mode 100644 index 0000000000..cc4e87b84e --- /dev/null +++ b/db/migrate/20180419183334_create_category_product_join.rb @@ -0,0 +1,8 @@ +class CreateCategoryProductJoin < ActiveRecord::Migration[5.1] + def change + create_table :category_product do |t| + t.belongs_to :product, index: true + t.belongs_to :category, index: true + end + end +end diff --git a/db/migrate/20180419183612_create_order_product_join.rb b/db/migrate/20180419183612_create_order_product_join.rb new file mode 100644 index 0000000000..9260aea46d --- /dev/null +++ b/db/migrate/20180419183612_create_order_product_join.rb @@ -0,0 +1,8 @@ +class CreateOrderProductJoin < ActiveRecord::Migration[5.1] + def change + create_table :order_product do |t| + t.belongs_to :order, index: true + t.belongs_to :product, index: true + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 1bc4c86179..a4038befcf 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: 20180419181359) do +ActiveRecord::Schema.define(version: 20180419183612) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -21,6 +21,13 @@ t.datetime "updated_at", null: false end + create_table "category_product", force: :cascade do |t| + t.bigint "product_id" + t.bigint "category_id" + t.index ["category_id"], name: "index_category_product_on_category_id" + t.index ["product_id"], name: "index_category_product_on_product_id" + end + create_table "merchants", force: :cascade do |t| t.string "username" t.string "email" @@ -28,6 +35,13 @@ t.datetime "updated_at", null: false end + create_table "order_product", force: :cascade do |t| + t.bigint "order_id" + t.bigint "product_id" + t.index ["order_id"], name: "index_order_product_on_order_id" + t.index ["product_id"], name: "index_order_product_on_product_id" + end + create_table "orders", force: :cascade do |t| t.string "status" t.string "email" From e5f6cb9edecbde9299e7012bcbd3fcdefe490825 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 19 Apr 2018 11:58:49 -0700 Subject: [PATCH 004/252] validates and relationships --- app/models/merchant.rb | 8 ++++++++ app/models/order.rb | 13 +++++++++++++ app/models/product.rb | 7 +++++++ app/models/review.rb | 3 +++ 4 files changed, 31 insertions(+) diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 0440407160..1bafefc7b5 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -1,2 +1,10 @@ class Merchant < ApplicationRecord + VALID_EMAIL = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i + + has_many :products + + validates :username, presence: true + validates :email, presence: true, + format: { with: VALID_EMAIL }, + uniqueness: { case_sensitive: false } end diff --git a/app/models/order.rb b/app/models/order.rb index 10281b3450..a46a2fe04a 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,2 +1,15 @@ class Order < ApplicationRecord + VALID_EMAIL = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i + + has_many :products, through :orderproduct + + validates :address, presence: true + validtes :card_name, presence: true + validates :cc_number, presence: true, length: { is: 16 } + validates :cc_expiration, presence: true + validates :ccv, presence: true, length: { is: 3 } + validates :zip_code, presence: true, length: { is: 5 } + validates :email, presence: true, + format: { with: VALID_EMAIL }, + uniqueness: { case_sensitive: false } end diff --git a/app/models/product.rb b/app/models/product.rb index 35a85acab3..2d13ae665a 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,2 +1,9 @@ class Product < ApplicationRecord + has_many :orders, through :orderproduct + has_many :categories, through :categoryproduct + has_many :reviews + + validates :name, presence: true + validates :category, presence: true + validates :quantity, presence: true, numericality: { greater_than_or_equal_to: 0 } end diff --git a/app/models/review.rb b/app/models/review.rb index b2ca4935ed..10be8b2ec2 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -1,2 +1,5 @@ class Review < ApplicationRecord + belongs_to :product + + validates :rating, presence: true, numericality: { in: 1..5 } end From 9a3a91f2f5d044ecd602f0513e13b8cf04b8ca9b Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 19 Apr 2018 12:05:18 -0700 Subject: [PATCH 005/252] Fixed typo in model relations. --- app/models/category.rb | 2 +- app/models/order.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/category.rb b/app/models/category.rb index 83898ed0d1..f8e8af1e50 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,5 +1,5 @@ class Category < ApplicationRecord - has_many :products, through :categoryproduct + has_many :products, through: :categoryproduct validates :name, presence: true, uniqueness: true end diff --git a/app/models/order.rb b/app/models/order.rb index a46a2fe04a..90116ade61 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,7 +1,7 @@ class Order < ApplicationRecord VALID_EMAIL = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i - has_many :products, through :orderproduct + has_many :products, through: :orderproduct validates :address, presence: true validtes :card_name, presence: true From dd2ec5101e40101eeb18938a1870148554f412e2 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 19 Apr 2018 13:29:04 -0700 Subject: [PATCH 006/252] Added basic tests for category model --- app/models/category.rb | 1 + app/models/order.rb | 2 +- app/models/product.rb | 4 ++-- test/fixtures/categories.yml | 9 +++++---- test/fixtures/orders.yml | 4 ++-- test/models/category_test.rb | 22 +++++++++++++++++++--- 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/app/models/category.rb b/app/models/category.rb index f8e8af1e50..694c4b9eff 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -2,4 +2,5 @@ class Category < ApplicationRecord has_many :products, through: :categoryproduct validates :name, presence: true, uniqueness: true + validates :name, length: { in: 1..5 } end diff --git a/app/models/order.rb b/app/models/order.rb index 90116ade61..3865beb6cc 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -4,7 +4,7 @@ class Order < ApplicationRecord has_many :products, through: :orderproduct validates :address, presence: true - validtes :card_name, presence: true + validates :card_name, presence: true validates :cc_number, presence: true, length: { is: 16 } validates :cc_expiration, presence: true validates :ccv, presence: true, length: { is: 3 } diff --git a/app/models/product.rb b/app/models/product.rb index 2d13ae665a..72b57dd1d0 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,6 +1,6 @@ class Product < ApplicationRecord - has_many :orders, through :orderproduct - has_many :categories, through :categoryproduct + has_many :orders, through: :orderproduct + has_many :categories, through: :categoryproduct has_many :reviews validates :name, presence: true diff --git a/test/fixtures/categories.yml b/test/fixtures/categories.yml index 56066c68af..3ea4954b47 100644 --- a/test/fixtures/categories.yml +++ b/test/fixtures/categories.yml @@ -1,7 +1,8 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: - name: MyString +candy: + name: Candy -two: - name: MyString +chocolate: + name: Chocolate + diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index 1b9f2d6fd3..9a60ad06be 100644 --- a/test/fixtures/orders.yml +++ b/test/fixtures/orders.yml @@ -9,7 +9,7 @@ one: cc_number: MyString cc_expiration: 2018-04-19 cvv: MyString - zip: MyString + zip_code: MyString two: status: MyString @@ -20,4 +20,4 @@ two: cc_number: MyString cc_expiration: 2018-04-19 cvv: MyString - zip: MyString + zip_code: MyString diff --git a/test/models/category_test.rb b/test/models/category_test.rb index 781320ad8e..d14c38a3bf 100644 --- a/test/models/category_test.rb +++ b/test/models/category_test.rb @@ -1,9 +1,25 @@ require "test_helper" describe Category do - let(:category) { Category.new } + let(:category) { Category.new name: "candy" } - it "must be valid" do - value(category).must_be :valid? + it 'must have a name' do + category.name = nil + category.valid?.must_equal false + end + + it 'must have at least one character' do + category.name = "" + category.valid?.must_equal false + end + + it 'cannot have more than 25 characters' do + category.name = "12345678901234567890123456" + category.valid?.must_equal false + end + + it 'name must be unique' do + category.name = "Chocolate" + category.valid?.must_equal false end end From cacc3fa835d4771e3ff093a1cb8e30407c5b9fec Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 19 Apr 2018 13:31:56 -0700 Subject: [PATCH 007/252] merchant model testing complete --- app/models/merchant.rb | 4 ++- app/models/order.rb | 2 +- app/models/product.rb | 4 +-- app/models/review.rb | 2 +- test/fixtures/merchants.yml | 8 +++--- test/fixtures/orders.yml | 4 +-- test/models/merchant_test.rb | 51 +++++++++++++++++++++++++++++++++++- 7 files changed, 63 insertions(+), 12 deletions(-) diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 1bafefc7b5..8b1399aa8b 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -3,7 +3,9 @@ class Merchant < ApplicationRecord has_many :products - validates :username, presence: true + validates :username, presence: true, + length: { :minimum => 0 }, + uniqueness: true validates :email, presence: true, format: { with: VALID_EMAIL }, uniqueness: { case_sensitive: false } diff --git a/app/models/order.rb b/app/models/order.rb index 90116ade61..3865beb6cc 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -4,7 +4,7 @@ class Order < ApplicationRecord has_many :products, through: :orderproduct validates :address, presence: true - validtes :card_name, presence: true + validates :card_name, presence: true validates :cc_number, presence: true, length: { is: 16 } validates :cc_expiration, presence: true validates :ccv, presence: true, length: { is: 3 } diff --git a/app/models/product.rb b/app/models/product.rb index 2d13ae665a..72b57dd1d0 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,6 +1,6 @@ class Product < ApplicationRecord - has_many :orders, through :orderproduct - has_many :categories, through :categoryproduct + has_many :orders, through: :orderproduct + has_many :categories, through: :categoryproduct has_many :reviews validates :name, presence: true diff --git a/app/models/review.rb b/app/models/review.rb index 10be8b2ec2..0c1fac0f48 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -1,5 +1,5 @@ class Review < ApplicationRecord belongs_to :product - validates :rating, presence: true, numericality: { in: 1..5 } + validates :rating, presence: true, numericality: { :in => 1..5 } end diff --git a/test/fixtures/merchants.yml b/test/fixtures/merchants.yml index 7af41d4fbe..26cea88b83 100644 --- a/test/fixtures/merchants.yml +++ b/test/fixtures/merchants.yml @@ -1,9 +1,9 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html one: - username: MyString - email: MyString + username: merchant-one + email: hello@hello.com two: - username: MyString - email: MyString + username: merchant-two + email: goodbye@goodbye.com diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index 1b9f2d6fd3..9a60ad06be 100644 --- a/test/fixtures/orders.yml +++ b/test/fixtures/orders.yml @@ -9,7 +9,7 @@ one: cc_number: MyString cc_expiration: 2018-04-19 cvv: MyString - zip: MyString + zip_code: MyString two: status: MyString @@ -20,4 +20,4 @@ two: cc_number: MyString cc_expiration: 2018-04-19 cvv: MyString - zip: MyString + zip_code: MyString diff --git a/test/models/merchant_test.rb b/test/models/merchant_test.rb index 1cc99d985f..34106ce377 100644 --- a/test/models/merchant_test.rb +++ b/test/models/merchant_test.rb @@ -1,9 +1,58 @@ require "test_helper" describe Merchant do - let(:merchant) { Merchant.new } + let(:merchant) { Merchant.new username: "person", email: "email@email.com"} it "must be valid" do value(merchant).must_be :valid? end + + it "must have a username" do + merchant.username = nil + + merchant.valid?.must_equal false + merchant.errors.must_include :username + end + + it "must raise error for invalid username length" do + merchant.username = "" + + merchant.valid?.must_equal false + merchant.errors.must_include :username + end + + it "must have a unique username" do + existing_username = Merchant.first.username + + merchant.username = existing_username + + merchant.valid? false + merchant.errors.must_include :username + end + + + it "must have an email" do + merchant.email = nil + + merchant.valid?.must_equal false + merchant.errors.must_include :email + end + + it "must raise error for invalid email format" do + merchant.email = "abcdefg" + + merchant.valid?.must_equal false + merchant.errors.must_include :email + end + + it "must have a unique email" do + existing_email = Merchant.first.email + + merchant.email = existing_email + + merchant.valid?.must_equal false + merchant.errors.must_include :email + end + + end From fab8c823824c7505774a0ac0fcf5378d8927ee9c Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 19 Apr 2018 14:12:10 -0700 Subject: [PATCH 008/252] added tests for review model --- app/models/review.rb | 5 +++- .../20180419181117_add_description_to.rb | 2 +- ...0180419205413_add_product_id_to_reviews.rb | 6 +++++ db/schema.rb | 5 +++- test/models/review_test.rb | 23 +++++++++++++++++-- 5 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 db/migrate/20180419205413_add_product_id_to_reviews.rb diff --git a/app/models/review.rb b/app/models/review.rb index 10be8b2ec2..96abdcdb1b 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -1,5 +1,8 @@ class Review < ApplicationRecord belongs_to :product - validates :rating, presence: true, numericality: { in: 1..5 } + validates :rating, presence: true + validates :rating, :inclusion => 1..5 + + validates :comment, length: { in: 1..250 } end diff --git a/db/migrate/20180419181117_add_description_to.rb b/db/migrate/20180419181117_add_description_to.rb index ffcf813fda..a2cd8be1fe 100644 --- a/db/migrate/20180419181117_add_description_to.rb +++ b/db/migrate/20180419181117_add_description_to.rb @@ -1,6 +1,6 @@ class AddDescriptionTo < ActiveRecord::Migration[5.1] def change add_column :products, :description, :string - + end end diff --git a/db/migrate/20180419205413_add_product_id_to_reviews.rb b/db/migrate/20180419205413_add_product_id_to_reviews.rb new file mode 100644 index 0000000000..694e9cef81 --- /dev/null +++ b/db/migrate/20180419205413_add_product_id_to_reviews.rb @@ -0,0 +1,6 @@ +class AddProductIdToReviews < ActiveRecord::Migration[5.1] + def change + add_reference :reviews,:product,foreign_key: true + + end +end diff --git a/db/schema.rb b/db/schema.rb index a4038befcf..19e08f3f9a 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: 20180419183612) do +ActiveRecord::Schema.define(version: 20180419205413) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -71,6 +71,9 @@ 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 "reviews", "products" end diff --git a/test/models/review_test.rb b/test/models/review_test.rb index ce8378a033..bd999f6d73 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -1,9 +1,28 @@ require "test_helper" describe Review do - let(:review) { Review.new } + let(:review) { Review.new rating:1,comment:"hdjdjhjj", product_id: (Product.create name:"candy",category:"sweets",quantity:3).id } it "must be valid" do - value(review).must_be :valid? + product = Product.create name:"candy",category:"sweets",quantity:3 + review.product.must_be :valid? end + + it "must be have a rating" do + review.product = Product.create name:"candy",category:"sweets",quantity:3 + review.rating = nil + review.valid?.must_equal false + end + it "rating must be between 1 and 5" do + product = Product.create name:"candy",category:"sweets",quantity:3 + review.rating = 6 + review.valid?.must_equal false + end + + it "must have a comment between 1 and 250 characters" do + review.product = Product.create name:"candy",category:"sweets",quantity:3 + review.comment = "" + review.valid?.must_equal false + end + end From 6d0c3b4c638b820b1d1c9b2b33b9ef502b0db836 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 19 Apr 2018 14:17:00 -0700 Subject: [PATCH 009/252] Started testing for order model --- app/models/order.rb | 2 +- test/fixtures/orders.yml | 28 +++++++++++++--------------- test/models/order_test.rb | 8 +++++++- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/app/models/order.rb b/app/models/order.rb index 3865beb6cc..b49b39f0c8 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -7,7 +7,7 @@ class Order < ApplicationRecord validates :card_name, presence: true validates :cc_number, presence: true, length: { is: 16 } validates :cc_expiration, presence: true - validates :ccv, presence: true, length: { is: 3 } + validates :cvv, presence: true, length: { is: 3 } validates :zip_code, presence: true, length: { is: 5 } validates :email, presence: true, format: { with: VALID_EMAIL }, diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index 9a60ad06be..0e82ca0b50 100644 --- a/test/fixtures/orders.yml +++ b/test/fixtures/orders.yml @@ -1,23 +1,21 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html one: - status: MyString - email: MyString - address: MyString - card_name: MyString - string: MyString - cc_number: MyString + status: Paid + email: some_person@testing.com + address: 123 Fake addres, Faketown + card_name: Fake Buyer + cc_number: 1234123412341234 cc_expiration: 2018-04-19 - cvv: MyString - zip_code: MyString + cvv: 1234 + zip_code: 98010 two: - status: MyString - email: MyString - address: MyString - card_name: MyString - string: MyString + status: Open + email: random_person@testing.com + address: 456 Fake addres, Faketown + card_name: Second Fake Buyer cc_number: MyString cc_expiration: 2018-04-19 - cvv: MyString - zip_code: MyString + cvv: 4567 + zip_code: 98000 diff --git a/test/models/order_test.rb b/test/models/order_test.rb index df80f10fb6..61c0409f2b 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -1,9 +1,15 @@ require "test_helper" describe Order do - let(:order) { Order.new } + let(:order) { Order.new address: "123, Fake address", card_name: "A name", cc_number: "1234567891234567", cc_expiration: Date.new(2001,2) , cvv: "123", zip_code: "98005", email: "email@test.com" } it "must be valid" do value(order).must_be :valid? end + +it 'must have a address' do + order.address = nil + order.valid? +end + end From 5c79631e89acd7ddb58c2fa5c5d6df2f639779b7 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 19 Apr 2018 14:30:21 -0700 Subject: [PATCH 010/252] More validations for order model testing --- test/models/order_test.rb | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/test/models/order_test.rb b/test/models/order_test.rb index 61c0409f2b..53c983a534 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -7,9 +7,32 @@ value(order).must_be :valid? end -it 'must have a address' do - order.address = nil - order.valid? -end + it 'must have a address' do + order.address = nil + order.valid?.must_equal false + end + + it 'must have a address with length more' do + order.address = nil + order.valid?.must_equal false + end + + it 'must have a card name' do + order.card_name = nil + order.valid?.must_equal false + end + + it 'must have a card number' do + order.cc_number = nil + order.valid?.must_equal false + end + + it 'must have a card expiration' do + order.cc_expiration = nil + order.valid?.must_equal false + end + + + end From c078b1f157d011a24a071b3ceba04853351659b6 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 19 Apr 2018 14:38:48 -0700 Subject: [PATCH 011/252] product model testing and model validation refactoring --- app/models/product.rb | 7 +++-- app/models/review.rb | 2 +- test/models/merchant_test.rb | 6 ++-- test/models/product_test.rb | 60 ++++++++++++++++++++++++++++++++++-- test/models/review_test.rb | 4 +-- 5 files changed, 68 insertions(+), 11 deletions(-) diff --git a/app/models/product.rb b/app/models/product.rb index 72b57dd1d0..98a14e4fbc 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -3,7 +3,8 @@ class Product < ApplicationRecord has_many :categories, through: :categoryproduct has_many :reviews - validates :name, presence: true - validates :category, presence: true - validates :quantity, presence: true, numericality: { greater_than_or_equal_to: 0 } + validates :name, presence: true, length: { minimum: 1 } + validates :category, presence: true, length: { minimum: 1 } + validates_numericality_of :quantity, presence: true, greater_than_or_equal_to: 0 + validates_numericality_of :price, presence: true, greater_than_or_equal_to: 0 end diff --git a/app/models/review.rb b/app/models/review.rb index 0c1fac0f48..10be8b2ec2 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -1,5 +1,5 @@ class Review < ApplicationRecord belongs_to :product - validates :rating, presence: true, numericality: { :in => 1..5 } + validates :rating, presence: true, numericality: { in: 1..5 } end diff --git a/test/models/merchant_test.rb b/test/models/merchant_test.rb index 34106ce377..cb37297390 100644 --- a/test/models/merchant_test.rb +++ b/test/models/merchant_test.rb @@ -1,10 +1,10 @@ require "test_helper" describe Merchant do - let(:merchant) { Merchant.new username: "person", email: "email@email.com"} + let(:merchant) { Merchant.new username: "person", email: "email@email.com" } it "must be valid" do - value(merchant).must_be :valid? + merchant.must_be :valid? end it "must have a username" do @@ -51,7 +51,7 @@ merchant.email = existing_email merchant.valid?.must_equal false - merchant.errors.must_include :email + merchant.errors.must_include :email end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index a618b0a156..9301159961 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -1,9 +1,65 @@ require "test_helper" describe Product do - let(:product) { Product.new } + let(:product) { Product.new name: "thing", price: 1, category: "red", quantity: 2 } it "must be valid" do - value(product).must_be :valid? + product.must_be :valid? + end + + it "must have a name" do + product.name = nil + + product.valid?.must_equal false + product.errors.must_include :name + end + + it "must have name length greater than zero" do + product.name = "" + + product.valid?.must_equal false + product.errors.must_include :name + end + + it "must have a category" do + product.category = nil + + product.valid?.must_equal false + product.errors.must_include :category + end + + it "must have category length greater than zero" do + product.category = "" + + product.valid?.must_equal false + product.errors.must_include :category + end + + it "must have a quantity" do + product.quantity = nil + + product.valid?.must_equal false + product.errors.must_include :quantity + end + + it "must not have a quantity less than zero" do + product.quantity = -1 + + product.valid?.must_equal false + product.errors.must_include :quantity + end + + it "must have a price" do + product.price = nil + + product.valid?.must_equal false + product.errors.must_include :price + end + + it "must not have a price less than zero" do + product.price = -2 + + product.valid?.must_equal false + product.errors.must_include :price end end diff --git a/test/models/review_test.rb b/test/models/review_test.rb index ce8378a033..e4eddbcfcf 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -1,9 +1,9 @@ require "test_helper" describe Review do - let(:review) { Review.new } + let(:review) { Review.new rating: 2, comment: nil } it "must be valid" do - value(review).must_be :valid? + review.must_be :valid? end end From f44f6311cafd56ab59a78b7c48bf8d7b984185d6 Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 19 Apr 2018 14:55:17 -0700 Subject: [PATCH 012/252] added some tests to order model --- app/models/review.rb | 2 +- ...0180419205413_add_product_id_to_reviews.rb | 6 ++++ test/models/order_test.rb | 35 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20180419205413_add_product_id_to_reviews.rb diff --git a/app/models/review.rb b/app/models/review.rb index 10be8b2ec2..2283cde3f3 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -1,5 +1,5 @@ class Review < ApplicationRecord belongs_to :product - validates :rating, presence: true, numericality: { in: 1..5 } + validates :rating, numericality: { in: 1..5 } end diff --git a/db/migrate/20180419205413_add_product_id_to_reviews.rb b/db/migrate/20180419205413_add_product_id_to_reviews.rb new file mode 100644 index 0000000000..694e9cef81 --- /dev/null +++ b/db/migrate/20180419205413_add_product_id_to_reviews.rb @@ -0,0 +1,6 @@ +class AddProductIdToReviews < ActiveRecord::Migration[5.1] + def change + add_reference :reviews,:product,foreign_key: true + + end +end diff --git a/test/models/order_test.rb b/test/models/order_test.rb index 53c983a534..61d1015af1 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -32,6 +32,41 @@ order.valid?.must_equal false end + it 'must have a cvv' do + order.cvv = nil + order.valid?.must_equal false + end + it "must have a length of three characters" do + order.cvv = "cvvv" + order.valid?.must_equal false + end + + it 'must have a zipcode' do + order.zip_code = nil + order.valid?.must_equal false + end + + it "zipcode length must be 5 " do + order.zip_code = "980756" + order.valid?.must_equal false + end + + it 'must have a email' do + order.email = nil + order.valid?.must_equal false + end + + it "must have a valid email format" do + order.email = "12345@.email.com" + order.valid?.must_equal false + end + + it "must have a unique email id" do + exisiting_email = Order.first.email + order.email = "some_person@testing.com" + order.valid?.must_equal false + end + From d4264108a5e6b58108948952688cbfdd5926b60c Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 19 Apr 2018 15:01:37 -0700 Subject: [PATCH 013/252] Started relation testing on order. --- app/models/order.rb | 4 +-- test/fixtures/products.yml | 8 ++--- test/models/order_test.rb | 73 ++++++++++++++++++++++++++------------ 3 files changed, 56 insertions(+), 29 deletions(-) diff --git a/app/models/order.rb b/app/models/order.rb index b49b39f0c8..af88d1d932 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -3,8 +3,8 @@ class Order < ApplicationRecord has_many :products, through: :orderproduct - validates :address, presence: true - validates :card_name, presence: true + validates :address, presence: true, length: { in: 1..35 } + validates :card_name, presence: true, length: { minimum: 1 } validates :cc_number, presence: true, length: { is: 16 } validates :cc_expiration, presence: true validates :cvv, presence: true, length: { is: 3 } diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index 077f7f80d4..523f73b4af 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -1,9 +1,9 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: - name: MyString - price: 1 - category: MyString +candy: + name: Candy + price: 10 + category: candy quantity: 1 two: diff --git a/test/models/order_test.rb b/test/models/order_test.rb index 53c983a534..b9187d410e 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -3,36 +3,63 @@ describe Order do let(:order) { Order.new address: "123, Fake address", card_name: "A name", cc_number: "1234567891234567", cc_expiration: Date.new(2001,2) , cvv: "123", zip_code: "98005", email: "email@test.com" } - it "must be valid" do - value(order).must_be :valid? - end + describe 'validations' do - it 'must have a address' do - order.address = nil - order.valid?.must_equal false - end - it 'must have a address with length more' do - order.address = nil - order.valid?.must_equal false - end + it "must be valid" do + value(order).must_be :valid? + end - it 'must have a card name' do - order.card_name = nil - order.valid?.must_equal false - end - it 'must have a card number' do - order.cc_number = nil - order.valid?.must_equal false - end + it 'must have a address' do + order.address = nil + order.valid?.must_equal false + end - it 'must have a card expiration' do - order.cc_expiration = nil - order.valid?.must_equal false - end + it 'must have an address with length more than 0 characters' do + order.address = "" + order.valid?.must_equal false + end + it 'must cannot have an address with length more than 35' do + order.address = "123451234512345123451234512345123451" + order.valid?.must_equal false + end + it 'must have a card name' do + order.card_name = nil + order.valid?.must_equal false + end + it 'must have a card name with more than 0 characters' do + order.card_name = "" + order.valid?.must_equal false + end + it 'must have a card number' do + order.cc_number = nil + order.valid?.must_equal false + end + + it 'must have a card expiration' do + order.cc_expiration = nil + order.valid?.must_equal false + end + + it 'card expiration must be a date' do + order.cc_expiration = "a string" + order.valid?.must_equal false + end + end + + describe "relations" do + it "has a list of products" do + # candy = products(:candy) + order.must_respond_to :products + order.products.each do |product| + product.must_be_kind_of Product + end + end + + end end From 354a72eae7789a949ef35d0301046d1a71ba278a Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 19 Apr 2018 15:40:41 -0700 Subject: [PATCH 014/252] added relation test to review --- .../20180419220012_add_product_id_to_order.rb | 5 ++ db/schema.rb | 5 +- test/fixtures/products.yml | 2 +- test/models/order_test.rb | 67 ++++++++++++++++++- test/models/review_test.rb | 16 ++++- 5 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 db/migrate/20180419220012_add_product_id_to_order.rb diff --git a/db/migrate/20180419220012_add_product_id_to_order.rb b/db/migrate/20180419220012_add_product_id_to_order.rb new file mode 100644 index 0000000000..b5e94e8622 --- /dev/null +++ b/db/migrate/20180419220012_add_product_id_to_order.rb @@ -0,0 +1,5 @@ +class AddProductIdToOrder < ActiveRecord::Migration[5.1] + def change + add_reference :orders, :product,foreign_key: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 19e08f3f9a..4f3dab415b 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: 20180419205413) do +ActiveRecord::Schema.define(version: 20180419220012) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -54,6 +54,8 @@ t.string "zip_code" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.bigint "product_id" + t.index ["product_id"], name: "index_orders_on_product_id" end create_table "products", force: :cascade do |t| @@ -75,5 +77,6 @@ t.index ["product_id"], name: "index_reviews_on_product_id" end + add_foreign_key "orders", "products" add_foreign_key "reviews", "products" end diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index 077f7f80d4..3e4583db1b 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -3,7 +3,7 @@ one: name: MyString price: 1 - category: MyString + category: sweets quantity: 1 two: diff --git a/test/models/order_test.rb b/test/models/order_test.rb index df80f10fb6..e80fb9612c 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -1,9 +1,74 @@ require "test_helper" describe Order do - let(:order) { Order.new } + let(:order) { Order.new address: "123, Fake address", card_name: "A name", cc_number: "1234567891234567", cc_expiration: Date.new(2001,2) , cvv: "123", zip_code: "98005", email: "email@test.com" } it "must be valid" do value(order).must_be :valid? end + + it 'must have a address' do + order.address = nil + order.valid?.must_equal false + end + + it 'must have a address with length more' do + order.address = nil + order.valid?.must_equal false + end + + it 'must have a card name' do + order.card_name = nil + order.valid?.must_equal false + end + + it 'must have a card number' do + order.cc_number = nil + order.valid?.must_equal false + end + + it 'must have a card expiration' do + order.cc_expiration = nil + order.valid?.must_equal false + end + + it 'must have a cvv' do + order.cvv = nil + order.valid?.must_equal false + end + it "must have a length of three characters" do + order.cvv = "cvvv" + order.valid?.must_equal false + end + + it 'must have a zipcode' do + order.zip_code = nil + order.valid?.must_equal false + end + + it "zipcode length must be 5 " do + order.zip_code = "980756" + order.valid?.must_equal false + end + + it 'must have a email' do + order.email = nil + order.valid?.must_equal false + end + + it "must have a valid email format" do + order.email = "12345@.email.com" + order.valid?.must_equal false + end + + it "must have a unique email id" do + exisiting_email = Order.first.email + order.email = "some_person@testing.com" + order.valid?.must_equal false + end + + + + + end diff --git a/test/models/review_test.rb b/test/models/review_test.rb index bd999f6d73..9f5d310817 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -9,20 +9,30 @@ end it "must be have a rating" do - review.product = Product.create name:"candy",category:"sweets",quantity:3 + review.rating = nil review.valid?.must_equal false end it "rating must be between 1 and 5" do - product = Product.create name:"candy",category:"sweets",quantity:3 + review.rating = 6 review.valid?.must_equal false end it "must have a comment between 1 and 250 characters" do - review.product = Product.create name:"candy",category:"sweets",quantity:3 + review.comment = "" review.valid?.must_equal false end + + it "belongs to a product and creates an error message if no product is given" do + + review = Review.new(rating: 1, comment:"qwewe") + review.must_respond_to :product + + review.wont_be :valid? + review.errors.messages.must_include :product + end + end From 73bc6b3dc341383786165cbcf1e2afb404b52e94 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 19 Apr 2018 15:42:17 -0700 Subject: [PATCH 015/252] model merchant and category have relations testing --- app/models/category.rb | 4 +- ...180419215459_add_product_id_to_category.rb | 5 ++ db/schema.rb | 5 +- test/fixtures/categories.yml | 1 - test/models/category_test.rb | 46 +++++++---- test/models/merchant_test.rb | 79 +++++++++++-------- 6 files changed, 86 insertions(+), 54 deletions(-) create mode 100644 db/migrate/20180419215459_add_product_id_to_category.rb diff --git a/app/models/category.rb b/app/models/category.rb index 694c4b9eff..059235cf53 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,6 +1,6 @@ class Category < ApplicationRecord - has_many :products, through: :categoryproduct - + has_and_belongs_to_many :products + validates :name, presence: true, uniqueness: true validates :name, length: { in: 1..5 } end diff --git a/db/migrate/20180419215459_add_product_id_to_category.rb b/db/migrate/20180419215459_add_product_id_to_category.rb new file mode 100644 index 0000000000..fe3f0ad24b --- /dev/null +++ b/db/migrate/20180419215459_add_product_id_to_category.rb @@ -0,0 +1,5 @@ +class AddProductIdToCategory < ActiveRecord::Migration[5.1] + def change + add_reference :categories, :product, foreign_key: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 19e08f3f9a..def787516d 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: 20180419205413) do +ActiveRecord::Schema.define(version: 20180419215459) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -19,6 +19,8 @@ t.string "name" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.bigint "product_id" + t.index ["product_id"], name: "index_categories_on_product_id" end create_table "category_product", force: :cascade do |t| @@ -75,5 +77,6 @@ t.index ["product_id"], name: "index_reviews_on_product_id" end + add_foreign_key "categories", "products" add_foreign_key "reviews", "products" end diff --git a/test/fixtures/categories.yml b/test/fixtures/categories.yml index 3ea4954b47..f4ef2aaa34 100644 --- a/test/fixtures/categories.yml +++ b/test/fixtures/categories.yml @@ -5,4 +5,3 @@ candy: chocolate: name: Chocolate - diff --git a/test/models/category_test.rb b/test/models/category_test.rb index d14c38a3bf..e4b4ffbb6c 100644 --- a/test/models/category_test.rb +++ b/test/models/category_test.rb @@ -1,25 +1,41 @@ require "test_helper" describe Category do - let(:category) { Category.new name: "candy" } + let(:category) { Category.new name: "candy", product_id: (Product.create name: "thing", category: "choco", quantity: 2).id } - it 'must have a name' do - category.name = nil - category.valid?.must_equal false - end + describe "validations" do + it "must be valid" do + category.valid?.must_equal true + end - it 'must have at least one character' do - category.name = "" - category.valid?.must_equal false - end + it 'must have a name' do + category.name = nil + category.valid?.must_equal false + end + + it 'must have at least one character' do + category.name = "" + category.valid?.must_equal false + end - it 'cannot have more than 25 characters' do - category.name = "12345678901234567890123456" - category.valid?.must_equal false + it 'cannot have more than 25 characters' do + category.name = "12345678901234567890123456" + category.valid?.must_equal false + end + + it 'name must be unique' do + category.name = "Chocolate" + category.valid?.must_equal false + end end - it 'name must be unique' do - category.name = "Chocolate" - category.valid?.must_equal false + describe "relations" do + it "has a list of products" do + category.must_respond_to :products + + category.products.each do |product| + product.must_be_kind_of Product + end + end end end diff --git a/test/models/merchant_test.rb b/test/models/merchant_test.rb index cb37297390..46e90a40e2 100644 --- a/test/models/merchant_test.rb +++ b/test/models/merchant_test.rb @@ -3,56 +3,65 @@ describe Merchant do let(:merchant) { Merchant.new username: "person", email: "email@email.com" } - it "must be valid" do - merchant.must_be :valid? - end - - it "must have a username" do - merchant.username = nil + describe "validations" do + it "must be valid" do + merchant.must_be :valid? + end - merchant.valid?.must_equal false - merchant.errors.must_include :username - end + it "must have a username" do + merchant.username = nil - it "must raise error for invalid username length" do - merchant.username = "" + merchant.valid?.must_equal false + merchant.errors.must_include :username + end - merchant.valid?.must_equal false - merchant.errors.must_include :username - end + it "must raise error for invalid username length" do + merchant.username = "" - it "must have a unique username" do - existing_username = Merchant.first.username + merchant.valid?.must_equal false + merchant.errors.must_include :username + end - merchant.username = existing_username + it "must have a unique username" do + existing_username = Merchant.first.username - merchant.valid? false - merchant.errors.must_include :username - end + merchant.username = existing_username + merchant.valid? false + merchant.errors.must_include :username + end - it "must have an email" do - merchant.email = nil + it "must have an email" do + merchant.email = nil - merchant.valid?.must_equal false - merchant.errors.must_include :email - end + merchant.valid?.must_equal false + merchant.errors.must_include :email + end - it "must raise error for invalid email format" do - merchant.email = "abcdefg" + it "must raise error for invalid email format" do + merchant.email = "abcdefg" - merchant.valid?.must_equal false - merchant.errors.must_include :email - end + merchant.valid?.must_equal false + merchant.errors.must_include :email + end - it "must have a unique email" do - existing_email = Merchant.first.email + it "must have a unique email" do + existing_email = Merchant.first.email - merchant.email = existing_email + merchant.email = existing_email - merchant.valid?.must_equal false - merchant.errors.must_include :email + merchant.valid?.must_equal false + merchant.errors.must_include :email + end end + describe "relations" do + it "has a list of products" do + merchant.must_respond_to :products + merchant.products.each do |product| + product.must_be_kind_of Product + end + end + end end From 95ad00280ff835079de1beea3e429fa21243a45f Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 19 Apr 2018 15:47:24 -0700 Subject: [PATCH 016/252] Added relations test for product. --- app/models/product.rb | 4 +- test/models/product_test.rb | 110 ++++++++++++++++++++++-------------- 2 files changed, 71 insertions(+), 43 deletions(-) diff --git a/app/models/product.rb b/app/models/product.rb index 98a14e4fbc..c72dbf23a8 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,6 +1,6 @@ class Product < ApplicationRecord - has_many :orders, through: :orderproduct - has_many :categories, through: :categoryproduct + has_and_belongs_to_many :orders, through: :orderproduct + has_and_belongs_to_many :categories, through: :categoryproduct has_many :reviews validates :name, presence: true, length: { minimum: 1 } diff --git a/test/models/product_test.rb b/test/models/product_test.rb index 9301159961..12a50b074f 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -3,63 +3,91 @@ describe Product do let(:product) { Product.new name: "thing", price: 1, category: "red", quantity: 2 } - it "must be valid" do - product.must_be :valid? - end + describe 'Validations' do - it "must have a name" do - product.name = nil + it "must be valid" do + product.must_be :valid? + end - product.valid?.must_equal false - product.errors.must_include :name - end + it "must have a name" do + product.name = nil - it "must have name length greater than zero" do - product.name = "" + product.valid?.must_equal false + product.errors.must_include :name + end - product.valid?.must_equal false - product.errors.must_include :name - end + it "must have name length greater than zero" do + product.name = "" - it "must have a category" do - product.category = nil + product.valid?.must_equal false + product.errors.must_include :name + end - product.valid?.must_equal false - product.errors.must_include :category - end + it "must have a category" do + product.category = nil - it "must have category length greater than zero" do - product.category = "" + product.valid?.must_equal false + product.errors.must_include :category + end - product.valid?.must_equal false - product.errors.must_include :category - end + it "must have category length greater than zero" do + product.category = "" - it "must have a quantity" do - product.quantity = nil + product.valid?.must_equal false + product.errors.must_include :category + end - product.valid?.must_equal false - product.errors.must_include :quantity - end + it "must have a quantity" do + product.quantity = nil - it "must not have a quantity less than zero" do - product.quantity = -1 + product.valid?.must_equal false + product.errors.must_include :quantity + end - product.valid?.must_equal false - product.errors.must_include :quantity - end + it "must not have a quantity less than zero" do + product.quantity = -1 + + product.valid?.must_equal false + product.errors.must_include :quantity + end - it "must have a price" do - product.price = nil + it "must have a price" do + product.price = nil - product.valid?.must_equal false - product.errors.must_include :price + product.valid?.must_equal false + product.errors.must_include :price + end + + it "must not have a price less than zero" do + product.price = -2 + + product.valid?.must_equal false + product.errors.must_include :price + end + end + +describe 'relations' do + it "has a list of orders" do + product.must_respond_to :orders + product.orders.each do |order| + order.must_be_kind_of Order + end end - it "must not have a price less than zero" do - product.price = -2 + it "has a list of categories" do + product.must_respond_to :categories + product.categories.each do |category| + category.must_be_kind_of Category + end + end - product.valid?.must_equal false - product.errors.must_include :price + it "has a list of reviews" do + product.must_respond_to :reviews + product.reviews.each do |review| + review.must_be_kind_of Review + end end + +end + end From b5dd3f14b8c19a4336119ab85090dddea99730b0 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 19 Apr 2018 15:50:00 -0700 Subject: [PATCH 017/252] merging conficts --- app/models/merchant.rb | 1 - test/models/order_test.rb | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 8b1399aa8b..70f790d139 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -1,6 +1,5 @@ class Merchant < ApplicationRecord VALID_EMAIL = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i - has_many :products validates :username, presence: true, diff --git a/test/models/order_test.rb b/test/models/order_test.rb index 1be28469b9..c394954979 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -1,10 +1,9 @@ require "test_helper" describe Order do - let(:order) { Order.new address: "123, Fake address", card_name: "A name", cc_number: "1234567891234567", cc_expiration: Date.new(2001,2) , cvv: "123", zip_code: "98005", email: "email@test.com" } + let(:order) { Order.new address: "123, Fake address", card_name: "A name", cc_number: "1234567891234567", cc_expiration: Date.new(2001,2), cvv: "123", zip_code: "98005", email: "email@test.com" } describe 'validations' do - it "must be valid" do value(order).must_be :valid? end From 7c18ef31fb91e8c772da9d49808947ac41018b10 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 19 Apr 2018 15:54:10 -0700 Subject: [PATCH 018/252] Resolving merge conflicts --- db/schema.rb | 11 ++-- test/models/order_test.rb | 121 ++++++++++++++++++-------------------- 2 files changed, 60 insertions(+), 72 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 7ec7799157..0f18276d63 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,11 +10,8 @@ # # It's strongly recommended that you check this file into your version control system. -<<<<<<< HEAD -ActiveRecord::Schema.define(version: 20180419215459) do -======= ActiveRecord::Schema.define(version: 20180419220012) do ->>>>>>> review_model_testing + # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -83,10 +80,10 @@ t.index ["product_id"], name: "index_reviews_on_product_id" end -<<<<<<< HEAD + add_foreign_key "categories", "products" -======= + add_foreign_key "orders", "products" ->>>>>>> review_model_testing + add_foreign_key "reviews", "products" end diff --git a/test/models/order_test.rb b/test/models/order_test.rb index ad1b29283b..162426c53e 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -1,11 +1,8 @@ require "test_helper" describe Order do -<<<<<<< HEAD - let(:order) { Order.new address: "123, Fake address", card_name: "A name", cc_number: "1234567891234567", cc_expiration: Date.new(2001,2) , cvv: "123", zip_code: "98005", email: "email@test.com" } -======= let(:order) { Order.new address: "123, Fake address", card_name: "A name", cc_number: "1234567891234567", cc_expiration: Date.new(2001,2) , cvv: "123", zip_code: "98005", email: "email@test.com" } ->>>>>>> review_model_testing + describe 'validations' do @@ -86,79 +83,73 @@ order.email = "some_person@testing.com" order.valid?.must_equal false end - end - - describe "relations" do - it "has a list of products" do - order.must_respond_to :products - order.products.each do |product| - product.must_be_kind_of Product - end + it 'must have a address' do + order.address = nil + order.valid?.must_equal false end - end - it 'must have a address' do - order.address = nil - order.valid?.must_equal false - end + it 'must have a address with length more' do + order.address = nil + order.valid?.must_equal false + end - it 'must have a address with length more' do - order.address = nil - order.valid?.must_equal false - end + it 'must have a card name' do + order.card_name = nil + order.valid?.must_equal false + end - it 'must have a card name' do - order.card_name = nil - order.valid?.must_equal false - end + it 'must have a card number' do + order.cc_number = nil + order.valid?.must_equal false + end - it 'must have a card number' do - order.cc_number = nil - order.valid?.must_equal false - end + it 'must have a card expiration' do + order.cc_expiration = nil + order.valid?.must_equal false + end - it 'must have a card expiration' do - order.cc_expiration = nil - order.valid?.must_equal false - end + it 'must have a cvv' do + order.cvv = nil + order.valid?.must_equal false + end + it "must have a length of three characters" do + order.cvv = "cvvv" + order.valid?.must_equal false + end - it 'must have a cvv' do - order.cvv = nil - order.valid?.must_equal false - end - it "must have a length of three characters" do - order.cvv = "cvvv" - order.valid?.must_equal false - end + it 'must have a zipcode' do + order.zip_code = nil + order.valid?.must_equal false + end - it 'must have a zipcode' do - order.zip_code = nil - order.valid?.must_equal false - end + it "zipcode length must be 5 " do + order.zip_code = "980756" + order.valid?.must_equal false + end - it "zipcode length must be 5 " do - order.zip_code = "980756" - order.valid?.must_equal false - end + it 'must have a email' do + order.email = nil + order.valid?.must_equal false + end - it 'must have a email' do - order.email = nil - order.valid?.must_equal false - end + it "must have a valid email format" do + order.email = "12345@.email.com" + order.valid?.must_equal false + end - it "must have a valid email format" do - order.email = "12345@.email.com" - order.valid?.must_equal false + it "must have a unique email id" do + exisiting_email = Order.first.email + order.email = "some_person@testing.com" + order.valid?.must_equal false + end end - it "must have a unique email id" do - exisiting_email = Order.first.email - order.email = "some_person@testing.com" - order.valid?.must_equal false + describe "relations" do + it "has a list of products" do + order.must_respond_to :products + order.products.each do |product| + product.must_be_kind_of Product + end + end end - - - - - end From 311dbdb3dbb9433e7a31fcfbecfc5f544c6f0cd8 Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 19 Apr 2018 15:56:44 -0700 Subject: [PATCH 019/252] merge conflict --- db/schema.rb | 7 ------- test/models/order_test.rb | 3 --- test/models/review_test.rb | 16 ++++++++-------- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 7ec7799157..77b0ab3735 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,11 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -<<<<<<< HEAD -ActiveRecord::Schema.define(version: 20180419215459) do -======= ActiveRecord::Schema.define(version: 20180419220012) do ->>>>>>> review_model_testing # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -83,10 +79,7 @@ t.index ["product_id"], name: "index_reviews_on_product_id" end -<<<<<<< HEAD add_foreign_key "categories", "products" -======= add_foreign_key "orders", "products" ->>>>>>> review_model_testing add_foreign_key "reviews", "products" end diff --git a/test/models/order_test.rb b/test/models/order_test.rb index ad1b29283b..4b85bda8e3 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -156,9 +156,6 @@ order.email = "some_person@testing.com" order.valid?.must_equal false end - - - end diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 9f5d310817..c516122414 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -9,10 +9,11 @@ end it "must be have a rating" do - + review.rating = nil review.valid?.must_equal false end + it "rating must be between 1 and 5" do review.rating = 6 @@ -25,14 +26,13 @@ review.valid?.must_equal false end + it "belongs to a product and creates an error message if no product is given" do - it "belongs to a product and creates an error message if no product is given" do + review = Review.new(rating: 1, comment:"qwewe") + review.must_respond_to :product - review = Review.new(rating: 1, comment:"qwewe") - review.must_respond_to :product - - review.wont_be :valid? - review.errors.messages.must_include :product - end + review.wont_be :valid? + review.errors.messages.must_include :product + end end From be9ec8a8d69862223127c1682b023d421708c8f2 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 19 Apr 2018 15:56:47 -0700 Subject: [PATCH 020/252] schema merge fix --- db/schema.rb | 7 ------- test/models/review_test.rb | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 7ec7799157..77b0ab3735 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,11 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -<<<<<<< HEAD -ActiveRecord::Schema.define(version: 20180419215459) do -======= ActiveRecord::Schema.define(version: 20180419220012) do ->>>>>>> review_model_testing # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -83,10 +79,7 @@ t.index ["product_id"], name: "index_reviews_on_product_id" end -<<<<<<< HEAD add_foreign_key "categories", "products" -======= add_foreign_key "orders", "products" ->>>>>>> review_model_testing add_foreign_key "reviews", "products" end diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 9f5d310817..1cace29f15 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -9,7 +9,7 @@ end it "must be have a rating" do - + review.rating = nil review.valid?.must_equal false end From 44b631fd616b9b46004f7822d294d4268337cbea Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 19 Apr 2018 15:57:53 -0700 Subject: [PATCH 021/252] Deleted unecessary code line. --- test/models/order_test.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/models/order_test.rb b/test/models/order_test.rb index ad445da903..a4c4ba4613 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -137,7 +137,6 @@ end it "must have a unique email id" do - exisiting_email = Order.first.email order.email = "some_person@testing.com" order.valid?.must_equal false end From 9b6c7cc6b1df6695529ded1395760b553a4eefc6 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 19 Apr 2018 16:09:48 -0700 Subject: [PATCH 022/252] Fixing review model testing --- db/schema.rb | 11 ----------- test/models/review_test.rb | 6 +++--- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index a78f1628c1..f714779f82 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,10 +11,6 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema.define(version: 20180419220012) do -<<<<<<< HEAD -======= - ->>>>>>> 97a05a3abc9531f2f9de2813b8384fd659a53d60 # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -83,15 +79,8 @@ t.index ["product_id"], name: "index_reviews_on_product_id" end -<<<<<<< HEAD - add_foreign_key "categories", "products" - add_foreign_key "orders", "products" -======= add_foreign_key "categories", "products" - add_foreign_key "orders", "products" - ->>>>>>> 97a05a3abc9531f2f9de2813b8384fd659a53d60 add_foreign_key "reviews", "products" end diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 1cace29f15..80a4d7f121 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -1,11 +1,11 @@ require "test_helper" describe Review do - let(:review) { Review.new rating:1,comment:"hdjdjhjj", product_id: (Product.create name:"candy",category:"sweets",quantity:3).id } + let(:review) { Review.new rating:1, comment:"hdjdjhjj" } it "must be valid" do - product = Product.create name:"candy",category:"sweets",quantity:3 - review.product.must_be :valid? + review.product = products(:candy) + review.valid?.must_equal true end it "must be have a rating" do From 1de640d4ed908df8ad3a6c2e71b0b1c14460c162 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 19 Apr 2018 16:10:30 -0700 Subject: [PATCH 023/252] review model refactor --- test/models/review_test.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 1cace29f15..66b8a2a4b9 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -1,11 +1,12 @@ require "test_helper" describe Review do - let(:review) { Review.new rating:1,comment:"hdjdjhjj", product_id: (Product.create name:"candy",category:"sweets",quantity:3).id } + let(:review) { Review.new rating:1,comment:"hdjdjhjj" } it "must be valid" do - product = Product.create name:"candy",category:"sweets",quantity:3 - review.product.must_be :valid? + review.product = Product.create name:"candy",category:"sweets",quantity:3 + + review.must_be :valid? end it "must be have a rating" do From 112a77cf34d3e18352609ec77b66d220730cd028 Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 19 Apr 2018 16:38:37 -0700 Subject: [PATCH 024/252] created products controller --- app/assets/javascripts/products.js | 2 + app/assets/stylesheets/products.scss | 3 ++ app/controllers/products_controller.rb | 22 +++++++++++ app/helpers/products_helper.rb | 2 + app/views/products/create.html.erb | 2 + app/views/products/destroy.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 + config/routes.rb | 14 +++++++ test/controllers/products_controller_test.rb | 39 ++++++++++++++++++++ 13 files changed, 96 insertions(+) create mode 100644 app/assets/javascripts/products.js create mode 100644 app/assets/stylesheets/products.scss create mode 100644 app/controllers/products_controller.rb create mode 100644 app/helpers/products_helper.rb create mode 100644 app/views/products/create.html.erb create mode 100644 app/views/products/destroy.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 test/controllers/products_controller_test.rb 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/stylesheets/products.scss b/app/assets/stylesheets/products.scss new file mode 100644 index 0000000000..89e2e8db07 --- /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/controllers/products_controller.rb b/app/controllers/products_controller.rb new file mode 100644 index 0000000000..6cc58717c0 --- /dev/null +++ b/app/controllers/products_controller.rb @@ -0,0 +1,22 @@ +class ProductsController < ApplicationController + def index + end + + def show + end + + def new + end + + def create + end + + def edit + end + + def update + end + + def destroy + end +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/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/destroy.html.erb b/app/views/products/destroy.html.erb new file mode 100644 index 0000000000..d5c678b499 --- /dev/null +++ b/app/views/products/destroy.html.erb @@ -0,0 +1,2 @@ +

Products#destroy

+

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

diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb new file mode 100644 index 0000000000..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/config/routes.rb b/config/routes.rb index 787824f888..dbc46a40e3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,17 @@ Rails.application.routes.draw do + get 'products/index' + + get 'products/show' + + get 'products/new' + + get 'products/create' + + get 'products/edit' + + get 'products/update' + + get 'products/destroy' + # 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 new file mode 100644 index 0000000000..a00ad0e288 --- /dev/null +++ b/test/controllers/products_controller_test.rb @@ -0,0 +1,39 @@ +require "test_helper" + +describe ProductsController do + 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 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 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 + + it "should get destroy" do + get products_destroy_url + value(response).must_be :success? + end + +end From dd9e45cf0e26703be9a6a48dbec51a25c5f51a11 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 19 Apr 2018 16:39:19 -0700 Subject: [PATCH 025/252] Genereted categories_controller and reviews_controller --- app/assets/javascripts/categories.js | 2 + app/assets/javascripts/reviews.js | 2 + app/assets/stylesheets/categories.scss | 3 ++ app/assets/stylesheets/reviews.scss | 3 ++ app/controllers/categories_controller.rb | 22 +++++++++++ app/controllers/reviews_controller.rb | 22 +++++++++++ app/helpers/categories_helper.rb | 2 + app/helpers/reviews_helper.rb | 2 + app/views/categories/create.html.erb | 2 + app/views/categories/destroy.html.erb | 2 + app/views/categories/edit.html.erb | 2 + app/views/categories/index.html.erb | 2 + app/views/categories/new.html.erb | 2 + app/views/categories/show.html.erb | 2 + app/views/categories/update.html.erb | 2 + app/views/reviews/create.html.erb | 2 + app/views/reviews/destroy.html.erb | 2 + app/views/reviews/edit.html.erb | 2 + app/views/reviews/index.html.erb | 2 + app/views/reviews/new.html.erb | 2 + app/views/reviews/show.html.erb | 2 + app/views/reviews/update.html.erb | 2 + config/routes.rb | 28 +++++++++++++ .../controllers/categories_controller_test.rb | 39 +++++++++++++++++++ test/controllers/reviews_controller_test.rb | 39 +++++++++++++++++++ 25 files changed, 192 insertions(+) create mode 100644 app/assets/javascripts/categories.js create mode 100644 app/assets/javascripts/reviews.js create mode 100644 app/assets/stylesheets/categories.scss create mode 100644 app/assets/stylesheets/reviews.scss create mode 100644 app/controllers/categories_controller.rb create mode 100644 app/controllers/reviews_controller.rb create mode 100644 app/helpers/categories_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/destroy.html.erb create mode 100644 app/views/categories/edit.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/categories/show.html.erb create mode 100644 app/views/categories/update.html.erb create mode 100644 app/views/reviews/create.html.erb create mode 100644 app/views/reviews/destroy.html.erb create mode 100644 app/views/reviews/edit.html.erb create mode 100644 app/views/reviews/index.html.erb create mode 100644 app/views/reviews/new.html.erb create mode 100644 app/views/reviews/show.html.erb create mode 100644 app/views/reviews/update.html.erb create mode 100644 test/controllers/categories_controller_test.rb create mode 100644 test/controllers/reviews_controller_test.rb 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/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/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..7f39ecd007 --- /dev/null +++ b/app/controllers/categories_controller.rb @@ -0,0 +1,22 @@ +class CategoriesController < ApplicationController + def index + end + + def show + end + + def new + end + + def create + end + + def update + end + + def edit + end + + def destroy + end +end diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb new file mode 100644 index 0000000000..f4b9f214e7 --- /dev/null +++ b/app/controllers/reviews_controller.rb @@ -0,0 +1,22 @@ +class ReviewsController < ApplicationController + def index + end + + def show + end + + def new + end + + def create + end + + def update + end + + def edit + end + + def destroy + 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/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/destroy.html.erb b/app/views/categories/destroy.html.erb new file mode 100644 index 0000000000..a6ac971f4c --- /dev/null +++ b/app/views/categories/destroy.html.erb @@ -0,0 +1,2 @@ +

Categories#destroy

+

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

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

Categories#edit

+

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

diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb new file mode 100644 index 0000000000..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/categories/show.html.erb b/app/views/categories/show.html.erb new file mode 100644 index 0000000000..60e06c3d7b --- /dev/null +++ b/app/views/categories/show.html.erb @@ -0,0 +1,2 @@ +

Categories#show

+

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

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

Categories#update

+

Find me in app/views/categories/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/app/views/reviews/destroy.html.erb b/app/views/reviews/destroy.html.erb new file mode 100644 index 0000000000..df58c59d5c --- /dev/null +++ b/app/views/reviews/destroy.html.erb @@ -0,0 +1,2 @@ +

Reviews#destroy

+

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

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

Reviews#edit

+

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

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

Reviews#index

+

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

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

Reviews#new

+

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

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

Reviews#show

+

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

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

Reviews#update

+

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

diff --git a/config/routes.rb b/config/routes.rb index 787824f888..d8658c80fc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,31 @@ Rails.application.routes.draw do + get 'reviews/index' + + get 'reviews/show' + + get 'reviews/new' + + get 'reviews/create' + + get 'reviews/update' + + get 'reviews/edit' + + get 'reviews/destroy' + + get 'categories/index' + + get 'categories/show' + + get 'categories/new' + + get 'categories/create' + + get 'categories/update' + + get 'categories/edit' + + get 'categories/destroy' + # 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..36e13c1822 --- /dev/null +++ b/test/controllers/categories_controller_test.rb @@ -0,0 +1,39 @@ +require "test_helper" + +describe CategoriesController do + it "should get index" do + get categories_index_url + value(response).must_be :success? + end + + it "should get show" do + get categories_show_url + value(response).must_be :success? + end + + 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 update" do + get categories_update_url + value(response).must_be :success? + end + + it "should get edit" do + get categories_edit_url + value(response).must_be :success? + end + + it "should get destroy" do + get categories_destroy_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..211b509ebe --- /dev/null +++ b/test/controllers/reviews_controller_test.rb @@ -0,0 +1,39 @@ +require "test_helper" + +describe ReviewsController do + it "should get index" do + get reviews_index_url + value(response).must_be :success? + end + + it "should get show" do + get reviews_show_url + value(response).must_be :success? + end + + it "should get new" do + get reviews_new_url + value(response).must_be :success? + end + + it "should get create" do + get reviews_create_url + value(response).must_be :success? + end + + it "should get update" do + get reviews_update_url + value(response).must_be :success? + end + + it "should get edit" do + get reviews_edit_url + value(response).must_be :success? + end + + it "should get destroy" do + get reviews_destroy_url + value(response).must_be :success? + end + +end From 22567688006e8148cabfcfbfc1d8a86e1b5c8930 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 19 Apr 2018 16:39:21 -0700 Subject: [PATCH 026/252] orders controller created --- app/assets/javascripts/orders.js | 2 ++ app/assets/stylesheets/orders.scss | 3 ++ app/controllers/orders_controller.rb | 22 ++++++++++++ app/helpers/orders_helper.rb | 2 ++ app/views/orders/create.html.erb | 2 ++ app/views/orders/destroy.html.erb | 2 ++ app/views/orders/edit.html.erb | 2 ++ app/views/orders/index.html.erb | 2 ++ app/views/orders/new.html.erb | 2 ++ app/views/orders/show.html.erb | 2 ++ app/views/orders/update.html.erb | 2 ++ config/routes.rb | 14 ++++++++ test/controllers/orders_controller_test.rb | 39 ++++++++++++++++++++++ test/models/review_test.rb | 12 +++---- 14 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 app/assets/javascripts/orders.js create mode 100644 app/assets/stylesheets/orders.scss create mode 100644 app/controllers/orders_controller.rb create mode 100644 app/helpers/orders_helper.rb create mode 100644 app/views/orders/create.html.erb create mode 100644 app/views/orders/destroy.html.erb create mode 100644 app/views/orders/edit.html.erb create mode 100644 app/views/orders/index.html.erb create mode 100644 app/views/orders/new.html.erb create mode 100644 app/views/orders/show.html.erb create mode 100644 app/views/orders/update.html.erb create mode 100644 test/controllers/orders_controller_test.rb 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/stylesheets/orders.scss b/app/assets/stylesheets/orders.scss new file mode 100644 index 0000000000..3b0428a94e --- /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/controllers/orders_controller.rb b/app/controllers/orders_controller.rb new file mode 100644 index 0000000000..3f0441143a --- /dev/null +++ b/app/controllers/orders_controller.rb @@ -0,0 +1,22 @@ +class OrdersController < ApplicationController + def index + end + + def show + end + + def new + end + + def create + end + + def update + end + + def edit + end + + def destroy + end +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/views/orders/create.html.erb b/app/views/orders/create.html.erb new file mode 100644 index 0000000000..295bd84094 --- /dev/null +++ b/app/views/orders/create.html.erb @@ -0,0 +1,2 @@ +

Orders#create

+

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

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

Orders#destroy

+

Find me in app/views/orders/destroy.html.erb

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

Orders#edit

+

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

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

Orders#index

+

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

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

Orders#new

+

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

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

Orders#show

+

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

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

Orders#update

+

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

diff --git a/config/routes.rb b/config/routes.rb index 787824f888..e82b5b949f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,17 @@ Rails.application.routes.draw do + get 'orders/index' + + get 'orders/show' + + get 'orders/new' + + get 'orders/create' + + get 'orders/update' + + get 'orders/edit' + + get 'orders/destroy' + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb new file mode 100644 index 0000000000..2f00b03123 --- /dev/null +++ b/test/controllers/orders_controller_test.rb @@ -0,0 +1,39 @@ +require "test_helper" + +describe OrdersController do + it "should get index" do + get orders_index_url + value(response).must_be :success? + end + + it "should get show" do + get orders_show_url + value(response).must_be :success? + end + + it "should get new" do + get orders_new_url + value(response).must_be :success? + end + + it "should get create" do + get orders_create_url + value(response).must_be :success? + end + + it "should get update" do + get orders_update_url + value(response).must_be :success? + end + + it "should get edit" do + get orders_edit_url + value(response).must_be :success? + end + + it "should get destroy" do + get orders_destroy_url + value(response).must_be :success? + end + +end diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 80a4d7f121..d3e6a41e20 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -26,13 +26,13 @@ end - it "belongs to a product and creates an error message if no product is given" do + it "belongs to a product and creates an error message if no product is given" do - review = Review.new(rating: 1, comment:"qwewe") - review.must_respond_to :product + review = Review.new(rating: 1, comment:"qwewe") + review.must_respond_to :product - review.wont_be :valid? - review.errors.messages.must_include :product - end + review.wont_be :valid? + review.errors.messages.must_include :product + end end From 8d5ddefd65878e51a33bf85d248f066e26d04f2e Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 19 Apr 2018 16:39:38 -0700 Subject: [PATCH 027/252] added merchants controller --- app/assets/javascripts/merchants.js | 2 + app/assets/stylesheets/merchants.scss | 3 ++ app/controllers/merchants_controller.rb | 22 +++++++++++ app/helpers/merchants_helper.rb | 2 + app/views/merchants/create.html.erb | 2 + app/views/merchants/destroy.html.erb | 2 + app/views/merchants/edit.html.erb | 2 + app/views/merchants/index.html.erb | 2 + app/views/merchants/new.html.erb | 2 + app/views/merchants/show.html.erb | 2 + app/views/merchants/update.html.erb | 2 + config/routes.rb | 14 +++++++ test/controllers/merchants_controller_test.rb | 39 +++++++++++++++++++ 13 files changed, 96 insertions(+) create mode 100644 app/assets/javascripts/merchants.js create mode 100644 app/assets/stylesheets/merchants.scss create mode 100644 app/controllers/merchants_controller.rb create mode 100644 app/helpers/merchants_helper.rb create mode 100644 app/views/merchants/create.html.erb create mode 100644 app/views/merchants/destroy.html.erb create mode 100644 app/views/merchants/edit.html.erb create mode 100644 app/views/merchants/index.html.erb create mode 100644 app/views/merchants/new.html.erb create mode 100644 app/views/merchants/show.html.erb create mode 100644 app/views/merchants/update.html.erb create mode 100644 test/controllers/merchants_controller_test.rb 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/stylesheets/merchants.scss b/app/assets/stylesheets/merchants.scss new file mode 100644 index 0000000000..2327c00afe --- /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/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb new file mode 100644 index 0000000000..45be0beb40 --- /dev/null +++ b/app/controllers/merchants_controller.rb @@ -0,0 +1,22 @@ +class MerchantsController < ApplicationController + def index + end + + def show + end + + def new + end + + def create + end + + def edit + end + + def update + end + + def destroy + end +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/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/destroy.html.erb b/app/views/merchants/destroy.html.erb new file mode 100644 index 0000000000..7378a23230 --- /dev/null +++ b/app/views/merchants/destroy.html.erb @@ -0,0 +1,2 @@ +

Merchants#destroy

+

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

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

Merchants#edit

+

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

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

Merchants#index

+

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

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

Merchants#new

+

Find me in app/views/merchants/new.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/merchants/update.html.erb b/app/views/merchants/update.html.erb new file mode 100644 index 0000000000..48e3f8aed5 --- /dev/null +++ b/app/views/merchants/update.html.erb @@ -0,0 +1,2 @@ +

Merchants#update

+

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

diff --git a/config/routes.rb b/config/routes.rb index dbc46a40e3..a3f61715b9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,18 @@ Rails.application.routes.draw do + get 'merchants/index' + + get 'merchants/show' + + get 'merchants/new' + + get 'merchants/create' + + get 'merchants/edit' + + get 'merchants/update' + + get 'merchants/destroy' + get 'products/index' get 'products/show' diff --git a/test/controllers/merchants_controller_test.rb b/test/controllers/merchants_controller_test.rb new file mode 100644 index 0000000000..0467f61ef1 --- /dev/null +++ b/test/controllers/merchants_controller_test.rb @@ -0,0 +1,39 @@ +require "test_helper" + +describe MerchantsController do + it "should get index" do + get merchants_index_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 new" do + get merchants_new_url + value(response).must_be :success? + end + + it "should get create" do + get merchants_create_url + value(response).must_be :success? + end + + it "should get edit" do + get merchants_edit_url + value(response).must_be :success? + end + + it "should get update" do + get merchants_update_url + value(response).must_be :success? + end + + it "should get destroy" do + get merchants_destroy_url + value(response).must_be :success? + end + +end From 328578858f1c5a101e5269c012393602b8b5250c Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 19 Apr 2018 16:46:18 -0700 Subject: [PATCH 028/252] added some routes --- config/routes.rb | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/config/routes.rb b/config/routes.rb index 1f4d96d8e7..d95b59130e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -29,5 +29,47 @@ get 'products/destroy' + get 'reviews/index' + + get 'reviews/show' + + get 'reviews/new' + + get 'reviews/create' + + get 'reviews/update' + + get 'reviews/edit' + + get 'reviews/destroy' + + get 'categories/index' + + get 'categories/show' + + get 'categories/new' + + get 'categories/create' + + get 'categories/update' + + get 'categories/edit' + + get 'categories/destroy' + + get 'orders/index' + + get 'orders/show' + + get 'orders/new' + + get 'orders/create' + + get 'orders/update' + + get 'orders/edit' + + get 'orders/destroy' + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end From 65de561ca593c67b27e6dc2a18b321e9b123bdda Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 19 Apr 2018 18:35:42 -0700 Subject: [PATCH 029/252] created sessions controller --- app/assets/javascripts/sessions.js | 2 ++ app/assets/stylesheets/sessions.scss | 3 ++ app/controllers/sessions_controller.rb | 16 +++++++++++ app/helpers/sessions_helper.rb | 2 ++ app/views/sessions/create.html.erb | 2 ++ app/views/sessions/destroy.html.erb | 2 ++ app/views/sessions/index.html.erb | 2 ++ app/views/sessions/new.html.erb | 2 ++ app/views/sessions/show.html.erb | 2 ++ config/routes.rb | 10 +++++++ test/controllers/sessions_controller_test.rb | 29 ++++++++++++++++++++ test/models/order_test.rb | 5 +--- 12 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 app/assets/javascripts/sessions.js create mode 100644 app/assets/stylesheets/sessions.scss create mode 100644 app/controllers/sessions_controller.rb create mode 100644 app/helpers/sessions_helper.rb create mode 100644 app/views/sessions/create.html.erb create mode 100644 app/views/sessions/destroy.html.erb create mode 100644 app/views/sessions/index.html.erb create mode 100644 app/views/sessions/new.html.erb create mode 100644 app/views/sessions/show.html.erb create mode 100644 test/controllers/sessions_controller_test.rb diff --git a/app/assets/javascripts/sessions.js b/app/assets/javascripts/sessions.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/sessions.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/stylesheets/sessions.scss b/app/assets/stylesheets/sessions.scss new file mode 100644 index 0000000000..7bef9cf826 --- /dev/null +++ b/app/assets/stylesheets/sessions.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the sessions controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 0000000000..e855433b06 --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,16 @@ +class SessionsController < ApplicationController + def index + end + + def show + end + + def new + end + + def create + end + + def destroy + end +end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb new file mode 100644 index 0000000000..309f8b2eb3 --- /dev/null +++ b/app/helpers/sessions_helper.rb @@ -0,0 +1,2 @@ +module SessionsHelper +end diff --git a/app/views/sessions/create.html.erb b/app/views/sessions/create.html.erb new file mode 100644 index 0000000000..c251174fea --- /dev/null +++ b/app/views/sessions/create.html.erb @@ -0,0 +1,2 @@ +

Sessions#create

+

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

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

Sessions#destroy

+

Find me in app/views/sessions/destroy.html.erb

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

Sessions#index

+

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

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

Sessions#new

+

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

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

Sessions#show

+

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

diff --git a/config/routes.rb b/config/routes.rb index d95b59130e..6aac2d0004 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,15 @@ Rails.application.routes.draw do + get 'sessions/index' + + get 'sessions/show' + + get 'sessions/new' + + get 'sessions/create' + + get 'sessions/destroy' + get 'merchants/index' get 'merchants/show' diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb new file mode 100644 index 0000000000..9637f4bcbb --- /dev/null +++ b/test/controllers/sessions_controller_test.rb @@ -0,0 +1,29 @@ +require "test_helper" + +describe SessionsController do + it "should get index" do + get sessions_index_url + value(response).must_be :success? + end + + it "should get show" do + get sessions_show_url + value(response).must_be :success? + end + + it "should get new" do + get sessions_new_url + value(response).must_be :success? + end + + it "should get create" do + get sessions_create_url + value(response).must_be :success? + end + + it "should get destroy" do + get sessions_destroy_url + value(response).must_be :success? + end + +end diff --git a/test/models/order_test.rb b/test/models/order_test.rb index 6e368a6d11..87497aa2aa 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -53,6 +53,7 @@ order.cvv = nil order.valid?.must_equal false end + it "must have a length of three characters" do order.cvv = "cvvv" order.valid?.must_equal false @@ -150,9 +151,5 @@ end end end -<<<<<<< HEAD - -======= ->>>>>>> 97a05a3abc9531f2f9de2813b8384fd659a53d60 end From 30557051c2a9fda6e07249a74af0050ecf4de3c0 Mon Sep 17 00:00:00 2001 From: Leticia Tran Date: Thu, 19 Apr 2018 21:30:34 -0700 Subject: [PATCH 030/252] Created products#root and views/root --- app/controllers/products_controller.rb | 4 +++ app/views/products/root.html.erb | 1 + config/routes.rb | 37 +++++++++++++++----------- 3 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 app/views/products/root.html.erb diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 6cc58717c0..eb8fb51228 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,4 +1,8 @@ class ProductsController < ApplicationController + def root + @products = Products.all + end + def index end diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb new file mode 100644 index 0000000000..a33bd2a9f8 --- /dev/null +++ b/app/views/products/root.html.erb @@ -0,0 +1 @@ +

root

diff --git a/config/routes.rb b/config/routes.rb index 6aac2d0004..607a3d96ff 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,15 +1,23 @@ Rails.application.routes.draw do - get 'sessions/index' + # Products: + get 'products/root', to: 'products#root', as: 'root' - get 'sessions/show' + get 'products/index' - get 'sessions/new' + get 'products/show' - get 'sessions/create' + get 'products/new' - get 'sessions/destroy' + get 'products/create' + + get 'products/edit' + + get 'products/update' + + get 'products/destroy' + # Merchants: get 'merchants/index' get 'merchants/show' @@ -24,21 +32,18 @@ get 'merchants/destroy' - get 'products/index' - - get 'products/show' - - get 'products/new' - - get 'products/create' + # Sessions: + get 'sessions/index' - get 'products/edit' + get 'sessions/show' - get 'products/update' + get 'sessions/new' - get 'products/destroy' + get 'sessions/create' + get 'sessions/destroy' + # Reviews: get 'reviews/index' get 'reviews/show' @@ -53,6 +58,7 @@ get 'reviews/destroy' + # Categories: get 'categories/index' get 'categories/show' @@ -67,6 +73,7 @@ get 'categories/destroy' + # Orders: get 'orders/index' get 'orders/show' From b258bf578b7474b8d33ef0e9d9c5d13367d1d028 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 19 Apr 2018 21:43:39 -0700 Subject: [PATCH 031/252] controller filters --- app/controllers/categories_controller.rb | 15 ++++++++++++++- app/controllers/merchants_controller.rb | 14 ++++++++++++++ app/controllers/orders_controller.rb | 14 ++++++++++++++ app/controllers/products_controller.rb | 14 ++++++++++++++ app/controllers/reviews_controller.rb | 14 ++++++++++++++ config/routes.rb | 1 - 6 files changed, 70 insertions(+), 2 deletions(-) diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 7f39ecd007..b33b06b653 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -1,11 +1,15 @@ class CategoriesController < ApplicationController + before_action :find_book, only: [:show, :edit, :update, :destroy] + def index + @categories = Category.all end def show end def new + @category = Category.new end def create @@ -19,4 +23,13 @@ def edit def destroy end -end + + private + + def category_params + return params.require(:category).permit(:name) + end + + def find_category + @category = Category.find_by(id: params[:id]) + end diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 45be0beb40..1dc89e2b59 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -1,11 +1,15 @@ class MerchantsController < ApplicationController + before_action :find_merchant, only: [:show, :edit, :update, :destroy] + def index + @merchants = Merchant.all end def show end def new + @merchant = Merchant.new end def create @@ -19,4 +23,14 @@ def update def destroy end + + private + + def merchant_params + return params.require(:merchant).permit(:username, :email) + end + + def find_merchant + @merchant = Merchant.find_by(:id params[:id]) + end end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 3f0441143a..a93788f8c3 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,11 +1,15 @@ class OrdersController < ApplicationController + before_action :find_order, only: [:show, :edit, :update, :destroy] + def index + @orders = Order.all end def show end def new + @order = Order.new end def create @@ -19,4 +23,14 @@ def edit def destroy end + + private + + def order_params + return params.require(:order).permit(:status, :email, :address, :card_name, :cc_number, :cc_expiration, :cvv, :zip_code) + end + + def find_order + @order = Order.find_by(id: params[:id]) + end end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 6cc58717c0..78f84b1204 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,11 +1,15 @@ class ProductsController < ApplicationController + before_action :find_product, only: [:show, :edit, :update, :destroy] + def index + @products = Product.all end def show end def new + @product = Product.new end def create @@ -19,4 +23,14 @@ def update def destroy end + + private + + def product_params + return params.require(:product).permit(:name, :price, :category, :quantity, :description) + end + + def find_product + @product = Product.find_by(id: params[:id]) + end end diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index f4b9f214e7..ca17a05e1b 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -1,11 +1,15 @@ class ReviewsController < ApplicationController + before_action :find_review, only: [:show, :edit, :update, :destroy] + def index + @reviews = Review.all end def show end def new + @review = Review.new end def create @@ -19,4 +23,14 @@ def edit def destroy end + + private + + def review_params + return params.require(:review).permit(:rating, :comment) + end + + def find_review + @review = Review.find_by(id: params[:id]) + end end diff --git a/config/routes.rb b/config/routes.rb index d95b59130e..85968a8c91 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -28,7 +28,6 @@ get 'products/destroy' - get 'reviews/index' get 'reviews/show' From 2b61706de1a2b7f945bd847a44577e0671447faa Mon Sep 17 00:00:00 2001 From: Leticia Tran Date: Thu, 19 Apr 2018 21:55:20 -0700 Subject: [PATCH 032/252] Created some seed files and som products(using faker for now.) --- Gemfile | 2 ++ Gemfile.lock | 9 +++++++++ app/controllers/products_controller.rb | 1 + db/seeds.rb | 12 ++++++++++++ db/seeds/merchants.csv | 0 db/seeds/products.csv | 0 6 files changed, 24 insertions(+) create mode 100644 db/seeds/merchants.csv create mode 100644 db/seeds/products.csv diff --git a/Gemfile b/Gemfile index 8490d0efb5..41afb43f6d 100644 --- a/Gemfile +++ b/Gemfile @@ -70,3 +70,5 @@ group :test do gem 'minitest-rails' gem 'minitest-reporters' end + +gem 'faker', :git => 'https://github.com/stympy/faker.git', :branch => 'master' diff --git a/Gemfile.lock b/Gemfile.lock index d528acb17a..344966d402 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,11 @@ +GIT + remote: https://github.com/stympy/faker.git + revision: f8e1b81f8da82ea9eb88c4939a3a6801f97e5ac1 + branch: master + specs: + faker (1.8.7) + i18n (>= 0.7) + GEM remote: https://rubygems.org/ specs: @@ -211,6 +219,7 @@ DEPENDENCIES binding_of_caller byebug capybara (~> 2.13) + faker! foundation-rails jbuilder (~> 2.5) jquery-rails diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 6cc58717c0..c5dc58579c 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,5 +1,6 @@ class ProductsController < ApplicationController def index + @products = Product.all end def show diff --git a/db/seeds.rb b/db/seeds.rb index 1beea2accd..7f4ddaed40 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -5,3 +5,15 @@ # # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) # Character.create(name: 'Luke', movie: movies.first) + + +require 'faker' + +category = Category.new(name: "Dessert") + +20.times do |t| + product = Product.create(name: Faker::Dessert.variety, price: 1, category: category , quantity: 2 ) + puts "#{product.name} created!" +end + +p "Created #{Product.count} desserts" diff --git a/db/seeds/merchants.csv b/db/seeds/merchants.csv new file mode 100644 index 0000000000..e69de29bb2 diff --git a/db/seeds/products.csv b/db/seeds/products.csv new file mode 100644 index 0000000000..e69de29bb2 From 0e3c4909f9da44cb41bcd34de053f048002f4e1d Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 19 Apr 2018 22:12:48 -0700 Subject: [PATCH 033/252] model testing style standardizing --- test/models/category_test.rb | 8 +++++ test/models/order_test.rb | 58 ++++++++++++++++++++++++++++++++---- test/models/product_test.rb | 38 ++++++++++++----------- test/models/review_test.rb | 54 +++++++++++++++++---------------- 4 files changed, 109 insertions(+), 49 deletions(-) diff --git a/test/models/category_test.rb b/test/models/category_test.rb index e4b4ffbb6c..9a2de957d1 100644 --- a/test/models/category_test.rb +++ b/test/models/category_test.rb @@ -10,22 +10,30 @@ it 'must have a name' do category.name = nil + category.valid?.must_equal false + category.errors.must_include :name end it 'must have at least one character' do category.name = "" + category.valid?.must_equal false + category.errors.must_include :name end it 'cannot have more than 25 characters' do category.name = "12345678901234567890123456" + category.valid?.must_equal false + category.errors.must_include :name end it 'name must be unique' do category.name = "Chocolate" + category.valid?.must_equal false + category.errors.must_include :name end end diff --git a/test/models/order_test.rb b/test/models/order_test.rb index 87497aa2aa..8999dfc53d 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -6,146 +6,194 @@ describe 'validations' do it "must be valid" do - value(order).must_be :valid? + order.must_be :valid? end it 'must have a address' do order.address = nil + order.valid?.must_equal false + order.errors.must_include :address end it 'must have an address with length more than 0 characters' do order.address = "" + order.valid?.must_equal false + order.errors.must_include :address end it 'must cannot have an address with length more than 35' do order.address = "123451234512345123451234512345123451" + order.valid?.must_equal false + order.errors.must_include :address end it 'must have a card name' do order.card_name = nil + order.valid?.must_equal false + order.errors.must_include :card_name end it 'must have a card name with more than 0 characters' do order.card_name = "" + order.valid?.must_equal false + order.errors.must_include :card_name end it 'must have a card number' do order.cc_number = nil + order.valid?.must_equal false + order.errors.must_include :cc_number end it 'must have a card expiration' do order.cc_expiration = nil + order.valid?.must_equal false + order.errors.must_include :cc_expiration end it 'card expiration must be a date' do order.cc_expiration = "a string" + order.valid?.must_equal false + order.errors.must_include :cc_expiration end it 'must have a cvv' do order.cvv = nil + order.valid?.must_equal false + order.errors.must_include :cvv end it "must have a length of three characters" do order.cvv = "cvvv" + order.valid?.must_equal false + order.errors.must_include :cvv end it 'must have a zipcode' do order.zip_code = nil + order.valid?.must_equal false + order.errors.must_include :zip_code end it "zipcode length must be 5 " do order.zip_code = "980756" + order.valid?.must_equal false + order.errors.must_include :zip_code end it 'must have a email' do order.email = nil + order.valid?.must_equal false + order.errors.must_include :email end it "must have a valid email format" do order.email = "12345@.email.com" + order.valid?.must_equal false + order.errors.must_include :email end it "must have a unique email id" do order.email = "some_person@testing.com" + order.valid?.must_equal false + order.errors.must_include :email end it 'must have a address' do order.address = nil + order.valid?.must_equal false + order.errors.must_include :address end it 'must have a address with length more' do order.address = nil + order.valid?.must_equal false + order.errors.must_include :address end it 'must have a card name' do order.card_name = nil - order.valid?.must_equal false - end - it 'must have a card number' do - order.cc_number = nil order.valid?.must_equal false + order.errors.must_include :card_name end it 'must have a card expiration' do order.cc_expiration = nil + order.valid?.must_equal false + order.errors.must_include :cc_expiration end it 'must have a cvv' do order.cvv = nil + order.valid?.must_equal false + order.errors.must_include :cvv end it "must have a length of three characters" do order.cvv = "cvvv" + order.valid?.must_equal false + order.errors.must_include :cvv end it 'must have a zipcode' do order.zip_code = nil + order.valid?.must_equal false + order.errors.must_include :zip_code end it "zipcode length must be 5 " do order.zip_code = "980756" + order.valid?.must_equal false + order.errors.must_include :zip_code end it 'must have a email' do order.email = nil + order.valid?.must_equal false + order.errors.must_include :email end it "must have a valid email format" do order.email = "12345@.email.com" + order.valid?.must_equal false + order.errors.must_include :email end it "must have a unique email id" do order.email = "some_person@testing.com" + order.valid?.must_equal false + order.errors.must_include :email end end describe "relations" do it "has a list of products" do order.must_respond_to :products + order.products.each do |product| product.must_be_kind_of Product end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index 12a50b074f..1272776888 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -4,7 +4,6 @@ let(:product) { Product.new name: "thing", price: 1, category: "red", quantity: 2 } describe 'Validations' do - it "must be valid" do product.must_be :valid? end @@ -66,28 +65,31 @@ end end -describe 'relations' do - it "has a list of orders" do - product.must_respond_to :orders - product.orders.each do |order| - order.must_be_kind_of Order + describe 'relations' do + it "has a list of orders" do + product.must_respond_to :orders + + product.orders.each do |order| + order.must_be_kind_of Order + end end - end - it "has a list of categories" do - product.must_respond_to :categories - product.categories.each do |category| - category.must_be_kind_of Category + it "has a list of categories" do + product.must_respond_to :categories + + product.categories.each do |category| + category.must_be_kind_of Category + end end - end - it "has a list of reviews" do - product.must_respond_to :reviews - product.reviews.each do |review| - review.must_be_kind_of Review + it "has a list of reviews" do + product.must_respond_to :reviews + + product.reviews.each do |review| + review.must_be_kind_of Review + end end - end -end + end end diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 629b0f17c5..76f463210b 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -3,41 +3,43 @@ describe Review do let(:review) { Review.new rating:1, comment:"hdjdjhjj" } - it "must be valid" do - review.product = products(:candy) - review.valid?.must_equal true - end - - it "must be have a rating" do + describe "validations" do + it "must be valid" do + review.product = products(:candy) - review.rating = nil - review.valid?.must_equal false - end + review.valid?.must_equal true + end - it "rating must be between 1 and 5" do + it "must be have a rating" do + review.rating = nil - review.rating = 6 - review.valid?.must_equal false - end + review.valid?.must_equal false + review.errors.must_include :rating + end - it "must have a comment between 1 and 250 characters" do + it "rating must be between 1 and 5" do + review.rating = 6 - review.comment = "" - review.valid?.must_equal false - end + review.valid?.must_equal false + review.errors.must_include :rating + end - it "belongs to a product and creates an error message if no product is given" do + it "must have a comment between 1 and 250 characters" do + review.comment = "" -<<<<<<< HEAD -======= - it "belongs to a product and creates an error message if no product is given" do + review.valid?.must_equal false + review.errors.must_include :comment + end + end ->>>>>>> 4abfedf6e5f3b151bcc59d057c836b4ac4634c6e - review = Review.new(rating: 1, comment:"qwewe") - review.must_respond_to :product + describe "relations" do + it "belongs to a product and creates an error message if no product is given" do + review = Review.new(rating: 1, comment:"qwewe") + review.must_respond_to :product - review.wont_be :valid? - review.errors.messages.must_include :product + review.wont_be :valid? + review.errors.messages.must_include :product + end end end From b96b5d703dd6441488bf422bb454c4f17b92b4a3 Mon Sep 17 00:00:00 2001 From: Leticia Tran Date: Thu, 19 Apr 2018 22:20:44 -0700 Subject: [PATCH 034/252] Seeds loop with faker for products outputing their name once they are created. --- db/seeds.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/db/seeds.rb b/db/seeds.rb index 7f4ddaed40..9b8c49b6b0 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -14,6 +14,7 @@ 20.times do |t| product = Product.create(name: Faker::Dessert.variety, price: 1, category: category , quantity: 2 ) puts "#{product.name} created!" + # puts " category: #{product.category.name}" end p "Created #{Product.count} desserts" From 6f7994863c3375fc189bda43f355be7ccf17c412 Mon Sep 17 00:00:00 2001 From: Leticia Tran Date: Thu, 19 Apr 2018 22:21:29 -0700 Subject: [PATCH 035/252] Fixed typo from maximun lenght of name (it was 5, put 25) --- app/models/category.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/category.rb b/app/models/category.rb index 059235cf53..74790501ed 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,6 +1,6 @@ class Category < ApplicationRecord has_and_belongs_to_many :products - + validates :name, presence: true, uniqueness: true - validates :name, length: { in: 1..5 } + validates :name, length: { in: 1..25 } end From 546a6bffcdeb93bb9d517cc851cacb85985074cd Mon Sep 17 00:00:00 2001 From: Leticia Tran Date: Thu, 19 Apr 2018 22:22:18 -0700 Subject: [PATCH 036/252] Passed all procust to views/root and created a loop with list to show all products for now. --- app/controllers/products_controller.rb | 3 +-- app/views/products/root.html.erb | 11 ++++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 7007e084a7..c8758bfa8f 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,10 +1,9 @@ class ProductsController < ApplicationController def root - @products = Products.all + @products = Product.all end def index - @products = Product.all end def show diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index a33bd2a9f8..5b2dea5b7a 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -1 +1,10 @@ -

root

+

Splash page...

+ + +
+
    + <% @products.each do |product|%> +
  • <%= product.name %>
  • + <% end %> +
+
From 98d8b07d301e63c58b42a67a36bf8deee9e8b5a5 Mon Sep 17 00:00:00 2001 From: Leticia Tran Date: Thu, 19 Apr 2018 22:32:52 -0700 Subject: [PATCH 037/252] Named products#show route --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 607a3d96ff..b62a5f0cd1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -5,7 +5,7 @@ get 'products/index' - get 'products/show' + get 'products/:id', to: 'products#show', as: 'product' get 'products/new' From a4c088ec5dbb855054187a006c9e8c3aa246f1ff Mon Sep 17 00:00:00 2001 From: Leticia Tran Date: Thu, 19 Apr 2018 22:33:27 -0700 Subject: [PATCH 038/252] Changed list of products to have the product name as a link to product/:id --- app/views/products/root.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index 5b2dea5b7a..2ead10c97a 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -4,7 +4,7 @@
    <% @products.each do |product|%> -
  • <%= product.name %>
  • +
  • <%= link_to product.name, product_path(product.id) %>
  • <% end %>
From 8cb74158bfd535f3cecb3cdb0f56f37978349387 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 19 Apr 2018 23:06:54 -0700 Subject: [PATCH 039/252] route for products#root --- config/routes.rb | 2 +- db/schema.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index b62a5f0cd1..22b39e46c0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,7 @@ Rails.application.routes.draw do # Products: - get 'products/root', to: 'products#root', as: 'root' + root 'products#root' get 'products/index' diff --git a/db/schema.rb b/db/schema.rb index 9c27fb6623..77b0ab3735 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,6 +11,7 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema.define(version: 20180419220012) do + # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -80,6 +81,5 @@ add_foreign_key "categories", "products" add_foreign_key "orders", "products" - add_foreign_key "reviews", "products" end From 552fc5f8762de4f0c6a4fcd220084c41dc9c8d1f Mon Sep 17 00:00:00 2001 From: Aruna Date: Fri, 20 Apr 2018 07:08:35 -0700 Subject: [PATCH 040/252] added session controller and its methods --- app/controllers/sessions_controller.rb | 25 +++++++++++++++++++++++-- config/routes.rb | 12 +++--------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index e855433b06..53c62f2b69 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -5,12 +5,33 @@ def index def show end - def new + def create + @merchant = Merchant.find_by(username: params[:merchant][:username]) + + if @merchant + session[:merchant_id] = @merchant.id + + flash[:success] = "Welcome back #{@merchant.username}" + redirect_to root_path + else + @merchant = Merchant.create(username: params[:merchant][:username]) + if session[:merchant_id] = @merchant.id + flash[:success] = "Successfully logged in as #{@merchant.username}" + redirect_to root_path + else + flash.now[:error] = "You are not logged in. Please login" + render :new + end + end end - def create + def new + @merchant = Merchant.new end def destroy + session[:merchant_id] = nil + flash[:success] = "You logged out!" + redirect_to root_path end end diff --git a/config/routes.rb b/config/routes.rb index 6aac2d0004..3e5a3c0dd9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,14 +1,8 @@ Rails.application.routes.draw do - get 'sessions/index' - - get 'sessions/show' - - get 'sessions/new' - - get 'sessions/create' - - get 'sessions/destroy' + get '/login', to: 'sessions#new', as: 'login_form' + post '/login', to: 'sessions#create' + delete '/login', to: 'sessions#destroy', as: 'logout' get 'merchants/index' From 1ec602ba2ab763727eaa317462c1d8bf076e2516 Mon Sep 17 00:00:00 2001 From: Aruna Date: Fri, 20 Apr 2018 10:07:49 -0700 Subject: [PATCH 041/252] changed routes --- config/routes.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/config/routes.rb b/config/routes.rb index 6ee521cace..badc48acb2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -5,6 +5,23 @@ post '/login', to: 'sessions#create' delete '/login', to: 'sessions#destroy', as: 'logout' + # Products: + root 'products#root' + + get 'products/index' + + get 'products/:id', to: 'products#show', as: 'product' + + get 'products/new' + + get 'products/create' + + get 'products/edit' + + get 'products/update' + + get 'products/destroy' + # Merchants: get 'merchants/index' From 034269add489ea793ee3adea52230f7f355dce2e Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Fri, 20 Apr 2018 10:08:45 -0700 Subject: [PATCH 042/252] routes refactor --- app/controllers/products_controller.rb | 1 + config/routes.rb | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index ec9c0fd676..32d09dcabf 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,5 +1,6 @@ class ProductsController < ApplicationController before_action :find_product, only: [:show, :edit, :update, :destroy] + def root @products = Product.all end diff --git a/config/routes.rb b/config/routes.rb index 6ee521cace..ab4f83d5a9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,10 +1,21 @@ Rails.application.routes.draw do + # Products: + root 'products#root', as: 'root' - get '/login', to: 'sessions#new', as: 'login_form' - post '/login', to: 'sessions#create' - delete '/login', to: 'sessions#destroy', as: 'logout' + get 'products/index' + get 'products/:id', to: 'products#show', as: 'product' + + get 'products/new' + + get 'products/create' + + get 'products/edit' + + get 'products/update' + + get 'products/destroy' # Merchants: get 'merchants/index' From 32b064ee2bc91642937f2faee201cb03e9388157 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Fri, 20 Apr 2018 10:50:48 -0700 Subject: [PATCH 043/252] DRY routes --- config/routes.rb | 155 +++++++++++++++++++++++++---------------------- 1 file changed, 82 insertions(+), 73 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 1ae1f5fd4b..1b61f44a0e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,96 +1,105 @@ Rails.application.routes.draw do # Products: - root 'products#root', as: 'root' - - get 'products/index' - - get 'products/:id', to: 'products#show', as: 'product' - - get 'products/new' - - get 'products/create' - - get 'products/edit' - - get 'products/update' - - get 'products/destroy' + root 'products#root', as: 'homepage' + + resources :products do + resouces :reviews, only: [:new] + end + + # get 'products/index' + # + # get 'products/:id', to: 'products#show', as: 'product' + # + # get 'products/new' + # + # get 'products/create' + # + # get 'products/edit' + # + # get 'products/update' + # + # get 'products/destroy' # Merchants: - get 'merchants/index' - - get 'merchants/show' - - get 'merchants/new' - - get 'merchants/create' - - get 'merchants/edit' - - get 'merchants/update' - - get 'merchants/destroy' + resources :merchants + # get 'merchants/index' + # + # get 'merchants/show' + # + # get 'merchants/new' + # + # get 'merchants/create' + # + # get 'merchants/edit' + # + # get 'merchants/update' + # + # get 'merchants/destroy' # Sessions: get '/login', to: 'sessions#new', as: 'login_form' post '/login', to: 'sessions#create' delete '/login', to: 'sessions#destroy', as: 'logout' - get 'sessions/index' - - get 'sessions/show' + resources :sessions, only: [:index, :show] + # get 'sessions/index' + # + # get 'sessions/show' - get 'sessions/new' + # get 'sessions/new' - get 'sessions/create' + # get 'sessions/create' - get 'sessions/destroy' + # get 'sessions/destroy' # Reviews: - get 'reviews/index' - - get 'reviews/show' - - get 'reviews/new' - - get 'reviews/create' - - get 'reviews/update' - - get 'reviews/edit' - - get 'reviews/destroy' + resources :reviews + # get 'reviews/index' + # + # get 'reviews/show' + # + # get 'reviews/new' + # + # get 'reviews/create' + # + # get 'reviews/update' + # + # get 'reviews/edit' + # + # get 'reviews/destroy' # Categories: - get 'categories/index' - - get 'categories/show' - - get 'categories/new' - - get 'categories/create' - - get 'categories/update' - - get 'categories/edit' - - get 'categories/destroy' + resources :categories + # get 'categories/index' + # + # get 'categories/show' + # + # get 'categories/new' + # + # get 'categories/create' + # + # get 'categories/update' + # + # get 'categories/edit' + # + # get 'categories/destroy' # Orders: - get 'orders/index' - - get 'orders/show' - - get 'orders/new' - - get 'orders/create' - - get 'orders/update' - - get 'orders/edit' - - get 'orders/destroy' + resources :orders + # get 'orders/index' + # + # get 'orders/show' + # + # get 'orders/new' + # + # get 'orders/create' + # + # get 'orders/update' + # + # get 'orders/edit' + # + # get 'orders/destroy' # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end From add2ff7dfb52a3b58cb09b927770938b12c7a8fe Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Fri, 20 Apr 2018 10:58:15 -0700 Subject: [PATCH 044/252] nested routes --- config/routes.rb | 87 ++++-------------------------------------------- 1 file changed, 7 insertions(+), 80 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 1b61f44a0e..805183ce17 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,104 +2,31 @@ # Products: root 'products#root', as: 'homepage' - resources :products do - resouces :reviews, only: [:new] + # add orderproducts (cart#index) + resources :reviews, only: [:new] + resources :merchants, only: [:index] + resources :categories, only: [:index] end - # get 'products/index' - # - # get 'products/:id', to: 'products#show', as: 'product' - # - # get 'products/new' - # - # get 'products/create' - # - # get 'products/edit' - # - # get 'products/update' - # - # get 'products/destroy' - # Merchants: - resources :merchants - # get 'merchants/index' - # - # get 'merchants/show' - # - # get 'merchants/new' - # - # get 'merchants/create' - # - # get 'merchants/edit' - # - # get 'merchants/update' - # - # get 'merchants/destroy' + resources :merchants do + resources :products, only: [:index] + end # Sessions: get '/login', to: 'sessions#new', as: 'login_form' post '/login', to: 'sessions#create' delete '/login', to: 'sessions#destroy', as: 'logout' - resources :sessions, only: [:index, :show] - # get 'sessions/index' - # - # get 'sessions/show' - - # get 'sessions/new' - - # get 'sessions/create' - - # get 'sessions/destroy' # Reviews: resources :reviews - # get 'reviews/index' - # - # get 'reviews/show' - # - # get 'reviews/new' - # - # get 'reviews/create' - # - # get 'reviews/update' - # - # get 'reviews/edit' - # - # get 'reviews/destroy' # Categories: resources :categories - # get 'categories/index' - # - # get 'categories/show' - # - # get 'categories/new' - # - # get 'categories/create' - # - # get 'categories/update' - # - # get 'categories/edit' - # - # get 'categories/destroy' # Orders: resources :orders - # get 'orders/index' - # - # get 'orders/show' - # - # get 'orders/new' - # - # get 'orders/create' - # - # get 'orders/update' - # - # get 'orders/edit' - # - # get 'orders/destroy' - # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end From 3dc573efa58b2636da637f9e7dc5db007f968410 Mon Sep 17 00:00:00 2001 From: Aruna Date: Fri, 20 Apr 2018 11:36:26 -0700 Subject: [PATCH 045/252] removed category from product --- app/models/category.rb | 2 +- app/models/product.rb | 15 ++++++++++++--- config/routes.rb | 2 +- ...0183422_remove_column_category_from_product.rb | 5 +++++ db/schema.rb | 3 +-- db/seeds.rb | 7 ++++--- 6 files changed, 24 insertions(+), 10 deletions(-) create mode 100644 db/migrate/20180420183422_remove_column_category_from_product.rb diff --git a/app/models/category.rb b/app/models/category.rb index 74790501ed..4f4abd100c 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,5 +1,5 @@ class Category < ApplicationRecord - has_and_belongs_to_many :products + has_and_belongs_to_many :products, join_table: "category_product" validates :name, presence: true, uniqueness: true validates :name, length: { in: 1..25 } diff --git a/app/models/product.rb b/app/models/product.rb index c72dbf23a8..46e71cccc0 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,10 +1,19 @@ class Product < ApplicationRecord - has_and_belongs_to_many :orders, through: :orderproduct - has_and_belongs_to_many :categories, through: :categoryproduct + has_and_belongs_to_many :orders + has_and_belongs_to_many :categories, join_table: "category_product" has_many :reviews validates :name, presence: true, length: { minimum: 1 } - validates :category, presence: true, length: { minimum: 1 } + validate :has_atleast_one_category validates_numericality_of :quantity, presence: true, greater_than_or_equal_to: 0 validates_numericality_of :price, presence: true, greater_than_or_equal_to: 0 + + + private + def has_atleast_one_category + + if categories.empty? + errors.add(:categories, "must have atleat one category") + end + end end diff --git a/config/routes.rb b/config/routes.rb index badc48acb2..4611577bb4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,6 @@ Rails.application.routes.draw do - + #sessions get '/login', to: 'sessions#new', as: 'login_form' post '/login', to: 'sessions#create' delete '/login', to: 'sessions#destroy', as: 'logout' diff --git a/db/migrate/20180420183422_remove_column_category_from_product.rb b/db/migrate/20180420183422_remove_column_category_from_product.rb new file mode 100644 index 0000000000..bd82814e74 --- /dev/null +++ b/db/migrate/20180420183422_remove_column_category_from_product.rb @@ -0,0 +1,5 @@ +class RemoveColumnCategoryFromProduct < ActiveRecord::Migration[5.1] + def change + remove_column :products, :category + end +end diff --git a/db/schema.rb b/db/schema.rb index 77b0ab3735..e3710fd8e0 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: 20180419220012) do +ActiveRecord::Schema.define(version: 20180420183422) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -63,7 +63,6 @@ create_table "products", force: :cascade do |t| t.string "name" t.integer "price" - t.string "category" t.integer "quantity" t.datetime "created_at", null: false t.datetime "updated_at", null: false diff --git a/db/seeds.rb b/db/seeds.rb index 9b8c49b6b0..8f22efeb0c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -9,12 +9,13 @@ require 'faker' -category = Category.new(name: "Dessert") +category = Category.create!(name: "Dessert") + 20.times do |t| - product = Product.create(name: Faker::Dessert.variety, price: 1, category: category , quantity: 2 ) + product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [category] , quantity: 2 ) puts "#{product.name} created!" - # puts " category: #{product.category.name}" + puts " category: #{product.categories.first.name}" end p "Created #{Product.count} desserts" From 201a2defedefa71dc35744530aa67b4617759c00 Mon Sep 17 00:00:00 2001 From: Aruna Date: Fri, 20 Apr 2018 11:43:43 -0700 Subject: [PATCH 046/252] added orderproduct model --- app/models/orderproduct.rb | 2 ++ config/routes.rb | 13 ------------- db/migrate/20180420184237_create_orderproducts.rb | 9 +++++++++ db/schema.rb | 8 +++++++- test/fixtures/orderproducts.yml | 7 +++++++ test/models/orderproduct_test.rb | 9 +++++++++ 6 files changed, 34 insertions(+), 14 deletions(-) create mode 100644 app/models/orderproduct.rb create mode 100644 db/migrate/20180420184237_create_orderproducts.rb create mode 100644 test/fixtures/orderproducts.yml create mode 100644 test/models/orderproduct_test.rb diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb new file mode 100644 index 0000000000..1361f4af6b --- /dev/null +++ b/app/models/orderproduct.rb @@ -0,0 +1,2 @@ +class Orderproduct < ApplicationRecord +end diff --git a/config/routes.rb b/config/routes.rb index 448a29035c..6baf251eb6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -37,20 +37,7 @@ get 'merchants/destroy' - # Sessions: - get '/login', to: 'sessions#new', as: 'login_form' - post '/login', to: 'sessions#create' - delete '/login', to: 'sessions#destroy', as: 'logout' - - get 'sessions/index' - - get 'sessions/show' - - get 'sessions/new' - - get 'sessions/create' - get 'sessions/destroy' # Reviews: get 'reviews/index' diff --git a/db/migrate/20180420184237_create_orderproducts.rb b/db/migrate/20180420184237_create_orderproducts.rb new file mode 100644 index 0000000000..e2384e944f --- /dev/null +++ b/db/migrate/20180420184237_create_orderproducts.rb @@ -0,0 +1,9 @@ +class CreateOrderproducts < ActiveRecord::Migration[5.1] + def change + create_table :orderproducts do |t| + t.integer :quantity + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index e3710fd8e0..809ca5315a 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: 20180420183422) do +ActiveRecord::Schema.define(version: 20180420184237) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -44,6 +44,12 @@ t.index ["product_id"], name: "index_order_product_on_product_id" end + create_table "orderproducts", force: :cascade do |t| + t.integer "quantity" + 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 "email" diff --git a/test/fixtures/orderproducts.yml b/test/fixtures/orderproducts.yml new file mode 100644 index 0000000000..6609c00aa6 --- /dev/null +++ b/test/fixtures/orderproducts.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/models/orderproduct_test.rb b/test/models/orderproduct_test.rb new file mode 100644 index 0000000000..0e29f8e9af --- /dev/null +++ b/test/models/orderproduct_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe Orderproduct do + let(:orderproduct) { Orderproduct.new } + + it "must be valid" do + value(orderproduct).must_be :valid? + end +end From 0312f56064065f8c1ce10d170d800e9e095e9ba8 Mon Sep 17 00:00:00 2001 From: Aruna Date: Fri, 20 Apr 2018 12:00:39 -0700 Subject: [PATCH 047/252] added relationship for orderproducts --- app/models/order.rb | 2 +- app/models/orderproduct.rb | 3 +++ app/models/product.rb | 4 ++-- config/routes.rb | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/models/order.rb b/app/models/order.rb index 9ce76c3345..99dc779fdf 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,6 +1,6 @@ class Order < ApplicationRecord VALID_EMAIL = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i - has_and_belongs_to_many :products, through: :orderproduct + has_many :products, through: :orderproduct validates :address, presence: true, length: { in: 1..35 } validates :card_name, presence: true, length: { minimum: 1 } diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index 1361f4af6b..0265ffdc7d 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -1,2 +1,5 @@ class Orderproduct < ApplicationRecord + belongs_to :order + belongs_to :product + end diff --git a/app/models/product.rb b/app/models/product.rb index 46e71cccc0..0269c60c5f 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,5 +1,5 @@ class Product < ApplicationRecord - has_and_belongs_to_many :orders + has_many :orders,through: :orderproduct has_and_belongs_to_many :categories, join_table: "category_product" has_many :reviews @@ -11,7 +11,7 @@ class Product < ApplicationRecord private def has_atleast_one_category - + if categories.empty? errors.add(:categories, "must have atleat one category") end diff --git a/config/routes.rb b/config/routes.rb index 6bf36fc28c..9adc60139b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,8 +9,8 @@ root 'products#root', as: 'homepage' resources :products do # add orderproducts (cart#index) - resources :reviews, only: [:new] - resources :merchants, only: [:index] + #resources :reviews, only: [:new] + #resources :merchants, only: [:index] resources :categories, only: [:index] end From 41d837cd01b5a93b3c2ad5031b8738c12a1ee51a Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 12:19:13 -0700 Subject: [PATCH 048/252] Merged --- config/routes.rb | 4 ++-- db/schema.rb | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 6bf36fc28c..29a46d66d1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,8 +9,8 @@ root 'products#root', as: 'homepage' resources :products do # add orderproducts (cart#index) - resources :reviews, only: [:new] - resources :merchants, only: [:index] + # resources :reviews, only: [:new] + # resources :merchants, only: [:index] resources :categories, only: [:index] end diff --git a/db/schema.rb b/db/schema.rb index 809ca5315a..384cd6fc18 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -30,6 +30,11 @@ t.index ["product_id"], name: "index_category_product_on_product_id" end + create_table "categoryproducts", force: :cascade do |t| + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "merchants", force: :cascade do |t| t.string "username" t.string "email" From 085c64346ff2fd892fd5ee4bcbc23f731f2689d1 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 12:54:27 -0700 Subject: [PATCH 049/252] Added missing end of categories class --- app/controllers/categories_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index b33b06b653..1c93ad70a7 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -33,3 +33,4 @@ def category_params def find_category @category = Category.find_by(id: params[:id]) end +end From 2279fb33328d4cd985b1e6e4d4e84c197f4a45e2 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Fri, 20 Apr 2018 14:45:31 -0700 Subject: [PATCH 050/252] 2 errors with model relationships, rest of tests pass --- app/controllers/categories_controller.rb | 1 + app/models/category.rb | 3 +- app/models/order.rb | 2 +- app/models/orderproduct.rb | 1 - app/models/product.rb | 9 +++--- ...420210148_add_order_id_to_orderproducts.rb | 5 +++ ...0210248_add_product_id_to_orderproducts.rb | 5 +++ ...20210623_add_order_id_to_orderproducts2.rb | 5 +++ db/schema.rb | 11 ++++++- test/fixtures/products.yml | 2 -- test/models/category_test.rb | 6 ++-- test/models/order_test.rb | 4 +-- test/models/orderproduct_test.rb | 4 +-- test/models/product_test.rb | 31 +++++++------------ 14 files changed, 50 insertions(+), 39 deletions(-) create mode 100644 db/migrate/20180420210148_add_order_id_to_orderproducts.rb create mode 100644 db/migrate/20180420210248_add_product_id_to_orderproducts.rb create mode 100644 db/migrate/20180420210623_add_order_id_to_orderproducts2.rb diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index b33b06b653..1c93ad70a7 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -33,3 +33,4 @@ def category_params def find_category @category = Category.find_by(id: params[:id]) end +end diff --git a/app/models/category.rb b/app/models/category.rb index 4f4abd100c..4dd25c942d 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,6 +1,5 @@ class Category < ApplicationRecord has_and_belongs_to_many :products, join_table: "category_product" - validates :name, presence: true, uniqueness: true - validates :name, length: { in: 1..25 } + validates :name, presence: true, uniqueness: true, length: { in: 1..25 } end diff --git a/app/models/order.rb b/app/models/order.rb index 99dc779fdf..c62bb1a0b2 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,6 +1,6 @@ class Order < ApplicationRecord VALID_EMAIL = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i - has_many :products, through: :orderproduct + has_many :products, through: :orderproducts validates :address, presence: true, length: { in: 1..35 } validates :card_name, presence: true, length: { minimum: 1 } diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index 0265ffdc7d..2be353fe43 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -1,5 +1,4 @@ class Orderproduct < ApplicationRecord belongs_to :order belongs_to :product - end diff --git a/app/models/product.rb b/app/models/product.rb index 0269c60c5f..29b70256e5 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,19 +1,18 @@ class Product < ApplicationRecord - has_many :orders,through: :orderproduct + has_many :orders, through: :orderproducts has_and_belongs_to_many :categories, join_table: "category_product" has_many :reviews validates :name, presence: true, length: { minimum: 1 } - validate :has_atleast_one_category + validate :has_at_least_one_category validates_numericality_of :quantity, presence: true, greater_than_or_equal_to: 0 validates_numericality_of :price, presence: true, greater_than_or_equal_to: 0 private - def has_atleast_one_category - + def has_at_least_one_category if categories.empty? - errors.add(:categories, "must have atleat one category") + errors.add(:categories, "must have at_least one category") end end end diff --git a/db/migrate/20180420210148_add_order_id_to_orderproducts.rb b/db/migrate/20180420210148_add_order_id_to_orderproducts.rb new file mode 100644 index 0000000000..d98807c476 --- /dev/null +++ b/db/migrate/20180420210148_add_order_id_to_orderproducts.rb @@ -0,0 +1,5 @@ +class AddOrderIdToOrderproducts < ActiveRecord::Migration[5.1] + def change + add_reference :orderproducts, :order, foreign_key: true + end +end diff --git a/db/migrate/20180420210248_add_product_id_to_orderproducts.rb b/db/migrate/20180420210248_add_product_id_to_orderproducts.rb new file mode 100644 index 0000000000..a51f692f6a --- /dev/null +++ b/db/migrate/20180420210248_add_product_id_to_orderproducts.rb @@ -0,0 +1,5 @@ +class AddProductIdToOrderproducts < ActiveRecord::Migration[5.1] + def change + add_reference :orderproducts, :product, foreign_key: true + end +end diff --git a/db/migrate/20180420210623_add_order_id_to_orderproducts2.rb b/db/migrate/20180420210623_add_order_id_to_orderproducts2.rb new file mode 100644 index 0000000000..6da40d990c --- /dev/null +++ b/db/migrate/20180420210623_add_order_id_to_orderproducts2.rb @@ -0,0 +1,5 @@ +class AddOrderIdToOrderproducts2 < ActiveRecord::Migration[5.1] + def change + add_reference :orderproducts, :order, foreign_key: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 809ca5315a..c0115bdc77 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: 20180420184237) do +ActiveRecord::Schema.define(version: 20180420210623) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -48,6 +48,10 @@ 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_orderproducts_on_order_id" + t.index ["product_id"], name: "index_orderproducts_on_product_id" end create_table "orders", force: :cascade do |t| @@ -73,6 +77,8 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "description" + t.bigint "order_id" + t.index ["order_id"], name: "index_products_on_order_id" end create_table "reviews", force: :cascade do |t| @@ -85,6 +91,9 @@ end add_foreign_key "categories", "products" + add_foreign_key "orderproducts", "orders" + add_foreign_key "orderproducts", "products" add_foreign_key "orders", "products" + add_foreign_key "products", "orders" add_foreign_key "reviews", "products" end diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index 523f73b4af..9af4a54fa9 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -3,11 +3,9 @@ candy: name: Candy price: 10 - category: candy quantity: 1 two: name: MyString price: 1 - category: MyString quantity: 1 diff --git a/test/models/category_test.rb b/test/models/category_test.rb index 9a2de957d1..3e0b478ab3 100644 --- a/test/models/category_test.rb +++ b/test/models/category_test.rb @@ -1,7 +1,7 @@ require "test_helper" describe Category do - let(:category) { Category.new name: "candy", product_id: (Product.create name: "thing", category: "choco", quantity: 2).id } + let(:category) { Category.new name: "candy", product_id: (Product.create name: "thing", quantity: 2).id } describe "validations" do it "must be valid" do @@ -15,14 +15,14 @@ category.errors.must_include :name end - it 'must have at least one character' do + it 'name must have at least one character' do category.name = "" category.valid?.must_equal false category.errors.must_include :name end - it 'cannot have more than 25 characters' do + it 'name cannot have more than 25 characters' do category.name = "12345678901234567890123456" category.valid?.must_equal false diff --git a/test/models/order_test.rb b/test/models/order_test.rb index 8999dfc53d..982efcb704 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -194,9 +194,7 @@ it "has a list of products" do order.must_respond_to :products - order.products.each do |product| - product.must_be_kind_of Product - end + order.products.last.must_be_kind_of Product end end diff --git a/test/models/orderproduct_test.rb b/test/models/orderproduct_test.rb index 0e29f8e9af..15df580e81 100644 --- a/test/models/orderproduct_test.rb +++ b/test/models/orderproduct_test.rb @@ -1,9 +1,9 @@ require "test_helper" describe Orderproduct do - let(:orderproduct) { Orderproduct.new } + let(:orderproduct) { Orderproduct.new quantity: 2, product_id: Product.first.id, order_id: Order.first.id } it "must be valid" do - value(orderproduct).must_be :valid? + orderproduct.must_be :valid? end end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index 1272776888..ba8a6db67d 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -1,13 +1,20 @@ require "test_helper" describe Product do - let(:product) { Product.new name: "thing", price: 1, category: "red", quantity: 2 } + let(:product) { Product.new name: "thing", price: 1, quantity: 2, categories: [Category.first, Category.last] } describe 'Validations' do it "must be valid" do product.must_be :valid? end + it "must have at least one category" do + product.categories.delete_all + + product.valid?.must_equal false + product.errors.must_include :categories + end + it "must have a name" do product.name = nil @@ -22,20 +29,6 @@ product.errors.must_include :name end - it "must have a category" do - product.category = nil - - product.valid?.must_equal false - product.errors.must_include :category - end - - it "must have category length greater than zero" do - product.category = "" - - product.valid?.must_equal false - product.errors.must_include :category - end - it "must have a quantity" do product.quantity = nil @@ -84,10 +77,10 @@ it "has a list of reviews" do product.must_respond_to :reviews - - product.reviews.each do |review| - review.must_be_kind_of Review - end + + # product.reviews.each do |review| + # review.must_be_kind_of Review + # end end end From 304fb0746f00b3752f91ba173aadae4ce255f976 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 14:50:38 -0700 Subject: [PATCH 051/252] Working on nav-bar --- app/assets/images/candy-icon.jpg | Bin 0 -> 74097 bytes app/controllers/categories_controller.rb | 2 +- app/views/layouts/application.html.erb | 54 ++++++++++++++++++----- 3 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 app/assets/images/candy-icon.jpg diff --git a/app/assets/images/candy-icon.jpg b/app/assets/images/candy-icon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ceaeef39f11cdc896d005a25bfdf1f74088c7068 GIT binary patch literal 74097 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%0AnuJ2K3w4=@4?KWG3GlI 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 literal 0 HcmV?d00001 diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 1c93ad70a7..27821ff5d8 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -1,5 +1,5 @@ class CategoriesController < ApplicationController - before_action :find_book, only: [:show, :edit, :update, :destroy] + before_action :find_category, only: [:show, :edit, :update, :destroy] def index @categories = Category.all diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index cd60004891..4951dacee7 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,19 +1,51 @@ - - - + + + - <%= content_for?(:title) ? yield(:title) : "Untitled" %> + <%= content_for?(:title) ? yield(:title) : "Yummsy!" %> - <%= stylesheet_link_tag "application" %> - <%= javascript_include_tag "application", 'data-turbolinks-track' => true %> - <%= csrf_meta_tags %> - + <%= stylesheet_link_tag "application" %> + <%= javascript_include_tag "application", 'data-turbolinks-track' => true %> + <%= csrf_meta_tags %> + - + + + + + <%= yield %> + + From 318cdd50046f278f74fcec3c78c9ef348d6e6d4d Mon Sep 17 00:00:00 2001 From: Aruna Date: Fri, 20 Apr 2018 14:50:42 -0700 Subject: [PATCH 052/252] added some methods to orderproducts controller --- app/assets/javascripts/orderproducts.js | 2 + app/assets/stylesheets/orderproducts.scss | 3 + app/controllers/orderproducts_controller.rb | 73 +++++++++++++++++++ app/helpers/orderproducts_helper.rb | 2 + app/views/orderproducts/create.html.erb | 2 + app/views/orderproducts/destroy.html.erb | 2 + app/views/orderproducts/edit.html.erb | 2 + app/views/orderproducts/index.html.erb | 0 app/views/orderproducts/new.html.erb | 2 + app/views/orderproducts/show.html.erb | 2 + app/views/orderproducts/update.html.erb | 2 + config/routes.rb | 2 + .../orderproducts_controller_test.rb | 39 ++++++++++ 13 files changed, 133 insertions(+) create mode 100644 app/assets/javascripts/orderproducts.js create mode 100644 app/assets/stylesheets/orderproducts.scss create mode 100644 app/controllers/orderproducts_controller.rb create mode 100644 app/helpers/orderproducts_helper.rb create mode 100644 app/views/orderproducts/create.html.erb create mode 100644 app/views/orderproducts/destroy.html.erb create mode 100644 app/views/orderproducts/edit.html.erb create mode 100644 app/views/orderproducts/index.html.erb create mode 100644 app/views/orderproducts/new.html.erb create mode 100644 app/views/orderproducts/show.html.erb create mode 100644 app/views/orderproducts/update.html.erb create mode 100644 test/controllers/orderproducts_controller_test.rb diff --git a/app/assets/javascripts/orderproducts.js b/app/assets/javascripts/orderproducts.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/orderproducts.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/orderproducts.scss b/app/assets/stylesheets/orderproducts.scss new file mode 100644 index 0000000000..0dc6e76eaa --- /dev/null +++ b/app/assets/stylesheets/orderproducts.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the orderproducts controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb new file mode 100644 index 0000000000..652921451f --- /dev/null +++ b/app/controllers/orderproducts_controller.rb @@ -0,0 +1,73 @@ +class OrderproductsController < ApplicationController + before_action :find_orderproduct, only: [:edit, :update, :destroy] + + def index + @orderproducts = Orderproduct.all + end + + def show + end + + def create + + if @order.nil? + @order = Order.create(status: "pending") + end + @op = @order.orderproducts.find_by(product_id: params[:id]) + if @op + @op.quantity += params[:orderproduct][:quantity].to_i + else + @op = Orderproduct.new(orderproduct_params) + @op.product_id = params[:id] + end + if @op.save + flash[:status] = :success + flash[:result_text] = "Successfully added to cart" + redirect_to product_path(params[:id]) + else + flash[:status] = :failure + flash[:result_text] = "Sorry" + flash[:messages] = @op.errors.messages + redirect_to product_path(params[:id]), status: :bad_request + end + end + + def new + end + + def edit + end + + def update + if @orderproduct.update(orderproduct_params) + flash[:status] = :success + flash[:result_text] = "Cart updated" + redirect_to orders_path + else + flash.now[:status] = :failure + flash.now[:result_text] = "Cart could not be updated" + flash.now[:messages] = @orderproduct.errors.messages + render :edit + end + end + + def destroy + order = @orderproduct.order + @orderproduct.destroy + if order.orderproducts.empty? + order.destroy + end + flash[:status] = :success + flash[:result_text] = "Successfully removed from your cart!" + redirect_to orders_path + end + + + private + def orderproduct_params + params.require(:order_product).permit(:quantity) + end + def find_orderproduct + @order_product = Orderproduct.find_by(:id params[:id]) + end +end diff --git a/app/helpers/orderproducts_helper.rb b/app/helpers/orderproducts_helper.rb new file mode 100644 index 0000000000..9ec91f4e16 --- /dev/null +++ b/app/helpers/orderproducts_helper.rb @@ -0,0 +1,2 @@ +module OrderproductsHelper +end diff --git a/app/views/orderproducts/create.html.erb b/app/views/orderproducts/create.html.erb new file mode 100644 index 0000000000..23119b1e7e --- /dev/null +++ b/app/views/orderproducts/create.html.erb @@ -0,0 +1,2 @@ +

Orderproducts#create

+

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

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

Orderproducts#destroy

+

Find me in app/views/orderproducts/destroy.html.erb

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

Orderproducts#edit

+

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

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

Orderproducts#new

+

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

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

Orderproducts#show

+

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

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

Orderproducts#update

+

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

diff --git a/config/routes.rb b/config/routes.rb index 9adc60139b..0772282627 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,7 @@ Rails.application.routes.draw do + resources :orderproducts + #sessions get '/login', to: 'sessions#new', as: 'login_form' post '/login', to: 'sessions#create' diff --git a/test/controllers/orderproducts_controller_test.rb b/test/controllers/orderproducts_controller_test.rb new file mode 100644 index 0000000000..fd5705f4d1 --- /dev/null +++ b/test/controllers/orderproducts_controller_test.rb @@ -0,0 +1,39 @@ +require "test_helper" + +describe OrderproductsController do + it "should get index" do + get orderproducts_index_url + value(response).must_be :success? + end + + it "should get show" do + get orderproducts_show_url + value(response).must_be :success? + end + + it "should get create" do + get orderproducts_create_url + value(response).must_be :success? + end + + it "should get new" do + get orderproducts_new_url + value(response).must_be :success? + end + + it "should get edit" do + get orderproducts_edit_url + value(response).must_be :success? + end + + it "should get update" do + get orderproducts_update_url + value(response).must_be :success? + end + + it "should get destroy" do + get orderproducts_destroy_url + value(response).must_be :success? + end + +end From a7712a7dddb5040f77d3fe0ddbd3030c535b0638 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 15:13:54 -0700 Subject: [PATCH 053/252] Deleted duplicate migration --- db/migrate/20180420210623_add_order_id_to_orderproducts2.rb | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 db/migrate/20180420210623_add_order_id_to_orderproducts2.rb diff --git a/db/migrate/20180420210623_add_order_id_to_orderproducts2.rb b/db/migrate/20180420210623_add_order_id_to_orderproducts2.rb deleted file mode 100644 index 6da40d990c..0000000000 --- a/db/migrate/20180420210623_add_order_id_to_orderproducts2.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddOrderIdToOrderproducts2 < ActiveRecord::Migration[5.1] - def change - add_reference :orderproducts, :order, foreign_key: true - end -end From ab665465e362d421918beeee14cb9a9a5052c8c4 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Fri, 20 Apr 2018 15:22:31 -0700 Subject: [PATCH 054/252] fixed order and products relations with orderproducts --- app/models/order.rb | 1 + app/models/product.rb | 1 + test/models/order_test.rb | 4 +++- test/models/product_test.rb | 6 +++--- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/models/order.rb b/app/models/order.rb index c62bb1a0b2..35549034f9 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,5 +1,6 @@ class Order < ApplicationRecord VALID_EMAIL = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i + has_many :orderproducts has_many :products, through: :orderproducts validates :address, presence: true, length: { in: 1..35 } diff --git a/app/models/product.rb b/app/models/product.rb index 29b70256e5..9e5dad563a 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,4 +1,5 @@ class Product < ApplicationRecord + has_many :orderproducts has_many :orders, through: :orderproducts has_and_belongs_to_many :categories, join_table: "category_product" has_many :reviews diff --git a/test/models/order_test.rb b/test/models/order_test.rb index 982efcb704..8999dfc53d 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -194,7 +194,9 @@ it "has a list of products" do order.must_respond_to :products - order.products.last.must_be_kind_of Product + order.products.each do |product| + product.must_be_kind_of Product + end end end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index ba8a6db67d..74716c3331 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -78,9 +78,9 @@ it "has a list of reviews" do product.must_respond_to :reviews - # product.reviews.each do |review| - # review.must_be_kind_of Review - # end + product.reviews.each do |review| + review.must_be_kind_of Review + end end end From e9d7a61199b9bae2e988c91a65c6db90707c1ba1 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 15:32:28 -0700 Subject: [PATCH 055/252] added rout for cart. --- app/controllers/orderproducts_controller.rb | 2 +- app/views/layouts/application.html.erb | 2 +- app/views/orderproducts/index.html.erb | 1 + config/routes.rb | 2 ++ 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 652921451f..34886b7329 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -68,6 +68,6 @@ def orderproduct_params params.require(:order_product).permit(:quantity) end def find_orderproduct - @order_product = Orderproduct.find_by(:id params[:id]) + @order_product = Orderproduct.find_by(params[:id]) end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 4951dacee7..44c082165f 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -37,7 +37,7 @@ <%= link_to "Log In", login_path, class: "button" %> <% end %> - <%= link_to "Cart", homepage_path, class: "button" %> + <%= link_to "Cart", cart_path, class: "button" %> diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index e69de29bb2..88a61e710e 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -0,0 +1 @@ +Cart diff --git a/config/routes.rb b/config/routes.rb index 648a4a46f7..ba6a067915 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -7,6 +7,8 @@ post '/login', to: 'sessions#create' delete '/login', to: 'sessions#destroy', as: 'logout' + get '/cart', to:'orderproducts#index', as: 'cart' + # Products: root 'products#root', as: 'homepage' resources :products do From 8fe7a42a068de4471b2419f67892157c19603674 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Fri, 20 Apr 2018 15:33:48 -0700 Subject: [PATCH 056/252] join table order_product dropped --- db/migrate/20180420223006_drop_op_join.rb | 5 +++++ db/schema.rb | 14 +------------- 2 files changed, 6 insertions(+), 13 deletions(-) create mode 100644 db/migrate/20180420223006_drop_op_join.rb diff --git a/db/migrate/20180420223006_drop_op_join.rb b/db/migrate/20180420223006_drop_op_join.rb new file mode 100644 index 0000000000..132d6216e4 --- /dev/null +++ b/db/migrate/20180420223006_drop_op_join.rb @@ -0,0 +1,5 @@ +class DropOpJoin < ActiveRecord::Migration[5.1] + def change + drop_join_table :order, :product + end +end diff --git a/db/schema.rb b/db/schema.rb index 8490c03fc4..2ec08c9e8d 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: 20180420210623) do +ActiveRecord::Schema.define(version: 20180420223006) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -30,11 +30,6 @@ t.index ["product_id"], name: "index_category_product_on_product_id" end - create_table "categoryproducts", force: :cascade do |t| - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - create_table "merchants", force: :cascade do |t| t.string "username" t.string "email" @@ -42,13 +37,6 @@ t.datetime "updated_at", null: false end - create_table "order_product", force: :cascade do |t| - t.bigint "order_id" - t.bigint "product_id" - t.index ["order_id"], name: "index_order_product_on_order_id" - t.index ["product_id"], name: "index_order_product_on_product_id" - end - create_table "orderproducts", force: :cascade do |t| t.integer "quantity" t.datetime "created_at", null: false From 894f6eeffb48521d93e92a58f63aa61167d597d0 Mon Sep 17 00:00:00 2001 From: Aruna Date: Fri, 20 Apr 2018 15:39:00 -0700 Subject: [PATCH 057/252] added index page for product and category --- app/views/categories/index.html.erb | 10 ++++++++-- app/views/products/index.html.erb | 10 ++++++++-- db/schema.rb | 12 ++---------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index a5d0d54736..e91b591221 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -1,2 +1,8 @@ -

Categories#index

-

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

+< +
+
    + <% @categories.each do |category|%> +
  • <%= link_to categories.name, categories_path(category.id) %>
  • + <% end %> +
+
diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index f8eeb82674..b8b67245c9 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,2 +1,8 @@ -

Products#index

-

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

+ +
+
    + <% @products.each do |product|%> +
  • <%= link_to product.name, product_path(product.id) %>
  • + <% end %> +
+
diff --git a/db/schema.rb b/db/schema.rb index 8490c03fc4..b955b5bff8 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: 20180420210623) do +ActiveRecord::Schema.define(version: 20180420210248) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -30,11 +30,6 @@ t.index ["product_id"], name: "index_category_product_on_product_id" end - create_table "categoryproducts", force: :cascade do |t| - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - create_table "merchants", force: :cascade do |t| t.string "username" t.string "email" @@ -53,8 +48,8 @@ t.integer "quantity" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.bigint "product_id" t.bigint "order_id" + t.bigint "product_id" t.index ["order_id"], name: "index_orderproducts_on_order_id" t.index ["product_id"], name: "index_orderproducts_on_product_id" end @@ -82,8 +77,6 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "description" - t.bigint "order_id" - t.index ["order_id"], name: "index_products_on_order_id" end create_table "reviews", force: :cascade do |t| @@ -99,6 +92,5 @@ add_foreign_key "orderproducts", "orders" add_foreign_key "orderproducts", "products" add_foreign_key "orders", "products" - add_foreign_key "products", "orders" add_foreign_key "reviews", "products" end From cca6e7dbc07f49ef2589592d270a9d52c44d16ba Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 16:28:05 -0700 Subject: [PATCH 058/252] Started form for reviews. --- app/controllers/reviews_controller.rb | 1 + app/views/products/_review_form.html.erb | 12 ++++++++++++ app/views/products/show.html.erb | 3 +-- 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 app/views/products/_review_form.html.erb diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index ca17a05e1b..854a8b6b51 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -6,6 +6,7 @@ def index end def show + @reviews = Review end def new diff --git a/app/views/products/_review_form.html.erb b/app/views/products/_review_form.html.erb new file mode 100644 index 0000000000..16cd361d66 --- /dev/null +++ b/app/views/products/_review_form.html.erb @@ -0,0 +1,12 @@ +
+ <%= form_for @orderproducts do |f| %> + + <%= f.label :rating %> + <%= f.text_field :rating %> + + <%= f.label :comment %> + <%= f.text_area :comment %> + + <%= f.submit class: "button" %> + <% end %> +
diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 5f44ec44d2..adfb2c8fa8 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,2 +1 @@ -

Products#show

-

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

+<%= render partial: "review_form" %> From d2191b63c6bd2228ff48a126f1e95210bc5b4208 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Fri, 20 Apr 2018 16:39:14 -0700 Subject: [PATCH 059/252] add merchant_id to products, updated references --- app/controllers/merchants_controller.rb | 2 +- app/models/product.rb | 1 + app/views/layouts/application.html.erb | 63 ++++++++++--------- app/views/products/root.html.erb | 5 ++ ...180420233543_add_merchant_id_to_product.rb | 5 ++ db/schema.rb | 5 +- 6 files changed, 49 insertions(+), 32 deletions(-) create mode 100644 db/migrate/20180420233543_add_merchant_id_to_product.rb diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 1dc89e2b59..81b413a033 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -31,6 +31,6 @@ def merchant_params end def find_merchant - @merchant = Merchant.find_by(:id params[:id]) + @merchant = Merchant.find_by(id: params[:id]) end end diff --git a/app/models/product.rb b/app/models/product.rb index 9e5dad563a..bdb36f63e3 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -3,6 +3,7 @@ class Product < ApplicationRecord has_many :orders, through: :orderproducts has_and_belongs_to_many :categories, join_table: "category_product" has_many :reviews + belongs_to :merchant validates :name, presence: true, length: { minimum: 1 } validate :has_at_least_one_category diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 44c082165f..abec10101a 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -4,7 +4,7 @@ - <%= content_for?(:title) ? yield(:title) : "Yummsy!" %> + <%= content_for?(:title) ? yield(:title) : "Sweetsy!" %> <%= stylesheet_link_tag "application" %> <%= javascript_include_tag "application", 'data-turbolinks-track' => true %> @@ -12,35 +12,38 @@ diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index 2ead10c97a..02a1202fb6 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -8,3 +8,8 @@ <% end %> + diff --git a/db/migrate/20180420233543_add_merchant_id_to_product.rb b/db/migrate/20180420233543_add_merchant_id_to_product.rb new file mode 100644 index 0000000000..ea6eb433b3 --- /dev/null +++ b/db/migrate/20180420233543_add_merchant_id_to_product.rb @@ -0,0 +1,5 @@ +class AddMerchantIdToProduct < ActiveRecord::Migration[5.1] + def change + add_reference :products, :merchant, foreign_key: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 2ec08c9e8d..bc832008d1 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: 20180420223006) do +ActiveRecord::Schema.define(version: 20180420233543) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -71,6 +71,8 @@ t.datetime "updated_at", null: false t.string "description" t.bigint "order_id" + t.bigint "merchant_id" + t.index ["merchant_id"], name: "index_products_on_merchant_id" t.index ["order_id"], name: "index_products_on_order_id" end @@ -87,6 +89,7 @@ add_foreign_key "orderproducts", "orders" add_foreign_key "orderproducts", "products" add_foreign_key "orders", "products" + add_foreign_key "products", "merchants" add_foreign_key "products", "orders" add_foreign_key "reviews", "products" end From 6cadee9668d8d26130f21c3cc4453ac926e9938f Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Fri, 20 Apr 2018 16:42:02 -0700 Subject: [PATCH 060/252] fussing with views --- app/views/layouts/application.html.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index abec10101a..0549abd577 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -16,9 +16,9 @@ -
Link Dropdown »> +
<%= link_to "View all products", products_path, class: "button" %> -
From d4c17f19d20de6f30064ebadebd3c3679b5d3da4 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 16:45:31 -0700 Subject: [PATCH 061/252] Created more seeds for Merchants and Categories - Change later. --- app/views/products/_review_form.html.erb | 12 ++++++++++ db/seeds.rb | 29 ++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 app/views/products/_review_form.html.erb diff --git a/app/views/products/_review_form.html.erb b/app/views/products/_review_form.html.erb new file mode 100644 index 0000000000..16cd361d66 --- /dev/null +++ b/app/views/products/_review_form.html.erb @@ -0,0 +1,12 @@ +
+ <%= form_for @orderproducts do |f| %> + + <%= f.label :rating %> + <%= f.text_field :rating %> + + <%= f.label :comment %> + <%= f.text_area :comment %> + + <%= f.submit class: "button" %> + <% end %> +
diff --git a/db/seeds.rb b/db/seeds.rb index 8f22efeb0c..a3ad8e5341 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -9,13 +9,38 @@ require 'faker' -category = Category.create!(name: "Dessert") +# Categories: + category = Category.create!(name: "Caramel") + puts "#{category.name} created!" + category = Category.create!(name: "Gummy") + puts "#{category.name} created!" + category = Category.create!(name: "Cakes") + puts "#{category.name} created!" + + category = Category.create!(name: Faker::Dessert.topping) + puts "#{category.name} created!" + + category = Category.create!(name: Faker::Dessert.topping) + puts "#{category.name} created!" +p "Created #{Category.count} categories" + + +# Products 20.times do |t| - product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [category] , quantity: 2 ) + product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.first] , quantity: 2 ) puts "#{product.name} created!" puts " category: #{product.categories.first.name}" end p "Created #{Product.count} desserts" + + +# Mercahnts +5.times do |t| + merchant = Merchant.create!(username: Faker::Name.name, email: Faker::Internet.email ) + puts "#{merchant.username} created!" +end + +p "Created #{Merchant.count} merchants" From 001988ccdeaba1d8a70e97c2cdbe5eead601d485 Mon Sep 17 00:00:00 2001 From: Aruna Date: Fri, 20 Apr 2018 16:45:34 -0700 Subject: [PATCH 062/252] added product show view --- app/controllers/categories_controller.rb | 1 + app/views/products/show.html.erb | 38 ++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index b33b06b653..1c93ad70a7 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -33,3 +33,4 @@ def category_params def find_category @category = Category.find_by(id: params[:id]) end +end diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 5f44ec44d2..9b3824c4b5 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,2 +1,36 @@ -

Products#show

-

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

+

Product Details

+ + +
+ <%= "Product : #{@product.name}" %> + +

<%= "Price:#{ @product.price}" %> + +

<%= "Stock: #{@product.quantity}" %>

+
+<%= form_for @orderproduct do |f| %> + <%= f.label :quantity %> + <%= f.select :quantity, options_for_select(1..10)%> + <%= f.submit "Add to Cart", class: "button" %> + <% end %> +
+

<%="Description:#{@product.description}" %> +

+ +
+ <%= button_to "Add to Cart", edit_product_path(@product.id), method: :get %> + +
+ +
+
    + <% @product.reviews.each do |review| %> +
  • + + <%= "Rating:#{review.rating}" %> + <%= "Comment:#{review.comment}" %> + <%= link_to "Review: #{review.id}", review_path(review.id) %> +
  • + <% end %> +
+
From 6ca19f723c8e140586709fba2d358a0e390ec354 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 17:06:15 -0700 Subject: [PATCH 063/252] Fixed seeds file on Products creation to have a Merchant id --- db/seeds.rb | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/db/seeds.rb b/db/seeds.rb index a3ad8e5341..0158c2286c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -22,25 +22,22 @@ category = Category.create!(name: Faker::Dessert.topping) puts "#{category.name} created!" - category = Category.create!(name: Faker::Dessert.topping) - puts "#{category.name} created!" p "Created #{Category.count} categories" +# Mercahnts +5.times do |t| + merchant = Merchant.create!(username: "#{Faker::Name.name}#{t}", email: Faker::Internet.email ) + puts "#{merchant.username} created!" +end + +p "Created #{Merchant.count} merchants" + # Products -20.times do |t| - product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.first] , quantity: 2 ) +10.times do |t| + product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.first] , quantity: 2, merchant_id: Merchant.first.id ) puts "#{product.name} created!" puts " category: #{product.categories.first.name}" end p "Created #{Product.count} desserts" - - -# Mercahnts -5.times do |t| - merchant = Merchant.create!(username: Faker::Name.name, email: Faker::Internet.email ) - puts "#{merchant.username} created!" -end - -p "Created #{Merchant.count} merchants" From fe5a8a95352052c58b2a7f02bf90be273ad6a9a5 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 17:06:50 -0700 Subject: [PATCH 064/252] Working on categories index to show a list of options --- app/views/categories/index.html.erb | 12 ++++++++++-- app/views/products/root.html.erb | 5 ----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index a5d0d54736..656f349ce2 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -1,2 +1,10 @@ -

Categories#index

-

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

+

Categories

+ + +
+
    + <% @categories.each do |category|%> +
  • <%= link_to category.name, category_path(category.id) %>
  • + <% end %> +
+
diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index 02a1202fb6..2ead10c97a 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -8,8 +8,3 @@ <% end %> - From bac2e36367aa653d92cfda6c58dbc9eed26d13bf Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 17:27:01 -0700 Subject: [PATCH 065/252] Category#show done with basic view of each category.products as a link to the product itself --- app/controllers/categories_controller.rb | 4 ++++ app/views/categories/show.html.erb | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 27821ff5d8..9609335936 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -6,6 +6,7 @@ def index end def show + find_category end def new @@ -13,12 +14,15 @@ def new end def create + end def update + find_category end def edit + find_category end def destroy diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 60e06c3d7b..a5e810f54b 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -1,2 +1,7 @@ -

Categories#show

-

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

+<%= @category.name %> + +
    +<% @category.products.each do |product| %> +
  • <%= link_to product.name, product_path(product.id) %>
  • +<% end %> +
From dc8a88271ea2c07e2548c50b1ae8e810bd722ee4 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 17:50:41 -0700 Subject: [PATCH 066/252] Added a form for creating/edit categories --- app/views/categories/_category_form.html.erb | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 app/views/categories/_category_form.html.erb diff --git a/app/views/categories/_category_form.html.erb b/app/views/categories/_category_form.html.erb new file mode 100644 index 0000000000..65dbc451e0 --- /dev/null +++ b/app/views/categories/_category_form.html.erb @@ -0,0 +1,6 @@ +<%= form_for @category do |f| %> +<%= f.label :name %> +<%= f.text_field :name %> + +<%= f.submit class: "button" %> +<% end %> From 6f6da91ce4190876f361184118f5bd9b8f9592f4 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 17:51:12 -0700 Subject: [PATCH 067/252] Adding categories basic methods and their views --- app/controllers/categories_controller.rb | 11 ++++++++++- app/views/categories/edit.html.erb | 3 +-- app/views/categories/index.html.erb | 1 - app/views/categories/new.html.erb | 3 +-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 9609335936..95458840d3 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -14,7 +14,16 @@ def new end def create - + @category = Category.new(category_params) + if @category.save + flash[:status] = :success + flash[:result_text] = "Successfully created #{@category.name}" + redirect_to categories_path(@category.id) + else + flash[:status] = :failure + flash[:result_text] = "Could not create this category" + redirect_to categories_path + end end def update diff --git a/app/views/categories/edit.html.erb b/app/views/categories/edit.html.erb index 3b8dca3af4..23706aa343 100644 --- a/app/views/categories/edit.html.erb +++ b/app/views/categories/edit.html.erb @@ -1,2 +1 @@ -

Categories#edit

-

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

+<%= render partial: "category_form", locals: { page_title: "Edit Category" } %> diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index 656f349ce2..cbd394c3b9 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -1,6 +1,5 @@

Categories

-
    <% @categories.each do |category|%> diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb index 7e5c27307e..77f2be88f0 100644 --- a/app/views/categories/new.html.erb +++ b/app/views/categories/new.html.erb @@ -1,2 +1 @@ -

    Categories#new

    -

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

    +<%= render partial: "category_form", locals: { page_title: "Add a Category" } %> From b41bf95fe5e5cf85a226e3ad14bc17bcbe144cee Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 18:04:46 -0700 Subject: [PATCH 068/252] Added category#destroy. --> Category methods done. --- app/controllers/categories_controller.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 95458840d3..f91af42f7e 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -6,7 +6,6 @@ def index end def show - find_category end def new @@ -27,14 +26,21 @@ def create end def update - find_category + if @category.update(category_params) + flash[:status] = :success + redirect_to categories_path(@category) + else + flash.now[:status] = :failure + end end def edit - find_category end def destroy + # shouls a user be able to delete a category? Maybe not... + @category.destroy if @category + redirect_to categories_path end private From a8bb6e39a663bebb847271ee5e0eefa1e3aded9e Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 20 Apr 2018 20:23:32 -0700 Subject: [PATCH 069/252] Seeds logic better. 10 random records of each. --- db/seeds.rb | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/db/seeds.rb b/db/seeds.rb index 0158c2286c..4900b9ccff 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -10,34 +10,34 @@ require 'faker' # Categories: - category = Category.create!(name: "Caramel") - puts "#{category.name} created!" - - category = Category.create!(name: "Gummy") - puts "#{category.name} created!" - - category = Category.create!(name: "Cakes") - puts "#{category.name} created!" - - category = Category.create!(name: Faker::Dessert.topping) +puts "\n" +10.times do |t| + category = Category.create(name: Faker::Dessert.topping) + until category.name do + category = Category.create!(name: Faker::Dessert.topping) + end puts "#{category.name} created!" - -p "Created #{Category.count} categories" +end +p "**Created #{Category.count} categories**" # Mercahnts -5.times do |t| - merchant = Merchant.create!(username: "#{Faker::Name.name}#{t}", email: Faker::Internet.email ) +puts "\n" +10.times do |t| + merchant = Merchant.create(username: "#{Faker::Name.name}#{t}", email: Faker::Internet.email ) + until merchant.username do + merchant = Merchant.create!(username: "#{Faker::Name.name}#{t}", email: Faker::Internet.email ) + end puts "#{merchant.username} created!" end -p "Created #{Merchant.count} merchants" +p "**Created #{Merchant.count} merchants**" # Products +puts "\n" 10.times do |t| - product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.first] , quantity: 2, merchant_id: Merchant.first.id ) - puts "#{product.name} created!" - puts " category: #{product.categories.first.name}" + product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.order("RANDOM()").first] , quantity: 2, merchant_id: Merchant.order("RANDOM()").first.id ) + puts "#{product.name} created in the category: #{product.categories.first.name}" end -p "Created #{Product.count} desserts" +p "**Created #{Product.count} desserts**" From 25f4451c761c30e067b11a59f6ace43bdb6e98ba Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Sat, 21 Apr 2018 12:03:19 -0700 Subject: [PATCH 070/252] table for merchant index --- app/controllers/merchants_controller.rb | 2 +- app/views/layouts/application.html.erb | 59 +++++++++++++------ app/views/merchants/index.html.erb | 22 ++++++- ...180420233543_add_merchant_id_to_product.rb | 5 ++ db/schema.rb | 5 +- db/seeds.rb | 34 +++++++++-- 6 files changed, 100 insertions(+), 27 deletions(-) create mode 100644 db/migrate/20180420233543_add_merchant_id_to_product.rb diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 1dc89e2b59..81b413a033 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -31,6 +31,6 @@ def merchant_params end def find_merchant - @merchant = Merchant.find_by(:id params[:id]) + @merchant = Merchant.find_by(id: params[:id]) end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 44c082165f..0012651bf8 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -12,23 +12,50 @@
- - + diff --git a/app/views/merchants/index.html.erb b/app/views/merchants/index.html.erb index 0ad7977813..37922fa560 100644 --- a/app/views/merchants/index.html.erb +++ b/app/views/merchants/index.html.erb @@ -1,2 +1,20 @@ -

Merchants#index

-

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

+

Merchants

+ +
+ + + + + + <% @merchants.each do |merchant| %> + + + + + <% end %> +
UsernameEmail
+ <%= link_to merchant.username, merchant_path(merchant.id) %> + + <%= merchant.email %> +
+
diff --git a/db/migrate/20180420233543_add_merchant_id_to_product.rb b/db/migrate/20180420233543_add_merchant_id_to_product.rb new file mode 100644 index 0000000000..ea6eb433b3 --- /dev/null +++ b/db/migrate/20180420233543_add_merchant_id_to_product.rb @@ -0,0 +1,5 @@ +class AddMerchantIdToProduct < ActiveRecord::Migration[5.1] + def change + add_reference :products, :merchant, foreign_key: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 2ec08c9e8d..bc832008d1 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: 20180420223006) do +ActiveRecord::Schema.define(version: 20180420233543) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -71,6 +71,8 @@ t.datetime "updated_at", null: false t.string "description" t.bigint "order_id" + t.bigint "merchant_id" + t.index ["merchant_id"], name: "index_products_on_merchant_id" t.index ["order_id"], name: "index_products_on_order_id" end @@ -87,6 +89,7 @@ add_foreign_key "orderproducts", "orders" add_foreign_key "orderproducts", "products" add_foreign_key "orders", "products" + add_foreign_key "products", "merchants" add_foreign_key "products", "orders" add_foreign_key "reviews", "products" end diff --git a/db/seeds.rb b/db/seeds.rb index 8f22efeb0c..4900b9ccff 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -9,13 +9,35 @@ require 'faker' -category = Category.create!(name: "Dessert") +# Categories: +puts "\n" +10.times do |t| + category = Category.create(name: Faker::Dessert.topping) + until category.name do + category = Category.create!(name: Faker::Dessert.topping) + end + puts "#{category.name} created!" +end +p "**Created #{Category.count} categories**" + +# Mercahnts +puts "\n" +10.times do |t| + merchant = Merchant.create(username: "#{Faker::Name.name}#{t}", email: Faker::Internet.email ) + until merchant.username do + merchant = Merchant.create!(username: "#{Faker::Name.name}#{t}", email: Faker::Internet.email ) + end + puts "#{merchant.username} created!" +end + +p "**Created #{Merchant.count} merchants**" -20.times do |t| - product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [category] , quantity: 2 ) - puts "#{product.name} created!" - puts " category: #{product.categories.first.name}" +# Products +puts "\n" +10.times do |t| + product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.order("RANDOM()").first] , quantity: 2, merchant_id: Merchant.order("RANDOM()").first.id ) + puts "#{product.name} created in the category: #{product.categories.first.name}" end -p "Created #{Product.count} desserts" +p "**Created #{Product.count} desserts**" From ad98322e04d09acb38cc4a9771f6e1d5929bd087 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Sat, 21 Apr 2018 12:16:39 -0700 Subject: [PATCH 071/252] reformmated index, added links to merchant#show --- app/views/merchants/index.html.erb | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/app/views/merchants/index.html.erb b/app/views/merchants/index.html.erb index 37922fa560..b9e847507e 100644 --- a/app/views/merchants/index.html.erb +++ b/app/views/merchants/index.html.erb @@ -1,20 +1,15 @@

Merchants

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

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

+

+ Email: <%= merchant.email %> +

+
+ <% end %>
From 953b315d35b05ef7d0ee63c26fe5a49d190caa3f Mon Sep 17 00:00:00 2001 From: Aruna Date: Sat, 21 Apr 2018 12:30:35 -0700 Subject: [PATCH 072/252] working on product controller --- app/controllers/orderproducts_controller.rb | 73 +++++++++++++++++++++ app/controllers/products_controller.rb | 23 +++++++ app/controllers/reviews_controller.rb | 26 +++++++- app/models/product.rb | 10 ++- app/views/categories/index.html.erb | 10 ++- app/views/products/show.html.erb | 53 +++++++-------- app/views/reviews/new.html.erb | 25 ++++++- config/routes.rb | 12 ++-- db/schema.rb | 8 ++- db/seeds.rb | 24 ++++++- db/seeds/reviews.csv | 4 ++ 11 files changed, 228 insertions(+), 40 deletions(-) create mode 100644 app/controllers/orderproducts_controller.rb create mode 100644 db/seeds/reviews.csv diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb new file mode 100644 index 0000000000..652921451f --- /dev/null +++ b/app/controllers/orderproducts_controller.rb @@ -0,0 +1,73 @@ +class OrderproductsController < ApplicationController + before_action :find_orderproduct, only: [:edit, :update, :destroy] + + def index + @orderproducts = Orderproduct.all + end + + def show + end + + def create + + if @order.nil? + @order = Order.create(status: "pending") + end + @op = @order.orderproducts.find_by(product_id: params[:id]) + if @op + @op.quantity += params[:orderproduct][:quantity].to_i + else + @op = Orderproduct.new(orderproduct_params) + @op.product_id = params[:id] + end + if @op.save + flash[:status] = :success + flash[:result_text] = "Successfully added to cart" + redirect_to product_path(params[:id]) + else + flash[:status] = :failure + flash[:result_text] = "Sorry" + flash[:messages] = @op.errors.messages + redirect_to product_path(params[:id]), status: :bad_request + end + end + + def new + end + + def edit + end + + def update + if @orderproduct.update(orderproduct_params) + flash[:status] = :success + flash[:result_text] = "Cart updated" + redirect_to orders_path + else + flash.now[:status] = :failure + flash.now[:result_text] = "Cart could not be updated" + flash.now[:messages] = @orderproduct.errors.messages + render :edit + end + end + + def destroy + order = @orderproduct.order + @orderproduct.destroy + if order.orderproducts.empty? + order.destroy + end + flash[:status] = :success + flash[:result_text] = "Successfully removed from your cart!" + redirect_to orders_path + end + + + private + def orderproduct_params + params.require(:order_product).permit(:quantity) + end + def find_orderproduct + @order_product = Orderproduct.find_by(:id params[:id]) + end +end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 32d09dcabf..5170364107 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -17,15 +17,38 @@ def new end def create + @product = Product.new(product_params) + #@product.merchant_id = session[:merchant_id] + if @product.save + flash[:status] = :success + redirect_to product_path(@product.id) + else + flash[:failure] = :failure + flash.now[:result_text]= "Error: product was not added" + render :new + end end def edit + render_404 unless @product end def update + if @product.update(product_params) + flash[:success] = "#{@product.name} updated" + redirect_to product_path(@product.id) + else + flash[:alert] = "A problem occured:Could not update" + + render :edit + end end def destroy + if @product.destroy + flash[:message] = "Deleted #{@product.category} #{@product.name}" + redirect_to products_path + end end private diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index ca17a05e1b..c389b1b48a 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -1,5 +1,6 @@ class ReviewsController < ApplicationController - before_action :find_review, only: [:show, :edit, :update, :destroy] + + before_action :find_review, only: [:show, :edit,:update, :destroy] def index @reviews = Review.all @@ -10,9 +11,29 @@ def show def new @review = Review.new + product = Product.find_by(id: params[:product_id]) + end def create + + product = Product.find_by(id: params[:product_id]) + # if session[:merchant_id] = @product.merchant_id + # flash[:status] = :failure + # flash[:result_text]= "AS a merchant u cannot review your own product" + # redirect_to product_path(@product.id) + # else + @review = Review.new(review_params) + @review.product_id = @product.id + + if @review.save + flash[:success] = "#{@review.rating} saved" + redirect_to product_path(@review.product) + else + flash[:alert] = "Could not create #{@review.rating}" + render :new + end + #end end def update @@ -27,10 +48,11 @@ def destroy private def review_params - return params.require(:review).permit(:rating, :comment) + return params.require(:review).permit(:rating, :comment) end def find_review @review = Review.find_by(id: params[:id]) + end end diff --git a/app/models/product.rb b/app/models/product.rb index 0269c60c5f..2fc7fa8e95 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -8,7 +8,14 @@ class Product < ApplicationRecord validates_numericality_of :quantity, presence: true, greater_than_or_equal_to: 0 validates_numericality_of :price, presence: true, greater_than_or_equal_to: 0 - + def average_rating + return "No reviews yet" if reviews.count == 0 + sum = 0 + reviews.each do |review| + sum += review.rating + end + return (sum.to_f/reviews.count).round(1) + end private def has_atleast_one_category @@ -16,4 +23,5 @@ def has_atleast_one_category errors.add(:categories, "must have atleat one category") end end + end diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index a5d0d54736..a53fbf04c4 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -1,2 +1,8 @@ -

Categories#index

-

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

+ +
+
    + <% @categories.each do |category|%> +
  • <%= link_to categories.name, categories_path(category.id) %>
  • + <% end %> +
+
diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 9b3824c4b5..5a309c892e 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -3,34 +3,35 @@
<%= "Product : #{@product.name}" %> - -

<%= "Price:#{ @product.price}" %> - -

<%= "Stock: #{@product.quantity}" %>

-
-<%= form_for @orderproduct do |f| %> - <%= f.label :quantity %> - <%= f.select :quantity, options_for_select(1..10)%> - <%= f.submit "Add to Cart", class: "button" %> + <%= image_tag "https://placeholder.com" %> +

<%= "Price:#{ @product.price}" %> + +

<%= "Stock: #{@product.quantity}" %>

+ + <%= form_for @product do |f| %> + <%= f.label :quantity %> + <%= f.select :quantity, options_for_select(1..10)%> + <%= f.submit "Add to Cart", class: "button" %> + <% end %> +
+

<%="Description:#{@product.description}" %> +

+
+

Reviews:

+

Average Rating:<%= "#{@product.average_rating}" %>

+ <% @product.reviews.each do |review| %> +
    +
  • + Rating: <%= review.rating %> +
  • +
  • + <%= review.comment %> +
  • +
<% end %> -
-

<%="Description:#{@product.description}" %> -

-
- <%= button_to "Add to Cart", edit_product_path(@product.id), method: :get %> -
+ <%= link_to("Add a Review", new_product_review_path(@product.id), :class => "button") %> -
-
    - <% @product.reviews.each do |review| %> -
  • - <%= "Rating:#{review.rating}" %> - <%= "Comment:#{review.comment}" %> - <%= link_to "Review: #{review.id}", review_path(review.id) %> -
  • - <% end %> -
-
+
diff --git a/app/views/reviews/new.html.erb b/app/views/reviews/new.html.erb index 9cc9d7f56b..f5280ff432 100644 --- a/app/views/reviews/new.html.erb +++ b/app/views/reviews/new.html.erb @@ -1,2 +1,23 @@ -

Reviews#new

-

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

+

Leave a review for

+ +<%= form_for @review do |f| %> + <%= f.hidden_field :product_id %> + <%= f.label :rating %> +
+ <%= f.radio_button(:rating, 5) %> + + <%= f.radio_button(:rating, 4) %> + + <%= f.radio_button(:rating, 3) %> + + <%= f.radio_button(:rating, 2) %> + + <%= f.radio_button(:rating, 1) %> + +
+ + <%= f.text_field :rating %> + <%= f.label :Review %> + <%= f.text_area :comment %> + <%= f.submit("submit", class: "button") %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index 9adc60139b..3883196200 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,14 +4,16 @@ get '/login', to: 'sessions#new', as: 'login_form' post '/login', to: 'sessions#create' delete '/login', to: 'sessions#destroy', as: 'logout' - + # Reviews: + # # Products: root 'products#root', as: 'homepage' +#resources :reviews resources :products do # add orderproducts (cart#index) - #resources :reviews, only: [:new] + resources :reviews,only: [:new,:create] #resources :merchants, only: [:index] - resources :categories, only: [:index] + #resources :categories, only: [:index] end # Merchants: @@ -19,8 +21,8 @@ resources :products, only: [:index] end - # Reviews: - resources :reviews + + resources :reviews,only: [:new,:create] # Categories: resources :categories diff --git a/db/schema.rb b/db/schema.rb index 809ca5315a..b955b5bff8 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: 20180420184237) do +ActiveRecord::Schema.define(version: 20180420210248) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -48,6 +48,10 @@ t.integer "quantity" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.bigint "order_id" + t.bigint "product_id" + t.index ["order_id"], name: "index_orderproducts_on_order_id" + t.index ["product_id"], name: "index_orderproducts_on_product_id" end create_table "orders", force: :cascade do |t| @@ -85,6 +89,8 @@ end add_foreign_key "categories", "products" + add_foreign_key "orderproducts", "orders" + add_foreign_key "orderproducts", "products" add_foreign_key "orders", "products" add_foreign_key "reviews", "products" end diff --git a/db/seeds.rb b/db/seeds.rb index 8f22efeb0c..dbe0720d5d 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -6,7 +6,7 @@ # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) # Character.create(name: 'Luke', movie: movies.first) - +require'csv' require 'faker' category = Category.create!(name: "Dessert") @@ -19,3 +19,25 @@ end p "Created #{Product.count} desserts" + +REVIEW_FILE = Rails.root.join('db', 'seeds', 'reviews.csv') +puts "Loading raw user data from #{REVIEW_FILE}" + +review_failures = [] +CSV.foreach(REVIEW_FILE, :headers => true) do |row| + review = Review.new + review.rating = row['rating'] + review.product_id = row['product_id'] + review.comment = row['comment'] + puts "Created review: #{review.inspect}" + successful = review.save + if !successful + puts review.errors + review_failures << review + end +end + +puts "Added #{Review.count} review records" +puts "#{review_failures.length} reviews failed to save" +p review_failures +puts diff --git a/db/seeds/reviews.csv b/db/seeds/reviews.csv new file mode 100644 index 0000000000..f5c1e4f38c --- /dev/null +++ b/db/seeds/reviews.csv @@ -0,0 +1,4 @@ +rating,product_id,comment +2,1,great +3,4,good +1,2,bad From c22a3bfc80ce558ef51f21ab6b59eaacec1ec701 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Sat, 21 Apr 2018 15:18:29 -0700 Subject: [PATCH 073/252] stying background, font, nav --- app/assets/stylesheets/application.css | 57 ++++++++++++++++++++++++++ app/views/layouts/application.html.erb | 4 +- app/views/merchants/index.html.erb | 18 ++++---- app/views/products/root.html.erb | 3 +- 4 files changed, 70 insertions(+), 12 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 3a38418320..cfdee43fa3 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -17,3 +17,60 @@ *= require foundation_and_overrides */ + body { + background-color: #ffe6cc; + font-family: 'Pontano Sans', sans-serif; + } + +.top-bar { + background-color: #009999; + border-bottom: dotted; + border-bottom-color: grey; + padding: 0; + margin: 0; + } + +.button { + background-color: white; + color: black; +} + h1 { + font-family: 'Pacifico', cursive; + padding-bottom: 20px; + display: flex; + justify-content: center; + padding-top: 20px; + } + .all-merchants { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + align-content: center; + } + .merch-container { + display: grid; + grid-template: + "image" + "text"; + padding-bottom: 40px; + padding-left: 15px; + padding-right: 15px; + } + + .merch-container #pic { + grid-area: image; + display: flex; + justify-content: center; + } + + .merch-container p { + grid-area: text; + display: flex; + justify-content: center; + margin: 0; + } + + strong { + margin-right: .3em; + } diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 0012651bf8..a0ac0d0002 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -3,8 +3,8 @@ - - <%= content_for?(:title) ? yield(:title) : "Yummsy!" %> + + <%= content_for?(:title) ? yield(:title) : "Sweetsy!" %> <%= stylesheet_link_tag "application" %> <%= javascript_include_tag "application", 'data-turbolinks-track' => true %> diff --git a/app/views/merchants/index.html.erb b/app/views/merchants/index.html.erb index b9e847507e..c3aea4f919 100644 --- a/app/views/merchants/index.html.erb +++ b/app/views/merchants/index.html.erb @@ -1,15 +1,17 @@

Merchants

-
+
<% @merchants.each do |merchant| %>
- merchant pic -

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

-

- Email: <%= merchant.email %> -

+ merchant pic +
+

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

+

+ Email:<%= merchant.email %> +

+
<% end %>
diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index 2ead10c97a..2a677eab83 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -1,5 +1,4 @@ -

Splash page...

- +

Sweetsy!

    From ddd28e706fea1b5c6ccbb462f7c928058fe12d02 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Sat, 21 Apr 2018 15:28:16 -0700 Subject: [PATCH 074/252] title --- app/views/merchants/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index cbb0f02bfe..21caeddb23 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -1,2 +1,2 @@ -

    Merchants#show

    +

    Products by <%= @merchant.username %>

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

    From b559b297a7279e633cec955fa68c0d76ddf5cf6f Mon Sep 17 00:00:00 2001 From: Aruna Date: Sat, 21 Apr 2018 15:36:40 -0700 Subject: [PATCH 075/252] add a new product --- app/controllers/products_controller.rb | 4 +-- app/controllers/reviews_controller.rb | 19 ++++-------- app/helpers/products_helper.rb | 1 + app/models/merchant.rb | 1 + app/models/order.rb | 3 +- app/models/product.rb | 26 +++++++++++----- app/views/products/index.html.erb | 12 ++++++-- app/views/products/new.html.erb | 26 ++++++++++++++-- app/views/products/show.html.erb | 42 ++++++++++++++++---------- app/views/reviews/new.html.erb | 4 +-- config/routes.rb | 10 ++---- db/seeds.rb | 6 ++-- db/seeds/reviews.csv | 15 ++++++--- 13 files changed, 109 insertions(+), 60 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 5170364107..17c51407e6 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -21,7 +21,7 @@ def create #@product.merchant_id = session[:merchant_id] if @product.save flash[:status] = :success - redirect_to product_path(@product.id) + redirect_to products_path else flash[:failure] = :failure flash.now[:result_text]= "Error: product was not added" @@ -30,7 +30,7 @@ def create end def edit - render_404 unless @product + end def update diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index c389b1b48a..f81b728893 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -11,7 +11,7 @@ def show def new @review = Review.new - product = Product.find_by(id: params[:product_id]) + #product = Product.find_by(id: params[:product_id]) end @@ -24,31 +24,24 @@ def create # redirect_to product_path(@product.id) # else @review = Review.new(review_params) - @review.product_id = @product.id + #@review.product_id = @product.id if @review.save flash[:success] = "#{@review.rating} saved" - redirect_to product_path(@review.product) + redirect_to products_path else flash[:alert] = "Could not create #{@review.rating}" - render :new + redirect_to products_path + end #end end - def update - end - - def edit - end - - def destroy - end private def review_params - return params.require(:review).permit(:rating, :comment) + return params.require(:review).permit(:rating, :comment,:product_id) end def find_review diff --git a/app/helpers/products_helper.rb b/app/helpers/products_helper.rb index ab5c42b325..1c21d86ccc 100644 --- a/app/helpers/products_helper.rb +++ b/app/helpers/products_helper.rb @@ -1,2 +1,3 @@ module ProductsHelper + end diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 70f790d139..c0b3263a23 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -1,6 +1,7 @@ class Merchant < ApplicationRecord VALID_EMAIL = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i has_many :products + validates :username, presence: true, length: { :minimum => 0 }, diff --git a/app/models/order.rb b/app/models/order.rb index 99dc779fdf..f443d9ba71 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,6 +1,7 @@ class Order < ApplicationRecord VALID_EMAIL = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i - has_many :products, through: :orderproduct + has_many :products, through: :orderproducts + has_many :orderproducts validates :address, presence: true, length: { in: 1..35 } validates :card_name, presence: true, length: { minimum: 1 } diff --git a/app/models/product.rb b/app/models/product.rb index 2fc7fa8e95..af3bb1f579 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -3,19 +3,31 @@ class Product < ApplicationRecord has_and_belongs_to_many :categories, join_table: "category_product" has_many :reviews + validates :name, presence: true, length: { minimum: 1 } validate :has_atleast_one_category validates_numericality_of :quantity, presence: true, greater_than_or_equal_to: 0 validates_numericality_of :price, presence: true, greater_than_or_equal_to: 0 - def average_rating - return "No reviews yet" if reviews.count == 0 - sum = 0 - reviews.each do |review| - sum += review.rating - end - return (sum.to_f/reviews.count).round(1) + if (self.reviews).count > 0 + product_reviews = self.reviews + sum_ratings = 0.0 + product_reviews.each do |review| + sum_ratings += review.rating + end + avg = sum_ratings/(product_reviews.count) + return avg + else + return 0 + end + # return "No reviews yet" if reviews.count == 0 + # sum = 0.0 + # products.reviews.each do |review| + # sum += review.rating + # end + # return (sum/reviews.count) end + private def has_atleast_one_category diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index f8eeb82674..5a4ca536df 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,2 +1,10 @@ -

    Products#index

    -

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

    + + <% @products.each do |product| %> +
    +

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

    +
    + <% end %> +

    <%= link_to("Add a Product", new_product_path, :class => "button") %> + +

diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index a14e0d91b6..9d787af51f 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -1,2 +1,24 @@ -

Products#new

-

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

+<%= form_for @product do |f| %> + <%= f.label :name %> + <%= f.text_field :name %> + + <%= f.label "price (cents)" %> + <%= f.text_field :price, placeholder: "in cents" %> + + <%= f.label :quantity %> + <%= f.text_field :quantity %> + + <%= f.label :description %> + <%= f.text_area :description %> + <%= f.collection_check_boxes :category_ids, Category.all, :id, :name do |b| %> + <%= b.check_box %> + <%= b.label %> + <% end %> + +
+ <%= f.submit class: "cart button"%> +
+ + + <% end %> +
diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 5a309c892e..2e9c1ae573 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -3,7 +3,7 @@
<%= "Product : #{@product.name}" %> - <%= image_tag "https://placeholder.com" %> + <%= image_tag "https://picsum.photos" %>

<%= "Price:#{ @product.price}" %>

<%= "Stock: #{@product.quantity}" %>

@@ -17,21 +17,31 @@

<%="Description:#{@product.description}" %>

-

Reviews:

-

Average Rating:<%= "#{@product.average_rating}" %>

- <% @product.reviews.each do |review| %> -
    -
  • - Rating: <%= review.rating %> -
  • -
  • - <%= review.comment %> -
  • -
- <% end %> - - - <%= link_to("Add a Review", new_product_review_path(@product.id), :class => "button") %> +

Ratings Summary

+

+ <%= @product.average_rating %> +

+ <% if @product.reviews.empty? %> +

+ Be the first to review! +

+ <%else %> +
    + <% @product.reviews.each do |review| %> +
    +
  • + <% review.rating.times do%> + <%= "🍦" %> + <% end %> +
  • +

    + <%= review.comment %> +

    + <%end %> +
+ <% end %> +

<%=link_to "review now!", new_product_review_path(@product.id), class: 'button' %>

+
diff --git a/app/views/reviews/new.html.erb b/app/views/reviews/new.html.erb index f5280ff432..2b5b4ca374 100644 --- a/app/views/reviews/new.html.erb +++ b/app/views/reviews/new.html.erb @@ -15,8 +15,8 @@ <%= f.radio_button(:rating, 1) %> - - <%= f.text_field :rating %> + + <%= f.label :Review %> <%= f.text_area :comment %> <%= f.submit("submit", class: "button") %> diff --git a/config/routes.rb b/config/routes.rb index 3883196200..371ddd0536 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,5 @@ Rails.application.routes.draw do - +root 'products#root', as: 'homepage' #sessions get '/login', to: 'sessions#new', as: 'login_form' post '/login', to: 'sessions#create' @@ -7,23 +7,19 @@ # Reviews: # # Products: - root 'products#root', as: 'homepage' -#resources :reviews + resources :products do # add orderproducts (cart#index) resources :reviews,only: [:new,:create] #resources :merchants, only: [:index] #resources :categories, only: [:index] end - +resources :reviews # Merchants: resources :merchants do resources :products, only: [:index] end - - resources :reviews,only: [:new,:create] - # Categories: resources :categories diff --git a/db/seeds.rb b/db/seeds.rb index dbe0720d5d..5bf1d8e7b8 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -19,16 +19,14 @@ end p "Created #{Product.count} desserts" - -REVIEW_FILE = Rails.root.join('db', 'seeds', 'reviews.csv') -puts "Loading raw user data from #{REVIEW_FILE}" +REVIEW_FILE = Rails.root.join('db','seeds', 'reviews.csv') +puts "Loading raw review data from #{REVIEW_FILE}" review_failures = [] CSV.foreach(REVIEW_FILE, :headers => true) do |row| review = Review.new review.rating = row['rating'] review.product_id = row['product_id'] - review.comment = row['comment'] puts "Created review: #{review.inspect}" successful = review.save if !successful diff --git a/db/seeds/reviews.csv b/db/seeds/reviews.csv index f5c1e4f38c..018a390427 100644 --- a/db/seeds/reviews.csv +++ b/db/seeds/reviews.csv @@ -1,4 +1,11 @@ -rating,product_id,comment -2,1,great -3,4,good -1,2,bad +rating,product_id +1,3 +2,4 +3,5 +4,6 +5,1 +6,2 +7,7 +8,8 +9,9 +10,10 From a477a4435a868401f369101934cd240d2f5696b4 Mon Sep 17 00:00:00 2001 From: Aruna Date: Sat, 21 Apr 2018 16:20:22 -0700 Subject: [PATCH 076/252] product controller show page --- app/controllers/products_controller.rb | 2 +- app/views/products/new.html.erb | 7 +++---- app/views/products/show.html.erb | 7 +++---- app/views/reviews/new.html.erb | 3 ++- config/routes.rb | 2 +- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 17c51407e6..f3fe4519cd 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -54,7 +54,7 @@ def destroy private def product_params - return params.require(:product).permit(:name, :price, :category, :quantity, :description) + return params.require(:product).permit(:name, :price, :quantity, :description) end def find_product diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index 9d787af51f..892ff2837b 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -7,7 +7,7 @@ <%= f.label :quantity %> <%= f.text_field :quantity %> - + <%= f.label :description %> <%= f.text_area :description %> <%= f.collection_check_boxes :category_ids, Category.all, :id, :name do |b| %> @@ -15,9 +15,8 @@ <%= b.label %> <% end %> -
- <%= f.submit class: "cart button"%> -
+ <%= f.submit %> + <% end %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 2e9c1ae573..fcb7f0d1aa 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -20,7 +20,7 @@

Ratings Summary

- <%= @product.average_rating %> + <%="Average rating: #{@product.average_rating}" %>

<% if @product.reviews.empty? %>

@@ -31,9 +31,8 @@ <% @product.reviews.each do |review| %>

  • - <% review.rating.times do%> - <%= "🍦" %> - <% end %> + <% review.rating%> +
  • <%= review.comment %> diff --git a/app/views/reviews/new.html.erb b/app/views/reviews/new.html.erb index 2b5b4ca374..202874dd1b 100644 --- a/app/views/reviews/new.html.erb +++ b/app/views/reviews/new.html.erb @@ -19,5 +19,6 @@ <%= f.label :Review %> <%= f.text_area :comment %> - <%= f.submit("submit", class: "button") %> + + <%= f.submit %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index 371ddd0536..78026df697 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -7,7 +7,7 @@ # Reviews: # # Products: - +resources :products resources :products do # add orderproducts (cart#index) resources :reviews,only: [:new,:create] From e0d6c0e70c6e66a567958deb3699f4af388f9440 Mon Sep 17 00:00:00 2001 From: Aruna Date: Sat, 21 Apr 2018 16:24:34 -0700 Subject: [PATCH 077/252] added edit view for order_product --- app/models/orderproduct.rb | 2 ++ app/views/orderproducts/edit.html.erb | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index 0265ffdc7d..b4832a998a 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -1,5 +1,7 @@ class Orderproduct < ApplicationRecord belongs_to :order belongs_to :product + + end diff --git a/app/views/orderproducts/edit.html.erb b/app/views/orderproducts/edit.html.erb index 43eaf2ec63..979fffc069 100644 --- a/app/views/orderproducts/edit.html.erb +++ b/app/views/orderproducts/edit.html.erb @@ -1,2 +1,15 @@ -

    Orderproducts#edit

    -

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

    +

    Update Product Quantity

    + +
    + <%= image_tag @order_product.product.image, alt: @order_product.product.name%> +
    +
    + <%= link_to @order_product.product.name.titleize ,product_path(@order_product.product_id)%> + <%= form_for @order_product do |f| %> + <%= f.label :quantity %> + <%= f.select :quantity, options_for_select(1..10, @order_product.quantity) %> + <%= f.submit "Update Quantity", class: "button" %> + <% end %> +
    + + From 42a9093f42abbcd916d63be128568e5c9219ddf0 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Sat, 21 Apr 2018 17:00:18 -0700 Subject: [PATCH 078/252] merchant show layout --- app/assets/stylesheets/application.css | 33 +++++++++++++++++++++----- app/views/merchants/index.html.erb | 4 ++-- app/views/merchants/show.html.erb | 21 ++++++++++++++-- db/seeds.rb | 2 +- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index cfdee43fa3..4da94c0f56 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -25,7 +25,7 @@ .top-bar { background-color: #009999; border-bottom: dotted; - border-bottom-color: grey; + border-bottom-color: skyblue; padding: 0; margin: 0; } @@ -41,11 +41,11 @@ justify-content: center; padding-top: 20px; } - .all-merchants { + .item-box { display: flex; flex-direction: row; flex-wrap: wrap; - justify-content: center; + justify-content: space-around; align-content: center; } .merch-container { @@ -53,9 +53,7 @@ grid-template: "image" "text"; - padding-bottom: 40px; - padding-left: 15px; - padding-right: 15px; + padding: 2em; } .merch-container #pic { @@ -74,3 +72,26 @@ strong { margin-right: .3em; } + + .product-container { + padding: 2em; + } + + .product-container h4 { + display: flex; + justify-content: center; + } + +.product-info { + border: solid; + border-style: outset; + background-color: #ffaa80; + display: flex; + justify-content: space-between; + align-items: center; +} + +.product-info p { + margin: 0; + padding-left: .5em; +} diff --git a/app/views/merchants/index.html.erb b/app/views/merchants/index.html.erb index c3aea4f919..af848d4742 100644 --- a/app/views/merchants/index.html.erb +++ b/app/views/merchants/index.html.erb @@ -1,9 +1,9 @@

    Merchants

    -
    +
    <% @merchants.each do |merchant| %>
    - merchant pic + merchant pic

    Username:<%= link_to merchant.username, merchant_path(merchant.id) %> diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index 4ad2108c42..76453449ad 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -1,5 +1,22 @@

    Products by <%= @merchant.username %>

    -
    - <%= @merchant.products.each do |product| %> +
    + <% Product.where(merchant_id: @merchant.id).each do |product| %> +
    +

    <%= product.name %>

    + product pic +
    +

    + Price: <%= product.price %> +

    + Stock: <%= product.quantity %> +

    +

    +

    + Add to cart +

    +
    +
    + <% end %>
    diff --git a/db/seeds.rb b/db/seeds.rb index 4900b9ccff..6629867e40 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -23,7 +23,7 @@ # Mercahnts puts "\n" 10.times do |t| - merchant = Merchant.create(username: "#{Faker::Name.name}#{t}", email: Faker::Internet.email ) + merchant = Merchant.create(username: "#{Faker::Name.first_name}#{t}", email: Faker::Internet.email ) until merchant.username do merchant = Merchant.create!(username: "#{Faker::Name.name}#{t}", email: Faker::Internet.email ) end From 99c95ff7d057b8ffeb45d2f8f85dd5f569883e01 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Sat, 21 Apr 2018 17:17:20 -0700 Subject: [PATCH 079/252] fixed root error --- app/views/products/root.html.erb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index c63433001d..2a677eab83 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -7,8 +7,3 @@ <% end %>
    - From fca30ade7fa390e6695be5e1c3f7107bc1ef17e5 Mon Sep 17 00:00:00 2001 From: Aruna Date: Sat, 21 Apr 2018 17:22:28 -0700 Subject: [PATCH 080/252] added review page --- app/assets/stylesheets/products.scss | 40 ++++++++++++ app/views/orderproducts/edit.html.erb | 2 + app/views/products/show.html.erb | 93 ++++++++++++++------------- app/views/reviews/new.html.erb | 2 +- 4 files changed, 93 insertions(+), 44 deletions(-) create mode 100644 app/views/orderproducts/edit.html.erb diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss index 89e2e8db07..80d8de2aab 100644 --- a/app/assets/stylesheets/products.scss +++ b/app/assets/stylesheets/products.scss @@ -1,3 +1,43 @@ // 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/ +.product_show{ + display: flex; +} +.image-show img { + + flex-flow: column wrap; + align-items: left; +} + + +.product-show h3, .description, .rating article { + border-bottom: 1px + +} + +.description, .rating-average, .rating article { + margin: 1em 0; + padding: 1em 0; +} + +.rating-average { + margin-top: 3em; +} + +.product-show h3{ + font-size: 1.5em; + text-transform: uppercase; + padding-bottom: 0.5em; +} + +.product-show { + width: 100%; + margin-bottom: 2em; +} + + + +.image-show { + text-align: center; +} diff --git a/app/views/orderproducts/edit.html.erb b/app/views/orderproducts/edit.html.erb new file mode 100644 index 0000000000..43eaf2ec63 --- /dev/null +++ b/app/views/orderproducts/edit.html.erb @@ -0,0 +1,2 @@ +

    Orderproducts#edit

    +

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

    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index fcb7f0d1aa..690218ac22 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,46 +1,53 @@

    Product Details

    +
    +
    + <%= image_tag ('https://placeimg.com/350/200/nature') %> +
    -
    - <%= "Product : #{@product.name}" %> - <%= image_tag "https://picsum.photos" %> -

    <%= "Price:#{ @product.price}" %> - -

    <%= "Stock: #{@product.quantity}" %>

    -
    - <%= form_for @product do |f| %> - <%= f.label :quantity %> - <%= f.select :quantity, options_for_select(1..10)%> - <%= f.submit "Add to Cart", class: "button" %> - <% end %> -
    -

    <%="Description:#{@product.description}" %> -

    -
    - -

    Ratings Summary

    -

    - <%="Average rating: #{@product.average_rating}" %> -

    - <% if @product.reviews.empty? %> -

    - Be the first to review! -

    - <%else %> -
      - <% @product.reviews.each do |review| %> -
      -
    • - <% review.rating%> - -
    • -

      - <%= review.comment %> - -

      - <%end %> -
    - <% end %> -

    <%=link_to "review now!", new_product_review_path(@product.id), class: 'button' %>

    -
    -
    +
    +

    <%= "Product : #{@product.name}" %>

    + <%= "Stock: #{@product.quantity}" %> + +

    <%= "Price:#{ @product.price}" %>

    + + + <%= form_for @product do |f| %> + <%= f.label :quantity %> + <%= f.select :quantity, options_for_select(1..10)%> + <%= f.submit "Add to Cart", class: "button" %> + <% end %> + +

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

    + + +
    + +

    Ratings Summary

    +

    + <%="Average rating: #{@product.average_rating}" %> +

    +
    +
    +

    Rating

    + <% if @product.reviews.empty? %> +

    + Be the first to review! +

    + <%else %> +
      + <% @product.reviews.each do |review| %> +
      +
    • + <% review.rating%> +
    • +

      + <%= review.comment %> +

      + <%end %> +
    + <% end %> +

    <%=link_to "review now!", new_product_review_path(@product.id), class: 'button' %>

    +
    diff --git a/app/views/reviews/new.html.erb b/app/views/reviews/new.html.erb index 202874dd1b..fba2d89cec 100644 --- a/app/views/reviews/new.html.erb +++ b/app/views/reviews/new.html.erb @@ -1,4 +1,4 @@ -

    Leave a review for

    +

    Leave a review

    <%= form_for @review do |f| %> <%= f.hidden_field :product_id %> From ccb7f55dbca10cd1f5de03cc1b4217ec712c6808 Mon Sep 17 00:00:00 2001 From: Aruna Date: Sat, 21 Apr 2018 21:27:11 -0700 Subject: [PATCH 081/252] fixed some bugs --- app/models/product.rb | 34 +++++++++---------- config/routes.rb | 2 +- ...859_remove_reference_order_from_product.rb | 5 +++ db/schema.rb | 12 +------ 4 files changed, 24 insertions(+), 29 deletions(-) create mode 100644 db/migrate/20180422041859_remove_reference_order_from_product.rb diff --git a/app/models/product.rb b/app/models/product.rb index af3bb1f579..7c541665cc 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -9,23 +9,23 @@ class Product < ApplicationRecord validates_numericality_of :quantity, presence: true, greater_than_or_equal_to: 0 validates_numericality_of :price, presence: true, greater_than_or_equal_to: 0 def average_rating - if (self.reviews).count > 0 - product_reviews = self.reviews - sum_ratings = 0.0 - product_reviews.each do |review| - sum_ratings += review.rating - end - avg = sum_ratings/(product_reviews.count) - return avg - else - return 0 - end - # return "No reviews yet" if reviews.count == 0 - # sum = 0.0 - # products.reviews.each do |review| - # sum += review.rating - # end - # return (sum/reviews.count) + # if (self.reviews).count > 0 + # product_reviews = self.reviews + # sum_ratings = 0.0 + # product_reviews.each do |review| + # sum_ratings += review.rating + # end + # avg = sum_ratings/(product_reviews.count) + # return avg + # else + # return 0 + # end + return "No reviews yet" if reviews.count == 0 + sum = 0.0 + products.reviews.each do |review| + sum += review.rating + end + return (sum/reviews.count) end private diff --git a/config/routes.rb b/config/routes.rb index 78026df697..76503081e7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,7 +10,7 @@ resources :products resources :products do # add orderproducts (cart#index) - resources :reviews,only: [:new,:create] + resources :reviews,only: [:new,:create] #resources :merchants, only: [:index] #resources :categories, only: [:index] end diff --git a/db/migrate/20180422041859_remove_reference_order_from_product.rb b/db/migrate/20180422041859_remove_reference_order_from_product.rb new file mode 100644 index 0000000000..075201cad5 --- /dev/null +++ b/db/migrate/20180422041859_remove_reference_order_from_product.rb @@ -0,0 +1,5 @@ +class RemoveReferenceOrderFromProduct < ActiveRecord::Migration[5.1] + def change + remove_reference :orders, :product,foreign_key: true + end +end diff --git a/db/schema.rb b/db/schema.rb index b955b5bff8..7f71b53e97 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: 20180420210248) do +ActiveRecord::Schema.define(version: 20180422041859) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -37,13 +37,6 @@ t.datetime "updated_at", null: false end - create_table "order_product", force: :cascade do |t| - t.bigint "order_id" - t.bigint "product_id" - t.index ["order_id"], name: "index_order_product_on_order_id" - t.index ["product_id"], name: "index_order_product_on_product_id" - end - create_table "orderproducts", force: :cascade do |t| t.integer "quantity" t.datetime "created_at", null: false @@ -66,8 +59,6 @@ t.string "zip_code" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.bigint "product_id" - t.index ["product_id"], name: "index_orders_on_product_id" end create_table "products", force: :cascade do |t| @@ -91,6 +82,5 @@ add_foreign_key "categories", "products" add_foreign_key "orderproducts", "orders" add_foreign_key "orderproducts", "products" - add_foreign_key "orders", "products" add_foreign_key "reviews", "products" end From 2961f7784c00b45445b7b41a0a70bc0799d92253 Mon Sep 17 00:00:00 2001 From: Aruna Date: Sat, 21 Apr 2018 22:49:08 -0700 Subject: [PATCH 082/252] added methods to orderproduct controlle --- app/controllers/orderproducts_controller.rb | 42 ++++++++++----------- app/models/orderproduct.rb | 2 +- app/views/orderproducts/edit.html.erb | 24 ++++++------ app/views/orderproducts/index.html.erb | 1 + app/views/orderproducts/new.html.erb | 11 +++++- app/views/products/show.html.erb | 2 +- config/routes.rb | 6 +-- 7 files changed, 47 insertions(+), 41 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 652921451f..a381770387 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -7,33 +7,31 @@ def index def show end + def new + @orderproduct = Orderproduct.new(orderproduct_params) + @product = Product.find_by(id: params[:product_id]) + end def create - if @order.nil? - @order = Order.create(status: "pending") - end - @op = @order.orderproducts.find_by(product_id: params[:id]) - if @op - @op.quantity += params[:orderproduct][:quantity].to_i - else - @op = Orderproduct.new(orderproduct_params) - @op.product_id = params[:id] - end - if @op.save - flash[:status] = :success - flash[:result_text] = "Successfully added to cart" - redirect_to product_path(params[:id]) + @product = Product.find_by(id: params[:product_id]) + @orderproduct = OrderProduct.new(orderproduct_params) + @orderproduct.product_id = @product.id + #@orderproduct.order_id = @order.id + + if @orderproduct.save + status = :success + flash[:result_text] = "#{@orderproduct.quantity} #{@orderproduct.product.name} have been added to your order!" + redirect_to products_path else - flash[:status] = :failure - flash[:result_text] = "Sorry" - flash[:messages] = @op.errors.messages - redirect_to product_path(params[:id]), status: :bad_request + status = :bad_request + flash[:result_text] = "Error - products not added to your order" + render :new, status: status + end end - def new - end + def edit end @@ -65,9 +63,9 @@ def destroy private def orderproduct_params - params.require(:order_product).permit(:quantity) + params.require(:order_product).permit(:quantity,:product_id) end def find_orderproduct - @order_product = Orderproduct.find_by(:id params[:id]) + @orderproduct = Orderproduct.find_by(id: params[:id]) end end diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index b4832a998a..e930e23b12 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -1,7 +1,7 @@ class Orderproduct < ApplicationRecord belongs_to :order belongs_to :product - + validates :quantity ,presence: true end diff --git a/app/views/orderproducts/edit.html.erb b/app/views/orderproducts/edit.html.erb index 979fffc069..275074d611 100644 --- a/app/views/orderproducts/edit.html.erb +++ b/app/views/orderproducts/edit.html.erb @@ -1,15 +1,15 @@ -

    Update Product Quantity

    - -
    - <%= image_tag @order_product.product.image, alt: @order_product.product.name%> -
    -
    - <%= link_to @order_product.product.name.titleize ,product_path(@order_product.product_id)%> - <%= form_for @order_product do |f| %> + + + + +

    Edit Order Item Quantity

    + +
    + <%= form_for @product do |f| %> + <%= f.label :quantity %> - <%= f.select :quantity, options_for_select(1..10, @order_product.quantity) %> - <%= f.submit "Update Quantity", class: "button" %> + <%= f.number_field :quantity, min: 1, max: @product.quantity %> + + <%= f.submit class: "button" %> <% end %> -
    -
    diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index e69de29bb2..0b330168a2 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -0,0 +1 @@ +asdads diff --git a/app/views/orderproducts/new.html.erb b/app/views/orderproducts/new.html.erb index 5404950c41..9e443f3245 100644 --- a/app/views/orderproducts/new.html.erb +++ b/app/views/orderproducts/new.html.erb @@ -1,2 +1,9 @@ -

    Orderproducts#new

    -

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

    +
    + <%= form_for @product do |f| %> + + <%= f.label :quantity %> + <%= f.number_field :quantity, min: 1, max: @product.quantity %> + + <%= f.submit class: "button" %> + <% end %> +
    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 690218ac22..7080e4c47a 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -15,7 +15,7 @@ <%= form_for @product do |f| %> <%= f.label :quantity %> <%= f.select :quantity, options_for_select(1..10)%> - <%= f.submit "Add to Cart", class: "button" %> + <%= link_to "Add to Cart",edit_product_orderproduct_path(@product.id) ,class: "button" %> <% end %>

    diff --git a/config/routes.rb b/config/routes.rb index 1fec2c3dc4..7de8c4281a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,11 +1,10 @@ Rails.application.routes.draw do -<<<<<<< HEAD + resources :orderproducts -======= root 'products#root', as: 'homepage' ->>>>>>> product_controller +resources :orderproducts #sessions get '/login', to: 'sessions#new', as: 'login_form' post '/login', to: 'sessions#create' @@ -16,6 +15,7 @@ resources :products resources :products do # add orderproducts (cart#index) + resources :orderproducts resources :reviews,only: [:new,:create] #resources :merchants, only: [:index] #resources :categories, only: [:index] From a3187626746a2e944df7b459faff2c419e83b5db Mon Sep 17 00:00:00 2001 From: Leticia Tran Date: Sun, 22 Apr 2018 15:44:16 -0700 Subject: [PATCH 083/252] Finished categories_controller tests for methods we have so far. --- .../controllers/categories_controller_test.rb | 122 +++++++++++++++--- 1 file changed, 103 insertions(+), 19 deletions(-) diff --git a/test/controllers/categories_controller_test.rb b/test/controllers/categories_controller_test.rb index 36e13c1822..ab0f04d02c 100644 --- a/test/controllers/categories_controller_test.rb +++ b/test/controllers/categories_controller_test.rb @@ -1,39 +1,123 @@ require "test_helper" describe CategoriesController do - it "should get index" do - get categories_index_url - value(response).must_be :success? + + describe "index" do + it "should get index" do + get categories_path + value(response).must_be :success? + end + it "succeeds when there are categories" do + get categories_path + + must_respond_with :success + end + + it "succeeds when there are no categories" do + Category.destroy_all + assert Category.all.empty? + get categories_path + must_respond_with :success + end end it "should get show" do - get categories_show_url + get categories_path(categories(:candy).id) value(response).must_be :success? end - it "should get new" do - get categories_new_url - value(response).must_be :success? + describe "new" do + it "should get new" do + get new_category_path + value(response).must_be :success? + end end - it "should get create" do - get categories_create_url - value(response).must_be :success? + describe "create" do + it "creates a category with valid data" do + + proc { + post categories_path, params: { + category: { + name: "New Category" + } + } + }.must_change 'Category.count', 1 + + # Assert + must_respond_with :redirect + must_redirect_to categories_path(Category.last.id) + end + + it "should get create" do + get categories_path + value(response).must_be :success? + end end - it "should get update" do - get categories_update_url - value(response).must_be :success? + describe 'update' do + it "should get update" do + get categories_path(categories(:candy).id) + value(response).must_be :success? + end + it "succeeds for valid data and an extant category ID" do + + patch category_path(categories(:candy).id), params: { + category: { + name: "Update name" + } + } + + must_respond_with :redirect + must_redirect_to categories_path(categories(:candy).id) + end + + it "renders bad_request for bogus data" do + + patch category_path(categories(:candy).id), params: { + category: { + doesnt_exists: "Update name" + } + } + + must_respond_with :redirect + end + + it "renders 404 not_found for a bogus category ID" do + patch category_path("wrong id") + + must_respond_with :missing # 404 + end end - it "should get edit" do - get categories_edit_url - value(response).must_be :success? + describe 'edit' do + it "should get edit" do + get categories_path(categories(:candy).id) + value(response).must_be :success? + end end - it "should get destroy" do - get categories_destroy_url - value(response).must_be :success? + describe 'destroy' do + it "should get destroy" do + get categories_path(categories(:candy).id) + value(response).must_be :success? + end + it "succeeds for an extant category ID" do + proc { + delete category_path(categories(:candy).id) + }.must_change 'Category.count', -1 + + must_respond_with :redirect + end + + it "renders 404 not_found and does not update the DB for a bogus category ID" do + proc { + delete category_path("wrond id") + }.must_change 'Category.count', 0 + + must_respond_with :missing + end end + end From 873c88acc2995c4f8ce46f8349f9accc8abdc13b Mon Sep 17 00:00:00 2001 From: Leticia Tran Date: Sun, 22 Apr 2018 15:45:01 -0700 Subject: [PATCH 084/252] Added method render_404 (not found) in application_controller. --- app/controllers/application_controller.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1c07694e9d..f7282f7a3f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,3 +1,8 @@ class ApplicationController < ActionController::Base protect_from_forgery with: :exception + + def render_404 + # raise ActionController::RoutingError.new('Not Found') + render text: 'Not Found', status: '404' + end end From e64b6e2077b4ccbb78922f5d924303cbd3ae71a7 Mon Sep 17 00:00:00 2001 From: Leticia Tran Date: Sun, 22 Apr 2018 15:46:20 -0700 Subject: [PATCH 085/252] Added line in catgeories#find_category to call application#render_404 if category not found. --- app/controllers/categories_controller.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index f91af42f7e..76a936ca57 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -31,6 +31,7 @@ def update redirect_to categories_path(@category) else flash.now[:status] = :failure + render :edit, status: :not_found end end @@ -51,5 +52,6 @@ def category_params def find_category @category = Category.find_by(id: params[:id]) + render_404 unless @category end end From 0902130a3ffca51415318230fc0b052501a92578 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Mon, 23 Apr 2018 09:14:10 -0700 Subject: [PATCH 086/252] starting merchant controller testing --- test/controllers/merchants_controller_test.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/controllers/merchants_controller_test.rb b/test/controllers/merchants_controller_test.rb index 0467f61ef1..ef69cbf7f9 100644 --- a/test/controllers/merchants_controller_test.rb +++ b/test/controllers/merchants_controller_test.rb @@ -2,12 +2,13 @@ describe MerchantsController do it "should get index" do - get merchants_index_url - value(response).must_be :success? + get merchants_path + + must_respond_with :success? end it "should get show" do - get merchants_show_url + get merchant_path(merchants(:one).id) value(response).must_be :success? end From 4ac83ad4cc96b2c844b2339f05d51c6115f951d4 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Mon, 23 Apr 2018 09:29:16 -0700 Subject: [PATCH 087/252] index and show --- test/controllers/merchants_controller_test.rb | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/test/controllers/merchants_controller_test.rb b/test/controllers/merchants_controller_test.rb index ef69cbf7f9..5ae6bc8819 100644 --- a/test/controllers/merchants_controller_test.rb +++ b/test/controllers/merchants_controller_test.rb @@ -4,37 +4,28 @@ it "should get index" do get merchants_path - must_respond_with :success? + must_respond_with :success end it "should get show" do get merchant_path(merchants(:one).id) - value(response).must_be :success? + + must_respond_with :success end it "should get new" do - get merchants_new_url - value(response).must_be :success? end it "should get create" do - get merchants_create_url - value(response).must_be :success? end it "should get edit" do - get merchants_edit_url - value(response).must_be :success? end it "should get update" do - get merchants_update_url - value(response).must_be :success? end it "should get destroy" do - get merchants_destroy_url - value(response).must_be :success? end end From 8aaa81cd54843efd194c59c6bb82fb78ae623b31 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Mon, 23 Apr 2018 09:37:37 -0700 Subject: [PATCH 088/252] Added OrderProducts methods --- app/controllers/orderproducts_controller.rb | 49 +++++++-------------- 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 34886b7329..4da68eaa4c 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -1,43 +1,31 @@ class OrderproductsController < ApplicationController before_action :find_orderproduct, only: [:edit, :update, :destroy] - def index @orderproducts = Orderproduct.all end - def show end - + def new + @orderproduct = Orderproduct.new(orderproduct_params) + @product = Product.find_by(id: params[:product_id]) + end def create - - if @order.nil? - @order = Order.create(status: "pending") - end - @op = @order.orderproducts.find_by(product_id: params[:id]) - if @op - @op.quantity += params[:orderproduct][:quantity].to_i - else - @op = Orderproduct.new(orderproduct_params) - @op.product_id = params[:id] - end - if @op.save - flash[:status] = :success - flash[:result_text] = "Successfully added to cart" - redirect_to product_path(params[:id]) + @product = Product.find_by(id: params[:product_id]) + @orderproduct = OrderProduct.new(orderproduct_params) + @orderproduct.product_id = @product.id + #@orderproduct.order_id = @order.id + if @orderproduct.save + status = :success + flash[:result_text] = "#{@orderproduct.quantity} #{@orderproduct.product.name} have been added to your order!" + redirect_to products_path else - flash[:status] = :failure - flash[:result_text] = "Sorry" - flash[:messages] = @op.errors.messages - redirect_to product_path(params[:id]), status: :bad_request + status = :bad_request + flash[:result_text] = "Error - products not added to your order" + render :new, status: status end end - - def new - end - def edit end - def update if @orderproduct.update(orderproduct_params) flash[:status] = :success @@ -50,7 +38,6 @@ def update render :edit end end - def destroy order = @orderproduct.order @orderproduct.destroy @@ -61,13 +48,11 @@ def destroy flash[:result_text] = "Successfully removed from your cart!" redirect_to orders_path end - - private def orderproduct_params - params.require(:order_product).permit(:quantity) + params.require(:order_product).permit(:quantity,:product_id) end def find_orderproduct - @order_product = Orderproduct.find_by(params[:id]) + @orderproduct = Orderproduct.find_by(id: params[:id]) end end From 7cff74bef897249963c8e6b9dadc4561b3f91495 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Mon, 23 Apr 2018 09:37:53 -0700 Subject: [PATCH 089/252] merchant controller methods --- app/controllers/merchants_controller.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 81b413a033..ad02731be6 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -13,15 +13,36 @@ def new end def create + @merchant = Merchant.new(merchant_params) + if @merchant.save + flash[:success] = "Merchant added!" + redirect_to merchants_path + else + flash.now[:alert] = @merchant.errors + render :new + end end def edit end def update + if @merchant.update(merchant_params) + flash[:success] = "#{@merchant.username} updated!" + redirect_to merchant_path(params[:id]) + else + render :edit + end end def destroy + if @merchant != nil + @merchant.destroy + flash[:success] = "#{@merchant} removed!" + else + flash.now[:alert] = "#{@merchant} does not exit!" + end + redirect_to merchants_path end private From ae75acdbe390b1c0a089600baece85f2ac24dd47 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Mon, 23 Apr 2018 09:51:56 -0700 Subject: [PATCH 090/252] Added calling 404 method on every find helper method if element is not found. --- app/controllers/merchants_controller.rb | 1 + app/controllers/orderproducts_controller.rb | 11 +++++++++++ app/controllers/orders_controller.rb | 1 + app/controllers/products_controller.rb | 1 + app/controllers/reviews_controller.rb | 1 + 5 files changed, 15 insertions(+) diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index ad02731be6..00892f55f7 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -53,5 +53,6 @@ def merchant_params def find_merchant @merchant = Merchant.find_by(id: params[:id]) + render_404 unless @merchant end end diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 4da68eaa4c..a5bdf8e9d4 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -1,14 +1,18 @@ class OrderproductsController < ApplicationController before_action :find_orderproduct, only: [:edit, :update, :destroy] + def index @orderproducts = Orderproduct.all end + def show end + def new @orderproduct = Orderproduct.new(orderproduct_params) @product = Product.find_by(id: params[:product_id]) end + def create @product = Product.find_by(id: params[:product_id]) @orderproduct = OrderProduct.new(orderproduct_params) @@ -24,8 +28,10 @@ def create render :new, status: status end end + def edit end + def update if @orderproduct.update(orderproduct_params) flash[:status] = :success @@ -38,6 +44,7 @@ def update render :edit end end + def destroy order = @orderproduct.order @orderproduct.destroy @@ -48,11 +55,15 @@ def destroy flash[:result_text] = "Successfully removed from your cart!" redirect_to orders_path end + private + def orderproduct_params params.require(:order_product).permit(:quantity,:product_id) end + def find_orderproduct @orderproduct = Orderproduct.find_by(id: params[:id]) + render_404 unless @orderproduct end end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index a93788f8c3..619c6c012f 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -32,5 +32,6 @@ def order_params def find_order @order = Order.find_by(id: params[:id]) + render_404 unless @order end end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 32d09dcabf..cbff0057e2 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -36,5 +36,6 @@ def product_params def find_product @product = Product.find_by(id: params[:id]) + render_404 unless @product end end diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index ca17a05e1b..cf9d5e0550 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -32,5 +32,6 @@ def review_params def find_review @review = Review.find_by(id: params[:id]) + render_404 unless @review end end From b3fe5363a1e99b2446abb76c637a78a971fe177d Mon Sep 17 00:00:00 2001 From: Aruna Date: Mon, 23 Apr 2018 10:18:26 -0700 Subject: [PATCH 091/252] fixed the reviews bug --- app/controllers/orderproducts_controller.rb | 17 ----------------- app/controllers/reviews_controller.rb | 4 ++-- app/models/review.rb | 2 +- app/views/categories/index.html.erb | 11 ++++------- app/views/products/show.html.erb | 7 +++++-- 5 files changed, 12 insertions(+), 29 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 1a0337fb34..389c4da2c1 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -9,21 +9,13 @@ def new @orderproduct = Orderproduct.new(orderproduct_params) @product = Product.find_by(id: params[:product_id]) end -<<<<<<< HEAD def create -======= - def create ->>>>>>> f0dcbc4480df5a45308b8470c830758917ea7076 @product = Product.find_by(id: params[:product_id]) @orderproduct = OrderProduct.new(orderproduct_params) @orderproduct.product_id = @product.id #@orderproduct.order_id = @order.id -<<<<<<< HEAD - -======= ->>>>>>> f0dcbc4480df5a45308b8470c830758917ea7076 if @orderproduct.save status = :success flash[:result_text] = "#{@orderproduct.quantity} #{@orderproduct.product.name} have been added to your order!" @@ -32,17 +24,8 @@ def create status = :bad_request flash[:result_text] = "Error - products not added to your order" render :new, status: status -<<<<<<< HEAD - - end - end - - - -======= end end ->>>>>>> f0dcbc4480df5a45308b8470c830758917ea7076 def edit end def update diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index 0f4e0064ce..d8b86b66f9 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -28,10 +28,10 @@ def create if @review.save flash[:success] = "#{@review.rating} saved" - redirect_to products_path + redirect_to product_path(@product.id) else flash[:alert] = "Could not create #{@review.rating}" - redirect_to products_path + redirect_to product_path(@product.id) end #end diff --git a/app/models/review.rb b/app/models/review.rb index 500bce10e9..b387047e55 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -3,5 +3,5 @@ class Review < ApplicationRecord validates :rating, presence: true validates :rating, :inclusion => 1..5 - validates :comment, length: { in: 1..250 } + # validates :comment, length: { in: 1..250 } end diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index 8f790bfd33..01081eca07 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -1,16 +1,13 @@ -<<<<<<< HEAD +

    Categories

    -======= ->>>>>>> product_controller +
      <% @categories.each do |category|%> -<<<<<<< HEAD +
    • <%= link_to category.name, category_path(category.id) %>
    • -======= -
    • <%= link_to categories.name, categories_path(category.id) %>
    • ->>>>>>> product_controller + <% end %>
    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 4a1bec6f91..fe1f0b0040 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -41,7 +41,10 @@ <% @product.reviews.each do |review| %>
  • - <% review.rating%> + <%review.rating.times do %> + <%= "🍦" %> + <% end %> +
  • <%= review.comment %> @@ -49,6 +52,6 @@ <%end %> <% end %> - +

    <%=link_to "review now!", new_product_review_path(@product.id), class: 'button' %>

    From 797193163aa3d9fb5c9c26c1c89bc4c5771198f2 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Mon, 23 Apr 2018 10:42:22 -0700 Subject: [PATCH 092/252] Added OmniAuth --- .gitignore | 1 + Gemfile | 5 +++ Gemfile.lock | 32 +++++++++++++- app/controllers/application_controller.rb | 6 ++- app/controllers/categories_controller.rb | 9 ++-- app/controllers/merchants_controller.rb | 1 + app/controllers/orderproducts_controller.rb | 3 +- app/controllers/orders_controller.rb | 3 +- app/controllers/products_controller.rb | 3 +- app/controllers/reviews_controller.rb | 3 +- app/controllers/sessions_controller.rb | 42 ++++++++++++------- app/models/merchant.rb | 16 +++++-- app/views/layouts/application.html.erb | 8 ++-- config/initializers/omniauth.rb | 3 ++ config/routes.rb | 10 +++-- .../20180423172301_add_auth_to_merchant.rb | 5 +++ ...0180423172432_add_provider_to_merchants.rb | 5 +++ db/schema.rb | 4 +- 18 files changed, 120 insertions(+), 39 deletions(-) create mode 100644 config/initializers/omniauth.rb create mode 100644 db/migrate/20180423172301_add_auth_to_merchant.rb create mode 100644 db/migrate/20180423172432_add_provider_to_merchants.rb diff --git a/.gitignore b/.gitignore index 82701fedc8..fd7861badf 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ /yarn-error.log .byebug_history +.env diff --git a/Gemfile b/Gemfile index 41afb43f6d..3f51d88b41 100644 --- a/Gemfile +++ b/Gemfile @@ -48,6 +48,8 @@ group :development do # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' + # for OmnAuth: + gem 'dotenv-rails' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem @@ -72,3 +74,6 @@ group :test do end gem 'faker', :git => 'https://github.com/stympy/faker.git', :branch => 'master' + +gem 'omniauth' +gem 'omniauth-github' diff --git a/Gemfile.lock b/Gemfile.lock index 344966d402..ceebc22432 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -76,8 +76,14 @@ GEM concurrent-ruby (1.0.5) crass (1.0.4) debug_inspector (0.0.3) + dotenv (2.3.0) + dotenv-rails (2.3.0) + dotenv (= 2.3.0) + railties (>= 3.2, < 6.0) erubi (1.7.1) execjs (2.7.0) + faraday (0.12.2) + multipart-post (>= 1.2, < 3) ffi (1.9.23) foundation-rails (6.4.3.0) railties (>= 3.1.0) @@ -85,6 +91,7 @@ GEM sprockets-es6 (>= 0.9.0) globalid (0.4.1) activesupport (>= 4.2.0) + hashie (3.5.7) i18n (1.0.1) concurrent-ruby (~> 1.0) jbuilder (2.7.0) @@ -97,6 +104,7 @@ GEM jquery-turbolinks (2.1.0) railties (>= 3.1.0) turbolinks + jwt (1.5.6) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -119,10 +127,27 @@ GEM minitest (>= 5.0) ruby-progressbar multi_json (1.13.1) + multi_xml (0.6.0) + multipart-post (2.0.0) nio4r (2.3.0) nokogiri (1.8.2) mini_portile2 (~> 2.3.0) normalize-rails (4.1.1) + oauth2 (1.4.0) + faraday (>= 0.8, < 0.13) + jwt (~> 1.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + omniauth (1.8.1) + hashie (>= 3.4.6, < 3.6.0) + rack (>= 1.6.2, < 3) + omniauth-github (1.3.0) + omniauth (~> 1.5) + omniauth-oauth2 (>= 1.4.0, < 2.0) + omniauth-oauth2 (1.5.0) + oauth2 (~> 1.1) + omniauth (~> 1.2) pg (1.0.0) pry (0.11.3) coderay (~> 1.1.0) @@ -198,9 +223,9 @@ GEM turbolinks-source (5.1.0) tzinfo (1.2.5) thread_safe (~> 0.1) - uglifier (4.1.9) + uglifier (4.1.10) execjs (>= 0.3.0, < 3) - web-console (3.6.0) + web-console (3.6.1) actionview (>= 5.0) activemodel (>= 5.0) bindex (>= 0.4.0) @@ -219,6 +244,7 @@ DEPENDENCIES binding_of_caller byebug capybara (~> 2.13) + dotenv-rails faker! foundation-rails jbuilder (~> 2.5) @@ -228,6 +254,8 @@ DEPENDENCIES minitest-rails minitest-reporters normalize-rails + omniauth + omniauth-github pg (>= 0.18, < 2.0) pry-rails puma (~> 3.7) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index f7282f7a3f..d068330d54 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,6 +3,10 @@ class ApplicationController < ActionController::Base def render_404 # raise ActionController::RoutingError.new('Not Found') - render text: 'Not Found', status: '404' + render text: 'Not Found', status: '404' + end + + def find_user + @merchant = Merchant.find_by(id: session[:merchant_id]) end end diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 76a936ca57..6dd96b219b 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -1,6 +1,7 @@ class CategoriesController < ApplicationController before_action :find_category, only: [:show, :edit, :update, :destroy] - + before_action :find_user + def index @categories = Category.all end @@ -40,8 +41,8 @@ def edit def destroy # shouls a user be able to delete a category? Maybe not... - @category.destroy if @category - redirect_to categories_path + @category.destroy if @category + redirect_to categories_path end private @@ -52,6 +53,6 @@ def category_params def find_category @category = Category.find_by(id: params[:id]) - render_404 unless @category + render_404 unless @category end end diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 00892f55f7..a50cc4ed9b 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -1,5 +1,6 @@ class MerchantsController < ApplicationController before_action :find_merchant, only: [:show, :edit, :update, :destroy] + before_action :find_user def index @merchants = Merchant.all diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index a5bdf8e9d4..7220925d6d 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -1,6 +1,7 @@ class OrderproductsController < ApplicationController before_action :find_orderproduct, only: [:edit, :update, :destroy] - + before_action :find_user + def index @orderproducts = Orderproduct.all end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 619c6c012f..dc9eb181db 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,6 +1,7 @@ class OrdersController < ApplicationController before_action :find_order, only: [:show, :edit, :update, :destroy] - + before_action :find_user + def index @orders = Order.all end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index cbff0057e2..18abf6b7e2 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,6 +1,7 @@ class ProductsController < ApplicationController before_action :find_product, only: [:show, :edit, :update, :destroy] - + before_action :find_user + def root @products = Product.all end diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index cf9d5e0550..639918d478 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -1,6 +1,7 @@ class ReviewsController < ApplicationController before_action :find_review, only: [:show, :edit, :update, :destroy] - + before_action :find_user + def index @reviews = Review.all end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 53c62f2b69..e097afc60b 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,4 +1,5 @@ class SessionsController < ApplicationController + def index end @@ -6,23 +7,32 @@ def show end def create - @merchant = Merchant.find_by(username: params[:merchant][:username]) + auth_hash = request.env['omniauth.auth'] - if @merchant - session[:merchant_id] = @merchant.id + if auth_hash[:uid] + @merchant = Merchant.find_by(uid: auth_hash[:uid], provider: 'github') + if @merchant.nil? + # it's a new merchant, we need to make a merchant + @merchant = Merchant.build_from_github(auth_hash) + successful_save = @merchant.save + if successful_save + flash[:success] = "Logged in successfully" + session[:merchant_id] = @merchant.id + redirect_to homepage_path + else + flash[:error] = "Some error happened in Merchant creation" + redirect_to homepage_path + end + else + flash[:success] = "Logged in successfully" + session[:merchant_id] = @merchant.id + redirect_to homepage_path + end - flash[:success] = "Welcome back #{@merchant.username}" - redirect_to root_path - else - @merchant = Merchant.create(username: params[:merchant][:username]) - if session[:merchant_id] = @merchant.id - flash[:success] = "Successfully logged in as #{@merchant.username}" - redirect_to root_path - else - flash.now[:error] = "You are not logged in. Please login" - render :new - end - end + else + flash[:error] = "Logging in via github not successful" + redirect_to homepage_path + end end def new @@ -32,6 +42,6 @@ def new def destroy session[:merchant_id] = nil flash[:success] = "You logged out!" - redirect_to root_path + redirect_to homepage_path end end diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 70f790d139..23eec15b5b 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -3,9 +3,17 @@ class Merchant < ApplicationRecord has_many :products validates :username, presence: true, - length: { :minimum => 0 }, - uniqueness: true + length: { :minimum => 0 }, + uniqueness: true validates :email, presence: true, - format: { with: VALID_EMAIL }, - uniqueness: { case_sensitive: false } + format: { with: VALID_EMAIL }, + uniqueness: { case_sensitive: false } + + def self.build_from_github(auth_hash) + Merchant.new( + provider: auth_hash[:provider], + uid: auth_hash[:uid], + email: auth_hash[:info][:email], + username: auth_hash[:info][:nickname]) + end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index a0ac0d0002..ae3a23d63b 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -57,11 +57,11 @@ - <% if @login_user %> - <%= link_to "Logged in as #{@login_user.username}", user_path(@login_user), class: "button" %> - <%= link_to "Log Out", logout_path, method: :post, class: "button" %> + <% if @merchant %> + <%= link_to "Logged in as #{@merchant.username}", merchant_path(@merchant), class: "button" %> + <%= link_to "Log Out", logout_path, method: :delete, class: "button" %> <% else %> - <%= link_to "Log In", login_path, class: "button" %> + <%= link_to "Log In", github_login_path, class: "button" %> <% end %> <%= link_to "Cart", cart_path, class: "button" %> diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb new file mode 100644 index 0000000000..f9b19612d1 --- /dev/null +++ b/config/initializers/omniauth.rb @@ -0,0 +1,3 @@ +Rails.application.config.middleware.use OmniAuth::Builder do + provider :github, ENV["GITHUB_CLIENT_ID"], ENV["GITHUB_CLIENT_SECRET"], scope: "user:email" +end diff --git a/config/routes.rb b/config/routes.rb index ba6a067915..79ed9ac037 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,10 +1,12 @@ Rails.application.routes.draw do - resources :orderproducts + # OmniAuth + get '/auth/:provider/callback', to: 'sessions#create' + get '/auth/github', as: 'github_login' #sessions - get '/login', to: 'sessions#new', as: 'login_form' - post '/login', to: 'sessions#create' + # get '/login', to: 'sessions#new', as: 'login_form' + # post '/login', to: 'sessions#create' delete '/login', to: 'sessions#destroy', as: 'logout' get '/cart', to:'orderproducts#index', as: 'cart' @@ -32,4 +34,6 @@ # Orders: resources :orders + # orderproducts: + resources :orderproducts end diff --git a/db/migrate/20180423172301_add_auth_to_merchant.rb b/db/migrate/20180423172301_add_auth_to_merchant.rb new file mode 100644 index 0000000000..02eb90e3cb --- /dev/null +++ b/db/migrate/20180423172301_add_auth_to_merchant.rb @@ -0,0 +1,5 @@ +class AddAuthToMerchant < ActiveRecord::Migration[5.1] + def change + add_column :merchants, :uid, :integer + end +end diff --git a/db/migrate/20180423172432_add_provider_to_merchants.rb b/db/migrate/20180423172432_add_provider_to_merchants.rb new file mode 100644 index 0000000000..3ca6a02f0a --- /dev/null +++ b/db/migrate/20180423172432_add_provider_to_merchants.rb @@ -0,0 +1,5 @@ +class AddProviderToMerchants < ActiveRecord::Migration[5.1] + def change + add_column :merchants, :provider, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index bc832008d1..f2a39e3f5f 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: 20180420233543) do +ActiveRecord::Schema.define(version: 20180423172432) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -35,6 +35,8 @@ t.string "email" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "uid" + t.string "provider" end create_table "orderproducts", force: :cascade do |t| From ad06f6bd7aba85f9cb622e73d3db5b57d5fd64f1 Mon Sep 17 00:00:00 2001 From: Aruna Date: Mon, 23 Apr 2018 10:44:13 -0700 Subject: [PATCH 093/252] added products --- app/views/orderproducts/edit.html.erb | 14 --------- app/views/orderproducts/new.html.erb | 9 ------ app/views/products/_review_form.html.erb | 12 ------- app/views/products/show.html.erb | 5 ++- config/routes.rb | 40 +++--------------------- 5 files changed, 7 insertions(+), 73 deletions(-) diff --git a/app/views/orderproducts/edit.html.erb b/app/views/orderproducts/edit.html.erb index 275074d611..8b13789179 100644 --- a/app/views/orderproducts/edit.html.erb +++ b/app/views/orderproducts/edit.html.erb @@ -1,15 +1 @@ - - - -

    Edit Order Item Quantity

    - -
    - <%= form_for @product do |f| %> - - <%= f.label :quantity %> - <%= f.number_field :quantity, min: 1, max: @product.quantity %> - - <%= f.submit class: "button" %> - <% end %> -
    diff --git a/app/views/orderproducts/new.html.erb b/app/views/orderproducts/new.html.erb index 9e443f3245..e69de29bb2 100644 --- a/app/views/orderproducts/new.html.erb +++ b/app/views/orderproducts/new.html.erb @@ -1,9 +0,0 @@ -
    - <%= form_for @product do |f| %> - - <%= f.label :quantity %> - <%= f.number_field :quantity, min: 1, max: @product.quantity %> - - <%= f.submit class: "button" %> - <% end %> -
    diff --git a/app/views/products/_review_form.html.erb b/app/views/products/_review_form.html.erb index 16cd361d66..e69de29bb2 100644 --- a/app/views/products/_review_form.html.erb +++ b/app/views/products/_review_form.html.erb @@ -1,12 +0,0 @@ -
    - <%= form_for @orderproducts do |f| %> - - <%= f.label :rating %> - <%= f.text_field :rating %> - - <%= f.label :comment %> - <%= f.text_area :comment %> - - <%= f.submit class: "button" %> - <% end %> -
    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index b00fec5aa6..2b2a753f40 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,6 +1,6 @@ -<<<<<<< HEAD + <%= render partial: "review_form" %> -======= +

    Product Details

    @@ -58,4 +58,3 @@

    <%=link_to "review now!", new_product_review_path(@product.id), class: 'button' %>

    ->>>>>>> product_controller diff --git a/config/routes.rb b/config/routes.rb index 55fe5447b8..7a02932891 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,63 +1,33 @@ Rails.application.routes.draw do -<<<<<<< HEAD -<<<<<<< HEAD - - resources :orderproducts - -======= -root 'products#root', as: 'homepage' ->>>>>>> product_controller -======= - resources :orderproducts - - - - root 'products#root', as: 'homepage' - ->>>>>>> testing #sessions get '/login', to: 'sessions#new', as: 'login_form' post '/login', to: 'sessions#create' delete '/login', to: 'sessions#destroy', as: 'logout' -<<<<<<< HEAD -<<<<<<< HEAD - - get '/cart', to:'orderproducts#index', as: 'cart' - -======= - # Reviews: - # ->>>>>>> product_controller -======= get '/cart', to:'orderproducts#index', as: 'cart' - # Reviews: - # ->>>>>>> testing + + # Products: resources :products resources :products do # add orderproducts (cart#index) -<<<<<<< HEAD -<<<<<<< HEAD + # resources :reviews, only: [:new] # resources :merchants, only: [:index] resources :categories, only: [:index] -======= + resources :reviews,only: [:new,:create] #resources :merchants, only: [:index] #resources :categories, only: [:index] ->>>>>>> product_controller -======= resources :reviews, only: [:new] @@ -71,7 +41,7 @@ #resources :merchants, only: [:index] #resources :categories, only: [:index] ->>>>>>> testing + end resources :reviews # Merchants: From 186761ac18d13ec07030d2a5cd24e8f80858c79e Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Mon, 23 Apr 2018 10:59:07 -0700 Subject: [PATCH 094/252] cleaned routes a bit --- config/routes.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 79ed9ac037..5d634dde55 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -14,9 +14,6 @@ # Products: root 'products#root', as: 'homepage' resources :products do - # add orderproducts (cart#index) - # resources :reviews, only: [:new] - # resources :merchants, only: [:index] resources :categories, only: [:index] end From 9fbb2b61921411e63ae0ce756853957d66ae9763 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Mon, 23 Apr 2018 11:24:48 -0700 Subject: [PATCH 095/252] Fixed merge conflicts --- app/controllers/reviews_controller.rb | 4 --- app/views/categories/index.html.erb | 8 +---- app/views/products/index.html.erb | 10 +----- db/schema.rb | 8 +---- db/seeds.rb | 44 +++------------------------ 5 files changed, 8 insertions(+), 66 deletions(-) diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index c9d531fe04..3fcd792000 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -47,10 +47,6 @@ def review_params def find_review @review = Review.find_by(id: params[:id]) -<<<<<<< HEAD - -======= render_404 unless @review ->>>>>>> 797193163aa3d9fb5c9c26c1c89bc4c5771198f2 end end diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index 4149ecc31c..da7d6fcf0a 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -1,23 +1,17 @@ -<<<<<<< HEAD -=======

    Categories

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

        <% @categories.each do |category|%> -======= ->>>>>>> testing
      • <%= link_to category.name, category_path(category.id) %>
      • <% end %> diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index fbe1ae9f6d..4ec3c90a88 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,12 +1,5 @@ - -<<<<<<< HEAD
        -
          - <% @products.each do |product|%> -
        • <%= link_to product.name, product_path(product.id) %>
        • - <% end %> -
        -======= + <% @products.each do |product| %>

        <%= link_to product.name, product_path(product.id) %> @@ -15,5 +8,4 @@ <% end %>

        <%= link_to("Add a Product", new_product_path, :class => "button") %> ->>>>>>> product_controller

        diff --git a/db/schema.rb b/db/schema.rb index ebf6c1e21d..9fa8004abd 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,9 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. - -ActiveRecord::Schema.define(version: 20180420210248) do - +ActiveRecord::Schema.define(version: 20180423172432) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -72,10 +70,8 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "description" - t.bigint "order_id" t.bigint "merchant_id" t.index ["merchant_id"], name: "index_products_on_merchant_id" - t.index ["order_id"], name: "index_products_on_order_id" end create_table "reviews", force: :cascade do |t| @@ -90,8 +86,6 @@ add_foreign_key "categories", "products" add_foreign_key "orderproducts", "orders" add_foreign_key "orderproducts", "products" - add_foreign_key "orders", "products" add_foreign_key "products", "merchants" - add_foreign_key "products", "orders" add_foreign_key "reviews", "products" end diff --git a/db/seeds.rb b/db/seeds.rb index eb76d5b256..ec3684ca4d 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -29,13 +29,7 @@ end puts "#{merchant.username} created!" end - -<<<<<<< HEAD -p "Created #{Product.count} desserts" -<<<<<<< HEAD -======= p "**Created #{Merchant.count} merchants**" ->>>>>>> a8bb6e39a663bebb847271ee5e0eefa1e3aded9e # Products @@ -44,40 +38,12 @@ product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.order("RANDOM()").first] , quantity: 2, merchant_id: Merchant.order("RANDOM()").first.id ) puts "#{product.name} created in the category: #{product.categories.first.name}" end - -<<<<<<< HEAD -<<<<<<< HEAD -p "Created #{Merchant.count} merchants" -======= -======= p "**Created #{Product.count} desserts**" -======= -p "Created #{Product.count} desserts" ->>>>>>> testing -REVIEW_FILE = Rails.root.join('db','seeds', 'reviews.csv') -puts "Loading raw review data from #{REVIEW_FILE}" -review_failures = [] + +# Reviews +REVIEW_FILE = Rails.root.join('db','seeds', 'reviews.csv') CSV.foreach(REVIEW_FILE, :headers => true) do |row| - review = Review.new - review.rating = row['rating'] - review.product_id = row['product_id'] - puts "Created review: #{review.inspect}" - successful = review.save - if !successful - puts review.errors - review_failures << review - end + review = Review.create(rating: row['rating'], product_id: row['product_id'] ) + puts "Review #{review.id} created with rating #{review.rating}" end - -puts "Added #{Review.count} review records" -puts "#{review_failures.length} reviews failed to save" -p review_failures -puts ->>>>>>> product_controller -<<<<<<< HEAD -======= -p "**Created #{Product.count} desserts**" ->>>>>>> a8bb6e39a663bebb847271ee5e0eefa1e3aded9e -======= ->>>>>>> testing From 19f37dc3038c494521ba54205995082522432d0d Mon Sep 17 00:00:00 2001 From: LetiTran Date: Mon, 23 Apr 2018 11:25:29 -0700 Subject: [PATCH 096/252] Fixed merge conflicts --- app/views/categories/index.html.erb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index da7d6fcf0a..b7354eb043 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -1,13 +1,6 @@

        Categories

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

          Categories

          -
            <% @categories.each do |category|%> From 944202a9125ac960f86bdf3ddc428ed02b4e5541 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Mon, 23 Apr 2018 12:14:17 -0700 Subject: [PATCH 097/252] Fixed model tests and merging conflicts --- app/models/order.rb | 6 ------ app/models/product.rb | 13 +------------ test/models/product_test.rb | 2 +- test/models/review_test.rb | 14 +++++++------- 4 files changed, 9 insertions(+), 26 deletions(-) diff --git a/app/models/order.rb b/app/models/order.rb index e0af1ed8da..06d4908ce4 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,15 +1,9 @@ class Order < ApplicationRecord VALID_EMAIL = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i -<<<<<<< HEAD - has_many :orderproducts - has_many :products, through: :orderproducts -======= has_many :orderproducts has_many :products, through: :orderproducts ->>>>>>> testing - validates :address, presence: true, length: { in: 1..35 } validates :card_name, presence: true, length: { minimum: 1 } validates :cc_number, presence: true, length: { is: 16 } diff --git a/app/models/product.rb b/app/models/product.rb index 5aa4a4adad..9842da2f01 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -5,23 +5,12 @@ class Product < ApplicationRecord has_many :reviews belongs_to :merchant - validates :name, presence: true, length: { minimum: 1 } validate :has_at_least_one_category validates_numericality_of :quantity, presence: true, greater_than_or_equal_to: 0 validates_numericality_of :price, presence: true, greater_than_or_equal_to: 0 + def average_rating - # if (self.reviews).count > 0 - # product_reviews = self.reviews - # sum_ratings = 0.0 - # product_reviews.each do |review| - # sum_ratings += review.rating - # end - # avg = sum_ratings/(product_reviews.count) - # return avg - # else - # return 0 - # end return "No reviews yet" if reviews.count == 0 sum = 0.0 self.reviews.each do |review| diff --git a/test/models/product_test.rb b/test/models/product_test.rb index 74716c3331..4b3ba36e96 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 name: "thing", price: 1, quantity: 2, categories: [Category.first, Category.last] } + let(:product) { Product.new(name: "A product", price: 1, quantity: 2, categories: [Category.first, Category.last], merchant_id: Merchant.first.id) } describe 'Validations' do it "must be valid" do diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 76f463210b..29c628bd07 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -1,7 +1,7 @@ require "test_helper" describe Review do - let(:review) { Review.new rating:1, comment:"hdjdjhjj" } + let(:review) { Review.new rating:1, comment:"A coment here" } describe "validations" do it "must be valid" do @@ -24,12 +24,12 @@ review.errors.must_include :rating end - it "must have a comment between 1 and 250 characters" do - review.comment = "" - - review.valid?.must_equal false - review.errors.must_include :comment - end + # it "must have a comment between 1 and 250 characters" do + # review.comment = "" + # + # review.valid?.must_equal false + # review.errors.must_include :comment + # end end describe "relations" do From b0d2e49a36ffef1a3182aebf34c5dc687059e7a0 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Mon, 23 Apr 2018 12:15:55 -0700 Subject: [PATCH 098/252] merge conflix --- app/controllers/reviews_controller.rb | 4 ---- app/models/order.rb | 6 ------ db/schema.rb | 7 ++----- test/models/review_test.rb | 6 ------ 4 files changed, 2 insertions(+), 21 deletions(-) diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index c9d531fe04..3fcd792000 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -47,10 +47,6 @@ def review_params def find_review @review = Review.find_by(id: params[:id]) -<<<<<<< HEAD - -======= render_404 unless @review ->>>>>>> 797193163aa3d9fb5c9c26c1c89bc4c5771198f2 end end diff --git a/app/models/order.rb b/app/models/order.rb index e0af1ed8da..06d4908ce4 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,15 +1,9 @@ class Order < ApplicationRecord VALID_EMAIL = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i -<<<<<<< HEAD - has_many :orderproducts - has_many :products, through: :orderproducts -======= has_many :orderproducts has_many :products, through: :orderproducts ->>>>>>> testing - validates :address, presence: true, length: { in: 1..35 } validates :card_name, presence: true, length: { minimum: 1 } validates :cc_number, presence: true, length: { is: 16 } diff --git a/db/schema.rb b/db/schema.rb index ebf6c1e21d..320e2cbd52 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,9 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. - -ActiveRecord::Schema.define(version: 20180420210248) do - +ActiveRecord::Schema.define(version: 20180423172432) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -45,8 +43,8 @@ t.integer "quantity" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.bigint "order_id" t.bigint "product_id" + t.bigint "order_id" t.index ["order_id"], name: "index_orderproducts_on_order_id" t.index ["product_id"], name: "index_orderproducts_on_product_id" end @@ -90,7 +88,6 @@ add_foreign_key "categories", "products" add_foreign_key "orderproducts", "orders" add_foreign_key "orderproducts", "products" - add_foreign_key "orders", "products" add_foreign_key "products", "merchants" add_foreign_key "products", "orders" add_foreign_key "reviews", "products" diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 76f463210b..fa21c37cc7 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -24,12 +24,6 @@ review.errors.must_include :rating end - it "must have a comment between 1 and 250 characters" do - review.comment = "" - - review.valid?.must_equal false - review.errors.must_include :comment - end end describe "relations" do From 987d3ae6a860a8d41525e96c5b83d9c5592d83ed Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Mon, 23 Apr 2018 13:21:49 -0700 Subject: [PATCH 099/252] sessions controller tests --- app/controllers/application_controller.rb | 5 ++ config/routes.rb | 4 +- test/controllers/sessions_controller_test.rb | 54 +++++++++++++------- test/fixtures/merchants.yml | 4 ++ test/models/review_test.rb | 1 - test/test_helper.rb | 27 +++++++++- 6 files changed, 72 insertions(+), 23 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d068330d54..96eae8d3c8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -6,7 +6,12 @@ def render_404 render text: 'Not Found', status: '404' end + private def find_user @merchant = Merchant.find_by(id: session[:merchant_id]) end + + def current_user + @current_user ||= Merchant.find(session[:merchant_id]) if session[:merchant_id] + end end diff --git a/config/routes.rb b/config/routes.rb index e74d747f6a..03bf13a298 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,7 @@ Rails.application.routes.draw do # OmniAuth - get '/auth/:provider/callback', to: 'sessions#create' + get '/auth/:provider/callback', to: 'sessions#create', as: 'auth_callback' get '/auth/github', as: 'github_login' root 'products#root', as: 'homepage' @@ -15,7 +15,7 @@ get '/cart', to:'orderproducts#index', as: 'cart' # Reviews: - + # Products: resources :products diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb index 9637f4bcbb..332ea9037b 100644 --- a/test/controllers/sessions_controller_test.rb +++ b/test/controllers/sessions_controller_test.rb @@ -1,29 +1,45 @@ require "test_helper" describe SessionsController do - it "should get index" do - get sessions_index_url - value(response).must_be :success? - end + describe "create" do + it "should log in an existing user and redirect to homepage" do + before_count = Merchant.count + existing_merchant = merchants(:one) - it "should get show" do - get sessions_show_url - value(response).must_be :success? - end + perform_login(existing_merchant) - it "should get new" do - get sessions_new_url - value(response).must_be :success? - end + must_redirect_to homepage_path + Merchant.count.must_equal before_count + end - it "should get create" do - get sessions_create_url - value(response).must_be :success? - end - it "should get destroy" do - get sessions_destroy_url - value(response).must_be :success? + it "should create a new user and redirect to homepage" do + new_user = Merchant.new( + provider: "github", + uid: 239802, + username: "test user", + email: "test@test.com" + ) + + proc { + perform_login(new_user) + }.must_change "Merchant.count", 1 + + must_respond_with :redirect + must_redirect_to homepage_path + end + + describe "destroy" do + it "should logout a user" do + existing_merchant = merchants(:two) + + perform_logout(existing_merchant) + + must_respond_with :redirect + must_redirect_to homepage_path + end + end + end end diff --git a/test/fixtures/merchants.yml b/test/fixtures/merchants.yml index 26cea88b83..058f8271fb 100644 --- a/test/fixtures/merchants.yml +++ b/test/fixtures/merchants.yml @@ -3,7 +3,11 @@ one: username: merchant-one email: hello@hello.com + provider: github + uid: 1222 two: username: merchant-two email: goodbye@goodbye.com + provider: github + uid: 22222 diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 65888dd6b5..a6a6525e64 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -23,7 +23,6 @@ review.valid?.must_equal false review.errors.must_include :rating end - end describe "relations" do diff --git a/test/test_helper.rb b/test/test_helper.rb index 10594a3248..22253bc47e 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -11,7 +11,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" @@ -23,4 +22,30 @@ 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... + def setup + OmniAuth.config.test_mode = true + end + + def mock_auth_hash(user) + return { + provider: user.provider, + uid: user.uid, + info: { + email: user.email, + nickname: user.username + } + } + end + + def perform_login(user) + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) + + get auth_callback_path(user.provider) + end + + def perform_logout(user) + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) + + delete logout_path(user.uid) + end end From b7ef025b02e56e2026ac66b1a312211fdfc66167 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Mon, 23 Apr 2018 13:22:00 -0700 Subject: [PATCH 100/252] Added some tests for products controller --- test/controllers/products_controller_test.rb | 88 +++++++++++++++----- 1 file changed, 67 insertions(+), 21 deletions(-) diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index a00ad0e288..f87cab1c4d 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -1,39 +1,85 @@ require "test_helper" +require "pry" describe ProductsController do - it "should get index" do - get products_index_url - value(response).must_be :success? + + describe 'root' do + it 'should work with all products' do + get homepage_path + must_respond_with :success + end + + it 'should work with no products' do + Product.destroy_all + assert Product.all.empty? + get homepage_path + must_respond_with :success + end end - it "should get show" do - get products_show_url - value(response).must_be :success? + describe 'index' do + it 'should get all products' do + get products_path + must_respond_with :success + end + + it 'should work with no products' do + Product.destroy_all + assert Product.all.empty? + get products_path + must_respond_with :success + end end - it "should get new" do - get products_new_url - value(response).must_be :success? + describe 'show' do + it 'should show details of a product' do + get products_path(products(:candy).id) + must_respond_with :success + end + it 'should return 404 for a bogus id' do + get products_path("wrong id") + must_respond_with :success + end end - it "should get create" do - get products_create_url - value(response).must_be :success? + describe 'new' do + it 'should create a new Product' do + get new_product_path + must_respond_with :success + end + end - it "should get edit" do - get products_edit_url - value(response).must_be :success? + describe 'create' do + it 'creates a work with valid id' do + perform_login(existing_merchant) + proc { + post products_path, params: { + product: { + name: "A product", + price: 1, + quantity: 2, + categories: [Category.first, Category.last], + merchant_id: @merchant.id + } + } + }.must_change 'Product.count', 1 + + # Assert + must_respond_with :redirect + must_redirect_to work_path(Product.last.id) + + end + end - it "should get update" do - get products_update_url - value(response).must_be :success? + describe 'edit' do + end + describe 'update' do - it "should get destroy" do - get products_destroy_url - value(response).must_be :success? end + describe 'destroy' do + end end From e3215ed7be2287eef31508c4c38f0a1f6b9bed72 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Mon, 23 Apr 2018 13:22:25 -0700 Subject: [PATCH 101/252] Fixed Products#create --- app/controllers/products_controller.rb | 6 +++--- app/views/products/new.html.erb | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 8ad69f5d22..1fcd193510 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,7 +1,7 @@ class ProductsController < ApplicationController before_action :find_product, only: [:show, :edit, :update, :destroy] before_action :find_user - + def root @products = Product.all end @@ -19,7 +19,7 @@ def new def create @product = Product.new(product_params) - #@product.merchant_id = session[:merchant_id] + @product.merchant_id = @merchant.id if @product.save flash[:status] = :success redirect_to products_path @@ -55,7 +55,7 @@ def destroy private def product_params - return params.require(:product).permit(:name, :price, :quantity, :description) + return params.require(:product).permit(:name, :price, :quantity, :description, :category_ids => []) end def find_product diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index 892ff2837b..f282700779 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -1,4 +1,5 @@ <%= form_for @product do |f| %> +<%= f.hidden_field :product_id, value: @product.id %> <%= f.label :name %> <%= f.text_field :name %> @@ -10,6 +11,7 @@ <%= f.label :description %> <%= f.text_area :description %> + <%= f.collection_check_boxes :category_ids, Category.all, :id, :name do |b| %> <%= b.check_box %> <%= b.label %> From f785c5432c55d7ddf1fe54c8f657b0d757d5cbb7 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Mon, 23 Apr 2018 14:32:25 -0700 Subject: [PATCH 102/252] merchant and sessions controller testing --- app/controllers/application_controller.rb | 2 +- app/controllers/merchants_controller.rb | 72 +++++++++---------- app/controllers/products_controller.rb | 4 +- app/controllers/reviews_controller.rb | 1 - app/controllers/sessions_controller.rb | 8 +-- app/views/orderproducts/index.html.erb | 2 +- test/controllers/merchants_controller_test.rb | 31 ++++---- 7 files changed, 60 insertions(+), 60 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 96eae8d3c8..f4041d3ca2 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -8,7 +8,7 @@ def render_404 private def find_user - @merchant = Merchant.find_by(id: session[:merchant_id]) + @user = Merchant.find_by(id: session[:merchant_id]) end def current_user diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index a50cc4ed9b..eb3b43daf0 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -9,42 +9,42 @@ def index def show end - def new - @merchant = Merchant.new - end - - def create - @merchant = Merchant.new(merchant_params) - if @merchant.save - flash[:success] = "Merchant added!" - redirect_to merchants_path - else - flash.now[:alert] = @merchant.errors - render :new - end - end - - def edit - end - - def update - if @merchant.update(merchant_params) - flash[:success] = "#{@merchant.username} updated!" - redirect_to merchant_path(params[:id]) - else - render :edit - end - end - - def destroy - if @merchant != nil - @merchant.destroy - flash[:success] = "#{@merchant} removed!" - else - flash.now[:alert] = "#{@merchant} does not exit!" - end - redirect_to merchants_path - end + # def new + # @merchant = Merchant.new + # end + # + # def create + # @merchant = Merchant.new(merchant_params) + # if @merchant.save + # flash[:success] = "Merchant added!" + # redirect_to merchants_path + # else + # flash.now[:alert] = @merchant.errors + # render :new + # end + # end + # + # def edit + # end + # + # def update + # if @merchant.update(merchant_params) + # flash[:success] = "#{@merchant.username} updated!" + # redirect_to merchant_path(params[:id]) + # else + # render :edit + # end + # end + + # def destroy + # if @merchant != nil + # @merchant.destroy + # flash[:success] = "#{@merchant} removed!" + # else + # flash.now[:alert] = "#{@merchant} does not exit!" + # end + # redirect_to merchants_path + # end private diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 8ad69f5d22..e739760a23 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,7 +1,7 @@ class ProductsController < ApplicationController before_action :find_product, only: [:show, :edit, :update, :destroy] before_action :find_user - + def root @products = Product.all end @@ -31,7 +31,6 @@ def create end def edit - end def update @@ -40,7 +39,6 @@ def update redirect_to product_path(@product.id) else flash[:alert] = "A problem occured:Could not update" - render :edit end end diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index 3fcd792000..1267507cbb 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -13,7 +13,6 @@ def show def new @review = Review.new @product = Product.find_by(id: params[:product_id]) - end def create diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index e097afc60b..ec86d3f375 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -6,6 +6,10 @@ def index def show end + def new + @merchant = Merchant.new + end + def create auth_hash = request.env['omniauth.auth'] @@ -35,10 +39,6 @@ def create end end - def new - @merchant = Merchant.new - end - def destroy session[:merchant_id] = nil flash[:success] = "You logged out!" diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index 88a61e710e..1e528bd476 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -1 +1 @@ -Cart +

            <%= @user.username %> Cart

            diff --git a/test/controllers/merchants_controller_test.rb b/test/controllers/merchants_controller_test.rb index 5ae6bc8819..f1ee7f13b3 100644 --- a/test/controllers/merchants_controller_test.rb +++ b/test/controllers/merchants_controller_test.rb @@ -13,19 +13,22 @@ must_respond_with :success end - it "should get new" do - end - - it "should get create" do - end - - it "should get edit" do - end - - it "should get update" do - end - - it "should get destroy" do - end + # it "should get create" do + # initial = Merchant.count + # post merchants_path + # + # Merchant.count.must_equal initial + 1 + # must_respond_with :redirect + # must_redirect_to merchants_path + # end + + # it "should get edit" do + # end + # + # it "should get update" do + # end + # + # it "should get destroy" do + # end end From d526aa7393813981e721cdfa7463bb04657b4a17 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Mon, 23 Apr 2018 14:33:49 -0700 Subject: [PATCH 103/252] Fixed products_controller#edit and create --- app/controllers/products_controller.rb | 15 ++++++++++----- test/controllers/products_controller_test.rb | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 1fcd193510..9e842cfa0a 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -19,10 +19,10 @@ def new def create @product = Product.new(product_params) - @product.merchant_id = @merchant.id + assign_merchant_id if @product.save flash[:status] = :success - redirect_to products_path + redirect_to product_path(@product.id) else flash[:failure] = :failure flash.now[:result_text]= "Error: product was not added" @@ -31,23 +31,24 @@ def create end def edit - end def update + @product.merchant_id = @merchant.id + assign_merchant_id if @product.update(product_params) flash[:success] = "#{@product.name} updated" redirect_to product_path(@product.id) else + binding.pry flash[:alert] = "A problem occured:Could not update" - render :edit end end def destroy if @product.destroy - flash[:message] = "Deleted #{@product.category} #{@product.name}" + flash[:message] = "Deleted #{@product.name}" redirect_to products_path end end @@ -62,4 +63,8 @@ def find_product @product = Product.find_by(id: params[:id]) render_404 unless @product end + + def assign_merchant_id + @product.merchant_id = @merchant.id + end end diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index f87cab1c4d..22c769d974 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -60,7 +60,7 @@ price: 1, quantity: 2, categories: [Category.first, Category.last], - merchant_id: @merchant.id + merchant_id: existing_merchant } } }.must_change 'Product.count', 1 From 8dd236acc40497bc2f5fbae64e6bc59868767f4d Mon Sep 17 00:00:00 2001 From: LetiTran Date: Mon, 23 Apr 2018 14:34:17 -0700 Subject: [PATCH 104/252] Finished tests on products controller. --- app/views/products/show.html.erb | 82 +++++++++--------- test/controllers/products_controller_test.rb | 91 ++++++++++++++++++-- 2 files changed, 126 insertions(+), 47 deletions(-) diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 2b2a753f40..591b25c8f2 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -8,53 +8,53 @@ <%= image_tag ('https://placeimg.com/350/200/nature') %>
    -
    -

    <%= "Product : #{@product.name}" %>

    - <%= "Stock: #{@product.quantity}" %> +
    +

    <%= "Product : #{@product.name}" %>

    + <%= "Stock: #{@product.quantity}" %> -

    <%= "Price:#{ @product.price}" %>

    +

    <%= "Price:#{ @product.price}" %>

    - <%= form_for @product do |f| %> - <%= f.label :quantity %> - <%= f.select :quantity, options_for_select(1..10)%> - <%= link_to "Add to Cart",edit_product_orderproduct_path(@product.id) ,class: "button" %> - <% end %> + <%= form_for @product do |f| %> + <%= f.label :quantity %> + <%= f.select :quantity, options_for_select(1..10)%> + <%= link_to "Add to Cart",edit_product_orderproduct_path(@product.id) ,class: "button" %> + <% end %> -

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

    +

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

    -
    +
    -

    Ratings Summary

    -

    - <%="Average rating: #{@product.average_rating}" %> -

    -
    -
    -

    Rating

    - <% if @product.reviews.empty? %> -

    - Be the first to review! -

    - <%else %> -
      - <% @product.reviews.each do |review| %> -
      -
    • - <%review.rating.times do %> - <%= "🍦" %> - <% end %> - -
    • -

      - <%= review.comment %> -

      - <%end %> -
    +

    Ratings Summary

    +

    + <%="Average rating: #{@product.average_rating}" %> +

    +
    +
    +

    Rating

    + <% if @product.reviews.empty? %> +

    + Be the first to review! +

    + <%else %> +
      + <% @product.reviews.each do |review| %> +
      +
    • + <%review.rating.times do %> + <%= "🍦" %> <% end %> -

      <%=link_to "review now!", new_product_review_path(@product.id), class: 'button' %>

      -
    + +

    + <%= review.comment %> +

    + <%end %> + + <% end %> + +

    <%=link_to "review now!", new_product_review_path(@product.id), class: 'button' %>

    + diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index 22c769d974..3a19aa6994 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -51,7 +51,8 @@ end describe 'create' do - it 'creates a work with valid id' do + it 'creates a product with valid id' do + existing_merchant = merchants(:one) perform_login(existing_merchant) proc { post products_path, params: { @@ -59,27 +60,105 @@ name: "A product", price: 1, quantity: 2, - categories: [Category.first, Category.last], - merchant_id: existing_merchant + :category_ids => [categories(:candy).id], + merchant_id: existing_merchant.id } } }.must_change 'Product.count', 1 # Assert must_respond_with :redirect - must_redirect_to work_path(Product.last.id) - + must_redirect_to product_path(Product.last.id) end end describe 'edit' do - + it 'should get edit for a valid id' do + get edit_product_path(products(:candy).id) + must_respond_with :success + end + it 'should not work for a bogus id' do + get edit_product_path("wrong id") + must_respond_with :missing + end end + describe 'update' do + it 'updates a product with valid id' do + existing_merchant = merchants(:one) + perform_login(existing_merchant) + + proc { + patch product_path(products(:candy).id), params: { + product: { + name: "A product", + price: 1, + quantity: 2, + :category_ids => [categories(:candy).id], + merchant_id: existing_merchant.id + } + } + }.must_change 'Product.count', 0 + + # Assert + must_respond_with :redirect + must_redirect_to product_path(products(:candy).id) + end + + it 'renders 404 for a bogus id' do + existing_merchant = merchants(:one) + perform_login(existing_merchant) + + proc { + patch product_path("wrong id"), params: { + product: { + name: "A product", + price: 1, + quantity: 2, + :category_ids => [categories(:candy).id], + merchant_id: existing_merchant.id + } + } + }.must_change 'Product.count', 0 + # Assert + must_respond_with 404 + end + + it "renders bad_request for bogus data" do + existing_merchant = merchants(:one) + perform_login(existing_merchant) + + patch product_path(products(:two).id), params: { + product: { + doesnt_exists: "Update title", + price: 1, + quantity: 2, + :category_ids => [categories(:candy).id], + merchant_id: existing_merchant.id + } + } + + must_respond_with :redirect + end end + describe 'destroy' do + it "succeeds for an extant product ID" do + proc { + delete product_path(products(:two).id) + }.must_change 'Product.count', -1 + must_respond_with :redirect + end + + it "renders 404 not_found and does not update the DB for a bogus product ID" do + proc { + delete product_path('bad id') + }.must_change 'Product.count', 0 + + must_respond_with 404 + end end end From fecea0151dfc9f7fd4c7c84ab4e5f099f1b1520d Mon Sep 17 00:00:00 2001 From: Aruna Date: Mon, 23 Apr 2018 14:40:03 -0700 Subject: [PATCH 105/252] review controller testing passed --- app/controllers/reviews_controller.rb | 5 +- app/views/orderproducts/edit.html.erb | 13 ++++ test/controllers/reviews_controller_test.rb | 70 +++++++++++++-------- test/fixtures/reviews.yml | 8 +-- 4 files changed, 63 insertions(+), 33 deletions(-) diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index 3fcd792000..c269daa576 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -7,13 +7,13 @@ def index end def show - @reviews = Review + end def new @review = Review.new @product = Product.find_by(id: params[:product_id]) - + end def create @@ -34,6 +34,7 @@ def create flash[:alert] = "Could not create #{@review.rating}" redirect_to product_path(@product.id) + end #end end diff --git a/app/views/orderproducts/edit.html.erb b/app/views/orderproducts/edit.html.erb index 8b13789179..2485ab7b7f 100644 --- a/app/views/orderproducts/edit.html.erb +++ b/app/views/orderproducts/edit.html.erb @@ -1 +1,14 @@ + +

    Edit Order Item Quantity

    + +
    + <%= form_for @orderproduct do |f| %> + <%= f.hidden_field :product_id, value: @product.id %> + + <%= f.label :quantity %> + <%= f.number_field :quantity, min: 1, max: @product.quantity %> + + <%= f.submit class: "button" %> + <% end %> +
    diff --git a/test/controllers/reviews_controller_test.rb b/test/controllers/reviews_controller_test.rb index 211b509ebe..4af252760d 100644 --- a/test/controllers/reviews_controller_test.rb +++ b/test/controllers/reviews_controller_test.rb @@ -1,39 +1,55 @@ require "test_helper" describe ReviewsController do - it "should get index" do - get reviews_index_url - value(response).must_be :success? - end - - it "should get show" do - get reviews_show_url - value(response).must_be :success? - end + describe "index" do + it "should get index" do + get reviews_path + must_respond_with :success + end - it "should get new" do - get reviews_new_url - value(response).must_be :success? end - - it "should get create" do - get reviews_create_url - value(response).must_be :success? + describe "show" do + it "should get show" do + get reviews_path(reviews(:candy).id) + value(response).must_be :success? + end end - it "should get update" do - get reviews_update_url - value(response).must_be :success? - end + describe "new" do + it "should get new" do - it "should get edit" do - get reviews_edit_url - value(response).must_be :success? + get new_product_review_path(products(:candy).id) + must_respond_with :success + end end - it "should get destroy" do - get reviews_destroy_url - value(response).must_be :success? + describe "create" do + it "creates a review with valid data" do + + proc { + post reviews_path, params: { + review: { + product_id: products(:candy).id, + rating: 2, + comment:"reviewtext" + } + } + }.must_change 'Review.count', 1 + + # Assert + must_respond_with :redirect + must_redirect_to product_path(Product.last.id) + end + + it " does not update the DB for bogus data" do + review_data = { + review: { + product_id: products(:candy).id, + rating: nil + } + } + start_count = Review.count + Review.count.must_equal start_count + end end - end diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml index 9c5cbbf36f..523a53e89a 100644 --- a/test/fixtures/reviews.yml +++ b/test/fixtures/reviews.yml @@ -1,9 +1,9 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: - rating: 1 - comment: MyString +candy: + rating: 2 + comment: reviewtext two: - rating: 1 + rating: 3 comment: MyString From ca62b6a7788079485653ee148b6fdbca1d27b1b5 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Mon, 23 Apr 2018 15:16:37 -0700 Subject: [PATCH 106/252] Added new file for checkout form with buyer information --- app/views/orders/_checkout_form.html.erb | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 app/views/orders/_checkout_form.html.erb diff --git a/app/views/orders/_checkout_form.html.erb b/app/views/orders/_checkout_form.html.erb new file mode 100644 index 0000000000..05828bedd5 --- /dev/null +++ b/app/views/orders/_checkout_form.html.erb @@ -0,0 +1,27 @@ + +<%= form_for @order do |f| %> + +<%= f.label :address %> +<%= f.text_field :address %> + +<%= f.label :card_name %> +<%= f.text_field :card_name %> + +<%= f.label :cc_number %> +<%= f.text_field :cc_number %> + +<%= f.label :cc_expiration %> +<%= f.text_field :cc_expiration %> + +<%= f.label :cvv %> +<%= f.text_field :cvv %> + +<%= f.label :zip_code %> +<%= f.text_field :zip_code %> + +<%= f.label :email %> +<%= f.text_field :email %> + +<%= f.submit %> + +<% end %> From 0ab9afeb08a922249a4737139725188d6df41a82 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Mon, 23 Apr 2018 15:17:07 -0700 Subject: [PATCH 107/252] Added path to new order form --- app/views/orders/new.html.erb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/views/orders/new.html.erb b/app/views/orders/new.html.erb index 1bc27609ce..eb56826fe4 100644 --- a/app/views/orders/new.html.erb +++ b/app/views/orders/new.html.erb @@ -1,2 +1 @@ -

    Orders#new

    -

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

    +<%= render partial: "checkout_form", locals: { page_title: "Checkout" } %> From cda27c9fb91f86fb3afcf1b5c89250b0aeccb386 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Tue, 24 Apr 2018 09:42:15 -0700 Subject: [PATCH 108/252] Added flash messages --- app/views/layouts/application.html.erb | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index ae3a23d63b..a00a7664aa 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -69,7 +69,21 @@ - + <% if flash[:result_text] or flash[:messages] %> +
    +

    <%= flash[:status] == :failure ? "A problem occurred: " : "" %><%= flash[:result_text] %>

    + <% if flash[:messages] %> +
      + <% flash[:messages].each do |name, problems| %> + <% problems.each do |problem| %> +
    • <%= name %>: <%= problem %>
    • + <% end %> + <% end %> +
    + <% end %> +
    + <% end %> + <%= yield %> From 71cd2c65f9364b7c80b11d1f345357ccfd63f486 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Tue, 24 Apr 2018 09:43:46 -0700 Subject: [PATCH 109/252] Added first tests for orders_controller --- test/controllers/orders_controller_test.rb | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 2f00b03123..a201ec7aea 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -1,10 +1,22 @@ + require "test_helper" describe OrdersController do - it "should get index" do - get orders_index_url - value(response).must_be :success? - end + describe 'index' do + describe 'index' do + it 'should get all products' do + get orders_path + must_respond_with :success + end + + it 'should work with no products' do + Order.destroy_all + assert Order.all.empty? + get orders_path + must_respond_with :success + end + end + end it "should get show" do get orders_show_url From b1b2643577076ce985f43314c611d4838b87802d Mon Sep 17 00:00:00 2001 From: Aruna Date: Tue, 24 Apr 2018 09:51:27 -0700 Subject: [PATCH 110/252] working on order_products --- app/controllers/application_controller.rb | 8 ++++++++ app/controllers/orderproducts_controller.rb | 16 +++++++++------- app/models/product.rb | 16 ++++++++-------- app/views/orderproducts/show.html.erb | 7 +++++-- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index f4041d3ca2..06bcd63b34 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -14,4 +14,12 @@ def find_user def current_user @current_user ||= Merchant.find(session[:merchant_id]) if session[:merchant_id] end + + def current_order + if !session[:order_id].nil? + Order.find(session[:order_id]) + else + Order.new + end + end end diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 905219b427..770bd9d1b9 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -1,12 +1,13 @@ class OrderproductsController < ApplicationController before_action :find_orderproduct, only: [:edit, :update, :destroy] - before_action :find_user - + before_action :find_user,:current_order + def index @orderproducts = Orderproduct.all end def show + @orderproducts = current_order.orderproducts end def new @@ -15,11 +16,12 @@ def new end def create + @order = current_order + @orderproduct = @order.orderproducts.new(orderproduct_params) + @order.save + session[:order_id] = @order.id + - @product = Product.find_by(id: params[:product_id]) - @orderproduct = OrderProduct.new(orderproduct_params) - @orderproduct.product_id = @product.id - #@orderproduct.order_id = @order.id if @orderproduct.save status = :success flash[:result_text] = "#{@orderproduct.quantity} #{@orderproduct.product.name} have been added to your order!" @@ -61,7 +63,7 @@ def destroy private def orderproduct_params - params.require(:order_product).permit(:quantity,:product_id) + params.require(:orderproduct).permit(:quantity,:product_id) end def find_orderproduct diff --git a/app/models/product.rb b/app/models/product.rb index 9842da2f01..0c7cffa16b 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,28 +1,28 @@ class Product < ApplicationRecord - has_many :orderproducts - has_many :orders, through: :orderproducts + has_many :orders,through: :orderproduct has_and_belongs_to_many :categories, join_table: "category_product" has_many :reviews - belongs_to :merchant + validates :name, presence: true, length: { minimum: 1 } - validate :has_at_least_one_category + validate :has_atleast_one_category validates_numericality_of :quantity, presence: true, greater_than_or_equal_to: 0 validates_numericality_of :price, presence: true, greater_than_or_equal_to: 0 - def average_rating + return "No reviews yet" if reviews.count == 0 sum = 0.0 - self.reviews.each do |review| + products.reviews.each do |review| sum += review.rating end return (sum/reviews.count) end private - def has_at_least_one_category + def has_atleast_one_category + if categories.empty? - errors.add(:categories, "must have at_least one category") + errors.add(:categories, "must have atleat one category") end end diff --git a/app/views/orderproducts/show.html.erb b/app/views/orderproducts/show.html.erb index a35500b556..b4aa4666a5 100644 --- a/app/views/orderproducts/show.html.erb +++ b/app/views/orderproducts/show.html.erb @@ -1,2 +1,5 @@ -

    Orderproducts#show

    -

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

    +

    <%= @user.username %> Cart

    + +<% @orderproduct.products.each do |product| %> +Item: <%= product.name %> +<% end %> From f0a4122de8d19b5bf6ae7883dfdca30cc04c33c8 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Tue, 24 Apr 2018 09:52:14 -0700 Subject: [PATCH 111/252] Order can be created. --- app/controllers/orders_controller.rb | 18 ++++++-- test/controllers/orders_controller_test.rb | 49 ++++++++++------------ 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index dc9eb181db..d44f8661e1 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,7 +1,7 @@ class OrdersController < ApplicationController before_action :find_order, only: [:show, :edit, :update, :destroy] before_action :find_user - + def index @orders = Order.all end @@ -10,10 +10,22 @@ def show end def new - @order = Order.new + @order = Order.new() + end def create + @order = Order.new(order_params) + + # binding.pry + if @order.save + flash[:status] = + redirect_to order_path(@order.id) + else + flash[:failure] = :failure + flash.now[:result_text]= "Error: Order was not created" + render :new + end end def update @@ -28,7 +40,7 @@ def destroy private def order_params - return params.require(:order).permit(:status, :email, :address, :card_name, :cc_number, :cc_expiration, :cvv, :zip_code) + return params.require(:order).permit( :email, :address, :card_name, :cc_number, :cc_expiration, :cvv, :zip_code) end def find_order diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index a201ec7aea..33aaeb45cb 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -18,34 +18,31 @@ end end - it "should get show" do - get orders_show_url - value(response).must_be :success? - end - - it "should get new" do - get orders_new_url - value(response).must_be :success? - end - - it "should get create" do - get orders_create_url - value(response).must_be :success? - end - - it "should get update" do - get orders_update_url - value(response).must_be :success? - end + describe 'create' do + it 'creates a product with valid id' do + existing_merchant = merchants(:one) + perform_login(existing_merchant) + proc { + post orders_path, params: { + order: { + email: "test@test.com", + address: "A address", + card_name: "A card name", + cc_number: "1234567890123456", + cc_expiration: "03-02-2019", + cvv: "123", + zip_code: "98000", + # merchant_id: existing_merchant.id + } + } + }.must_change 'Order.count', 1 + + # Assert + must_respond_with :redirect + must_redirect_to order_path(Order.last.id) + end - it "should get edit" do - get orders_edit_url - value(response).must_be :success? end - it "should get destroy" do - get orders_destroy_url - value(response).must_be :success? - end end From b833856e52134711bc203d1c181180593d440f8d Mon Sep 17 00:00:00 2001 From: LetiTran Date: Tue, 24 Apr 2018 09:59:45 -0700 Subject: [PATCH 112/252] Removed order validations for now, will do it in a different way for when order status become paid. --- app/controllers/orders_controller.rb | 1 - app/models/order.rb | 18 +++++++++--------- test/controllers/orders_controller_test.rb | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index d44f8661e1..b56315e8d1 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -19,7 +19,6 @@ def create # binding.pry if @order.save - flash[:status] = redirect_to order_path(@order.id) else flash[:failure] = :failure diff --git a/app/models/order.rb b/app/models/order.rb index 06d4908ce4..1c09680e20 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -4,13 +4,13 @@ class Order < ApplicationRecord has_many :orderproducts has_many :products, through: :orderproducts - validates :address, presence: true, length: { in: 1..35 } - validates :card_name, presence: true, length: { minimum: 1 } - validates :cc_number, presence: true, length: { is: 16 } - validates :cc_expiration, presence: true - validates :cvv, presence: true, length: { is: 3 } - validates :zip_code, presence: true, length: { is: 5 } - validates :email, presence: true, - format: { with: VALID_EMAIL }, - uniqueness: { case_sensitive: false } + # validates :address, presence: true, length: { in: 1..35 } + # validates :card_name, presence: true, length: { minimum: 1 } + # validates :cc_number, presence: true, length: { is: 16 } + # validates :cc_expiration, presence: true + # validates :cvv, presence: true, length: { is: 3 } + # validates :zip_code, presence: true, length: { is: 5 } + # validates :email, presence: true, + # format: { with: VALID_EMAIL }, + # uniqueness: { case_sensitive: false } end diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 33aaeb45cb..75cc3eedd6 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -32,6 +32,24 @@ cc_expiration: "03-02-2019", cvv: "123", zip_code: "98000", + status: :paid + # merchant_id: existing_merchant.id + } + } + }.must_change 'Order.count', 1 + + # Assert + must_respond_with :redirect + must_redirect_to order_path(Order.last.id) + end + + it 'creates a product with valid id' do + existing_merchant = merchants(:one) + perform_login(existing_merchant) + proc { + post orders_path, params: { + order: { + status: :open # merchant_id: existing_merchant.id } } From 98b47ac14a4d404ba4f3478e80f11d2ff6ff3641 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 24 Apr 2018 10:11:47 -0700 Subject: [PATCH 113/252] fixed session display --- app/assets/javascripts/application.js | 1 - app/controllers/application_controller.rb | 9 ++++--- app/controllers/orderproducts_controller.rb | 7 ++---- app/models/orderproduct.rb | 4 --- app/views/layouts/application.html.erb | 6 ++--- app/views/products/show.html.erb | 28 ++++++++++----------- 6 files changed, 25 insertions(+), 30 deletions(-) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index f04673be81..bbeccf9c77 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -14,7 +14,6 @@ // //= require rails-ujs //= require foundation -//= require turbolinks //= require_tree . $(function(){ $(document).foundation(); }); diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index f4041d3ca2..4217ebfc22 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -7,11 +7,14 @@ def render_404 end private + def find_user @user = Merchant.find_by(id: session[:merchant_id]) end - def current_user - @current_user ||= Merchant.find(session[:merchant_id]) if session[:merchant_id] - end + # def current_user + # @current_user ||= Merchant.find(session[:merchant_id]) if session[:merchant_id] + # end + + end diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 905219b427..cd327b07ac 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -1,7 +1,7 @@ class OrderproductsController < ApplicationController before_action :find_orderproduct, only: [:edit, :update, :destroy] before_action :find_user - + def index @orderproducts = Orderproduct.all end @@ -10,16 +10,13 @@ def show end def new - @orderproduct = Orderproduct.new(orderproduct_params) - @product = Product.find_by(id: params[:product_id]) + @orderproduct = Orderproduct.new end def create - @product = Product.find_by(id: params[:product_id]) @orderproduct = OrderProduct.new(orderproduct_params) @orderproduct.product_id = @product.id - #@orderproduct.order_id = @order.id if @orderproduct.save status = :success flash[:result_text] = "#{@orderproduct.quantity} #{@orderproduct.product.name} have been added to your order!" diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index 06b5805354..8474302c22 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -2,9 +2,5 @@ class Orderproduct < ApplicationRecord belongs_to :order belongs_to :product - - validates :quantity ,presence: true - - end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index a00a7664aa..185b83a481 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -57,8 +57,8 @@ - <% if @merchant %> - <%= link_to "Logged in as #{@merchant.username}", merchant_path(@merchant), class: "button" %> + <% if @user %> + <%= link_to "Logged in as #{@user.username}", merchant_path(@user), class: "button" %> <%= link_to "Log Out", logout_path, method: :delete, class: "button" %> <% else %> <%= link_to "Log In", github_login_path, class: "button" %> @@ -83,7 +83,7 @@ <% end %> <% end %> - + <%= yield %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 591b25c8f2..d92e2c73ea 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,4 +1,3 @@ - <%= render partial: "review_form" %>

    Product Details

    @@ -11,7 +10,6 @@

    <%= "Product : #{@product.name}" %>

    <%= "Stock: #{@product.quantity}" %> -

    <%= "Price:#{ @product.price}" %>

    @@ -25,14 +23,13 @@ Description: <%=@product.description %>

    -
    -

    Ratings Summary

    <%="Average rating: #{@product.average_rating}" %>

    +

    Rating

    <% if @product.reviews.empty? %> @@ -47,14 +44,17 @@ <%review.rating.times do %> <%= "🍦" %> <% end %> - -

    - <%= review.comment %> -

    - <%end %> - - <% end %> - -

    <%=link_to "review now!", new_product_review_path(@product.id), class: 'button' %>

    - + + <%= review.comment %> +
    + <%end %> + + <% end %> + +

    + <%=link_to "review now!", new_product_review_path(@product.id), class: 'button' %> +

    + +
    + From 6d78e22d04e7980b30afaf5c0d34de083dddccfb Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 24 Apr 2018 10:21:35 -0700 Subject: [PATCH 114/252] order has merchant_id --- .../20180424171919_add_merchant_id_to_order.rb | 5 +++++ db/schema.rb | 14 ++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 db/migrate/20180424171919_add_merchant_id_to_order.rb diff --git a/db/migrate/20180424171919_add_merchant_id_to_order.rb b/db/migrate/20180424171919_add_merchant_id_to_order.rb new file mode 100644 index 0000000000..2bbd073cb6 --- /dev/null +++ b/db/migrate/20180424171919_add_merchant_id_to_order.rb @@ -0,0 +1,5 @@ +class AddMerchantIdToOrder < ActiveRecord::Migration[5.1] + def change + add_reference :orders, :merchant, foreign_key: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 86eac11b19..96b5069f0c 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: 20180423172432) do +ActiveRecord::Schema.define(version: 20180424171919) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -44,8 +44,6 @@ 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_orderproducts_on_order_id" t.index ["product_id"], name: "index_orderproducts_on_product_id" end @@ -61,6 +59,8 @@ t.string "zip_code" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.bigint "merchant_id" + t.index ["merchant_id"], name: "index_orders_on_merchant_id" end create_table "products", force: :cascade do |t| @@ -70,8 +70,12 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "description" + t.bigint "order_id" t.bigint "merchant_id" + t.bigint "orderproduct_id" t.index ["merchant_id"], name: "index_products_on_merchant_id" + t.index ["order_id"], name: "index_products_on_order_id" + t.index ["orderproduct_id"], name: "index_products_on_orderproduct_id" end create_table "reviews", force: :cascade do |t| @@ -84,8 +88,10 @@ end add_foreign_key "categories", "products" - add_foreign_key "orderproducts", "orders" add_foreign_key "orderproducts", "products" + add_foreign_key "orders", "merchants" add_foreign_key "products", "merchants" + add_foreign_key "products", "orderproducts" + add_foreign_key "products", "orders" add_foreign_key "reviews", "products" end From 50595811b496ddee1a7d320ef8bc544133841296 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Tue, 24 Apr 2018 10:21:45 -0700 Subject: [PATCH 115/252] Working on Order --- app/views/orders/index.html.erb | 7 +++++-- app/views/orders/show.html.erb | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb index d63a69fb54..7c0a80c6f8 100644 --- a/app/views/orders/index.html.erb +++ b/app/views/orders/index.html.erb @@ -1,2 +1,5 @@ -

    Orders#index

    -

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

    +

    Your orders

    + +<% @orders.each do |order| %> +<%= order %> +<% end %> diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb index 22eb495f6f..e9289ebdc4 100644 --- a/app/views/orders/show.html.erb +++ b/app/views/orders/show.html.erb @@ -1,2 +1,3 @@ -

    Orders#show

    -

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

    + From 204aa51d9d86d6086a7744831bae2f030c474fc8 Mon Sep 17 00:00:00 2001 From: Aruna Date: Tue, 24 Apr 2018 11:06:21 -0700 Subject: [PATCH 116/252] changes --- app/assets/javascripts/application.js | 2 +- app/controllers/application_controller.rb | 5 +++-- app/controllers/orderproducts_controller.rb | 5 +---- app/controllers/products_controller.rb | 4 +++- app/models/product.rb | 4 ++-- app/views/layouts/application.html.erb | 4 ++-- app/views/orderproducts/edit.html.erb | 13 ------------- app/views/orderproducts/index.html.erb | 1 - config/routes.rb | 4 ++-- 9 files changed, 14 insertions(+), 28 deletions(-) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index f04673be81..cf4bdced41 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -14,7 +14,7 @@ // //= require rails-ujs //= require foundation -//= require turbolinks + //= require_tree . $(function(){ $(document).foundation(); }); diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 06bcd63b34..2e2a7a477b 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -17,9 +17,10 @@ def current_user def current_order if !session[:order_id].nil? - Order.find(session[:order_id]) + @order = Order.find(session[:order_id]) else - Order.new + @order = Order.new + @order.save end end end diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 770bd9d1b9..51e3482785 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -17,10 +17,7 @@ def new def create @order = current_order - @orderproduct = @order.orderproducts.new(orderproduct_params) - @order.save - session[:order_id] = @order.id - + @orderproduct = Orderproduct.new(orderproduct_params) if @orderproduct.save status = :success diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 9e842cfa0a..937f81b5dd 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,6 +1,6 @@ class ProductsController < ApplicationController before_action :find_product, only: [:show, :edit, :update, :destroy] - before_action :find_user + before_action :find_user,:current_order def root @products = Product.all @@ -8,6 +8,8 @@ def root def index @products = Product.all + @orderproduct = current_order.orderproduct.new + end def show diff --git a/app/models/product.rb b/app/models/product.rb index 0c7cffa16b..f153aa4637 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -9,10 +9,10 @@ class Product < ApplicationRecord validates_numericality_of :quantity, presence: true, greater_than_or_equal_to: 0 validates_numericality_of :price, presence: true, greater_than_or_equal_to: 0 def average_rating - + return "No reviews yet" if reviews.count == 0 sum = 0.0 - products.reviews.each do |review| + self.reviews.each do |review| sum += review.rating end return (sum/reviews.count) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index a00a7664aa..8576757540 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -63,7 +63,7 @@ <% else %> <%= link_to "Log In", github_login_path, class: "button" %> <% end %> - <%= link_to "Cart", cart_path, class: "button" %> + <%= link_to "Cart", order_path(@order.id), class: "button" %> @@ -83,7 +83,7 @@ <% end %> <% end %> - + <%= yield %> diff --git a/app/views/orderproducts/edit.html.erb b/app/views/orderproducts/edit.html.erb index 2485ab7b7f..8b13789179 100644 --- a/app/views/orderproducts/edit.html.erb +++ b/app/views/orderproducts/edit.html.erb @@ -1,14 +1 @@ - -

    Edit Order Item Quantity

    - -
    - <%= form_for @orderproduct do |f| %> - <%= f.hidden_field :product_id, value: @product.id %> - - <%= f.label :quantity %> - <%= f.number_field :quantity, min: 1, max: @product.quantity %> - - <%= f.submit class: "button" %> - <% end %> -
    diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index 1e528bd476..e69de29bb2 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -1 +0,0 @@ -

    <%= @user.username %> Cart

    diff --git a/config/routes.rb b/config/routes.rb index 03bf13a298..575f73a9e6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -12,8 +12,8 @@ delete '/login', to: 'sessions#destroy', as: 'logout' - get '/cart', to:'orderproducts#index', as: 'cart' - + #x get '/cart', to:'orderproducts#index', as: 'cart' + resources :orderproducts, only: [:show] # Reviews: From 5ba12190065161d09faa953dfdd1565a1c9ed41d Mon Sep 17 00:00:00 2001 From: LetiTran Date: Tue, 24 Apr 2018 11:26:45 -0700 Subject: [PATCH 117/252] Working on Order and new migration to add order_id to orderproducts --- app/controllers/orders_controller.rb | 3 ++- app/models/order.rb | 1 + app/views/merchants/show.html.erb | 8 ++++++++ app/views/orders/index.html.erb | 2 +- app/views/orders/show.html.erb | 10 +++++++--- config/routes.rb | 1 + ...180424182249_add_order_id_to_orderproducts_again.rb | 6 ++++++ db/schema.rb | 8 ++++---- test/controllers/orders_controller_test.rb | 2 +- 9 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 db/migrate/20180424182249_add_order_id_to_orderproducts_again.rb diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index b56315e8d1..d7624b6bab 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -3,7 +3,8 @@ class OrdersController < ApplicationController before_action :find_user def index - @orders = Order.all + # @orders = Order.all + @orders = Order.where(merchant_id: @user.id) end def show diff --git a/app/models/order.rb b/app/models/order.rb index 1c09680e20..9cade0df32 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -4,6 +4,7 @@ class Order < ApplicationRecord has_many :orderproducts has_many :products, through: :orderproducts + # validates :address, presence: true, length: { in: 1..35 } # validates :card_name, presence: true, length: { minimum: 1 } # validates :cc_number, presence: true, length: { is: 16 } diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index 76453449ad..695e4ddae2 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -1,3 +1,11 @@ +<% if @user %> +

    <%= link_to "See Your Orders" , orders_path %>

    +<% end %> + + + + +

    Products by <%= @merchant.username %>

    diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb index 7c0a80c6f8..a42077ce73 100644 --- a/app/views/orders/index.html.erb +++ b/app/views/orders/index.html.erb @@ -1,5 +1,5 @@

    Your orders

    <% @orders.each do |order| %> -<%= order %> +<%= link_to "Order ##{order.id}", order_path(order.id) %> <% end %> diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb index e9289ebdc4..947dcab11e 100644 --- a/app/views/orders/show.html.erb +++ b/app/views/orders/show.html.erb @@ -1,3 +1,7 @@ - +

    <%= "Order # #{@order.id}" %>

    +

    <%= "User #{@order.merchant_id}" %>

    + +

    Items:

    +<% @order.products do |p| %> +<%= p.id %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index 03bf13a298..ca40922ef4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -48,6 +48,7 @@ # Merchants: resources :merchants do resources :products, only: [:index] + resources :orders, only: [:index] end # Categories: diff --git a/db/migrate/20180424182249_add_order_id_to_orderproducts_again.rb b/db/migrate/20180424182249_add_order_id_to_orderproducts_again.rb new file mode 100644 index 0000000000..f520c8be3a --- /dev/null +++ b/db/migrate/20180424182249_add_order_id_to_orderproducts_again.rb @@ -0,0 +1,6 @@ +class AddOrderIdToOrderproductsAgain < ActiveRecord::Migration[5.1] + def change + add_reference :orderproducts, :order, foreign_key: true + + end +end diff --git a/db/schema.rb b/db/schema.rb index 96b5069f0c..c75fd88074 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: 20180424171919) do +ActiveRecord::Schema.define(version: 20180424182249) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -44,6 +44,8 @@ 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_orderproducts_on_order_id" t.index ["product_id"], name: "index_orderproducts_on_product_id" end @@ -70,11 +72,9 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "description" - t.bigint "order_id" t.bigint "merchant_id" t.bigint "orderproduct_id" t.index ["merchant_id"], name: "index_products_on_merchant_id" - t.index ["order_id"], name: "index_products_on_order_id" t.index ["orderproduct_id"], name: "index_products_on_orderproduct_id" end @@ -88,10 +88,10 @@ end add_foreign_key "categories", "products" + add_foreign_key "orderproducts", "orders" add_foreign_key "orderproducts", "products" add_foreign_key "orders", "merchants" add_foreign_key "products", "merchants" add_foreign_key "products", "orderproducts" - add_foreign_key "products", "orders" add_foreign_key "reviews", "products" end diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 75cc3eedd6..01d3de6416 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -4,7 +4,7 @@ describe OrdersController do describe 'index' do describe 'index' do - it 'should get all products' do + it 'should get all orders' do get orders_path must_respond_with :success end From 9bf613f190818eb20c89a66676d98b1626c1800b Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 24 Apr 2018 11:28:50 -0700 Subject: [PATCH 118/252] orderprouct stuff --- app/controllers/application_controller.rb | 7 +++---- app/controllers/orderproducts_controller.rb | 9 +++++++-- app/models/order.rb | 18 +++++++++--------- app/views/orderproducts/edit.html.erb | 2 -- app/views/products/show.html.erb | 6 +++--- config/routes.rb | 19 +++++-------------- 6 files changed, 27 insertions(+), 34 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4217ebfc22..25d17c6a39 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -12,9 +12,8 @@ def find_user @user = Merchant.find_by(id: session[:merchant_id]) end - # def current_user - # @current_user ||= Merchant.find(session[:merchant_id]) if session[:merchant_id] - # end - + def find_order + @order = Order.find_by(merchant_id: session[:merchant_id]) + end end diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index cd327b07ac..5d4eb207f7 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -14,8 +14,13 @@ def new end def create - @product = Product.find_by(id: params[:product_id]) - @orderproduct = OrderProduct.new(orderproduct_params) + orderproduct = Orderproduct.new + orderproduct.quantity = params['orderproduct']['quantity'] + orderproduct.product_id = params['orderproduct']['product_id'] + + + raise + @orderproduct.product_id = @product.id if @orderproduct.save status = :success diff --git a/app/models/order.rb b/app/models/order.rb index 06d4908ce4..1c09680e20 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -4,13 +4,13 @@ class Order < ApplicationRecord has_many :orderproducts has_many :products, through: :orderproducts - validates :address, presence: true, length: { in: 1..35 } - validates :card_name, presence: true, length: { minimum: 1 } - validates :cc_number, presence: true, length: { is: 16 } - validates :cc_expiration, presence: true - validates :cvv, presence: true, length: { is: 3 } - validates :zip_code, presence: true, length: { is: 5 } - validates :email, presence: true, - format: { with: VALID_EMAIL }, - uniqueness: { case_sensitive: false } + # validates :address, presence: true, length: { in: 1..35 } + # validates :card_name, presence: true, length: { minimum: 1 } + # validates :cc_number, presence: true, length: { is: 16 } + # validates :cc_expiration, presence: true + # validates :cvv, presence: true, length: { is: 3 } + # validates :zip_code, presence: true, length: { is: 5 } + # validates :email, presence: true, + # format: { with: VALID_EMAIL }, + # uniqueness: { case_sensitive: false } end diff --git a/app/views/orderproducts/edit.html.erb b/app/views/orderproducts/edit.html.erb index 2485ab7b7f..c46ef29b58 100644 --- a/app/views/orderproducts/edit.html.erb +++ b/app/views/orderproducts/edit.html.erb @@ -1,5 +1,3 @@ - -

    Edit Order Item Quantity

    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index d92e2c73ea..433a6b2593 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -13,10 +13,11 @@

    <%= "Price:#{ @product.price}" %>

    - <%= form_for @product do |f| %> + <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> <%= f.label :quantity %> <%= f.select :quantity, options_for_select(1..10)%> - <%= link_to "Add to Cart",edit_product_orderproduct_path(@product.id) ,class: "button" %> + <%= f.hidden_field :product_id, value: @product.id %> + <%= f.submit %> <% end %>

    @@ -45,7 +46,6 @@ <%= "🍦" %> <% end %> - <%= review.comment %> <%end %> diff --git a/config/routes.rb b/config/routes.rb index 03bf13a298..f242a5db9c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,11 +4,9 @@ get '/auth/:provider/callback', to: 'sessions#create', as: 'auth_callback' get '/auth/github', as: 'github_login' -root 'products#root', as: 'homepage' + root 'products#root', as: 'homepage' #sessions - # get '/login', to: 'sessions#new', as: 'login_form' - # post '/login', to: 'sessions#create' delete '/login', to: 'sessions#destroy', as: 'logout' @@ -18,33 +16,26 @@ # Products: -resources :products + resources :products resources :products do # add orderproducts (cart#index) - # resources :reviews, only: [:new] - # resources :merchants, only: [:index] resources :categories, only: [:index] resources :reviews,only: [:new,:create] - #resources :merchants, only: [:index] - #resources :categories, only: [:index] - resources :reviews, only: [:new] + resources :reviews, only: [:new] # resources :merchants, only: [:index] resources :categories, only: [:index] resources :orderproducts - resources :reviews,only: [:new,:create] - #resources :merchants, only: [:index] - #resources :categories, only: [:index] - + resources :reviews,only: [:new,:create] end -resources :reviews + resources :reviews # Merchants: resources :merchants do resources :products, only: [:index] From 978c380bba489dcb2a71afd5d11dc036b72d1c41 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Tue, 24 Apr 2018 12:04:56 -0700 Subject: [PATCH 119/252] Working on Orders views for merchants, order#index. --- app/views/merchants/show.html.erb | 9 +++++---- app/views/orders/index.html.erb | 6 ++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index 695e4ddae2..dc57788ac0 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -1,8 +1,8 @@ -<% if @user %> -

    <%= link_to "See Your Orders" , orders_path %>

    -<% end %> - +<% if @merchant.id == @user.id %> +

    <%= link_to "See Your Orders" , orders_path %>

    +

    <%= link_to "See Your Products" , merchant_products_path(@merchant.id) %>

    +<% else %> @@ -28,3 +28,4 @@ <% end %>
    +<% end %> diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb index a42077ce73..65540a69cb 100644 --- a/app/views/orders/index.html.erb +++ b/app/views/orders/index.html.erb @@ -1,5 +1,7 @@

    Your orders

    -<% @orders.each do |order| %> -<%= link_to "Order ##{order.id}", order_path(order.id) %> +
      + <% @orders.each do |order| %> +
    • <%= link_to "Order ##{order.id}", order_path(order.id) %>
    • +
    <% end %> From 4c012f2e905077998ae0d3ab54a12b97b30b6889 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 24 Apr 2018 12:06:33 -0700 Subject: [PATCH 120/252] submit button text --- 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 433a6b2593..8da26fb5a1 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -17,7 +17,7 @@ <%= f.label :quantity %> <%= f.select :quantity, options_for_select(1..10)%> <%= f.hidden_field :product_id, value: @product.id %> - <%= f.submit %> + <%= f.submit "Add to cart" %> <% end %>

    From cb9b3278e37b2b9e8d29cb055f9829c170199bd2 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 24 Apr 2018 13:24:04 -0700 Subject: [PATCH 121/252] method in orderproducts to create orderproduct --- app/controllers/orderproducts_controller.rb | 16 +++++----------- app/models/orderproduct.rb | 8 ++++++++ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index bfcab217f8..1057b7193a 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -16,20 +16,14 @@ def new def create if @order - orderproduct = Orderproduct.new - orderproduct.quantity = params['orderproduct']['quantity'] - orderproduct.product_id = params['orderproduct']['product_id'] - orderproduct.order_id = @order.id + # creates orderproduct + orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.id) else @order = Order.create(merchant_id: @user.id) - orderproduct = Orderproduct.new - orderproduct.quantity = params['orderproduct']['quantity'] - orderproduct.product_id = params['orderproduct']['product_id'] - orderproduct.order_id = @order.id - + # creates orderproduct + orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.id) product = Product.find(orderproduct.product_id) - # call method to reduce product stock by quantity amount selected by user - # before adding product + @order.products << product end diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index 8474302c22..334bfa24e9 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -3,4 +3,12 @@ class Orderproduct < ApplicationRecord belongs_to :product validates :quantity ,presence: true + + def self.create_orderproduct(quantity, product_id, order_id) + orderproduct = Orderproduct.new + orderproduct.quantity = quantity + orderproduct.product_id = product_id + orderproduct.order_id = order_id + return orderproduct + end end From ada7db5f7a75c28c2538c952276376e955dd6b64 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 24 Apr 2018 14:05:47 -0700 Subject: [PATCH 122/252] basic table with data --- app/controllers/orderproducts_controller.rb | 3 +- app/views/orderproducts/index.html.erb | 40 +++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 1057b7193a..96aad3eb93 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -23,8 +23,7 @@ def create # creates orderproduct orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.id) product = Product.find(orderproduct.product_id) - - @order.products << product + # @order.products << product end if orderproduct.save diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index 1e528bd476..69ac878ea7 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -1 +1,41 @@

    <%= @user.username %> Cart

    + +
    + + + + + + + + + <% @orderproducts.each do |product| %> + <% product = Product.find(product.product_id) %> + + + + + + + <% end %> +
    + Item + + Quantity + + Price + + Options +
    + <%= product.name %>
    +
    + <%= product.quantity %> + + <%= product.price %> + + Edit + Delete +
    + + +
    From 0684475ac3ff98f55a440f0ab762a9d715e4dda9 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 24 Apr 2018 14:10:12 -0700 Subject: [PATCH 123/252] op index styling --- app/views/orderproducts/index.html.erb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index 69ac878ea7..d756220110 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -1,7 +1,6 @@

    <%= @user.username %> Cart

    -
    - +
    @@ -37,5 +36,9 @@ <% end %>
    +
    + +
    +
    From d93062a8bbc9bc79cccdf94cba23a3e2e5507e57 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Tue, 24 Apr 2018 14:10:48 -0700 Subject: [PATCH 124/252] Added destroy method for canceling a order --- test/controllers/orders_controller_test.rb | 46 ++++++++++++++-------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 01d3de6416..497958f76d 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -2,24 +2,38 @@ require "test_helper" describe OrdersController do - describe 'index' do - describe 'index' do - it 'should get all orders' do - get orders_path - must_respond_with :success - end + describe 'index' do + describe 'index' do + it 'should get all orders from the logged in user' do + # Perform login for a user: + existing_merchant = merchants(:one) + perform_login(existing_merchant) - it 'should work with no products' do - Order.destroy_all - assert Order.all.empty? - get orders_path - must_respond_with :success - end - end - end + # Assign currente logged in user to the firts order in fixture + order1 = orders(:one) + order1.merchant_id = existing_merchant.id + order1.save + + # Assert + get merchant_orders_path(existing_merchant) + # binding.pry + must_respond_with :success + end + + it 'should work when merchant has no orders' do + existing_merchant = merchants(:one) + perform_login(existing_merchant) + + Order.destroy_all + assert Order.all.empty? + get merchant_orders_path(existing_merchant) + must_respond_with :success + end + end + end describe 'create' do - it 'creates a product with valid id' do + it 'creates an order with valid id' do existing_merchant = merchants(:one) perform_login(existing_merchant) proc { @@ -43,7 +57,7 @@ must_redirect_to order_path(Order.last.id) end - it 'creates a product with valid id' do + it 'creates a product with valid id and open status' do existing_merchant = merchants(:one) perform_login(existing_merchant) proc { From 8b9f56545f4720ac7637932dbd2d965b4303aeb4 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Tue, 24 Apr 2018 14:11:52 -0700 Subject: [PATCH 125/252] Added order#show view --- app/views/orders/show.html.erb | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb index 947dcab11e..90c1030a55 100644 --- a/app/views/orders/show.html.erb +++ b/app/views/orders/show.html.erb @@ -1,7 +1,23 @@

    <%= "Order # #{@order.id}" %>

    -

    <%= "User #{@order.merchant_id}" %>

    -

    Items:

    -<% @order.products do |p| %> -<%= p.id %> +

    Status:

    +

    <%= "#{@order.status.capitalize}" %>

    + +

    Shipped to:

    +

    <%= "User #{@order.merchant_id}" %>

    +

    <%= "Address: #{@order.address}" %>

    +

    <%= "Zip: #{@order.zip_code}" %>

    + +

    Charged to:

    +

    <%= "Card ************#{@order.cc_number[13]}#{@order.cc_number[14]}#{@order.cc_number[15]}" %>

    + +

    Order Items:

    +
      + <% @order.products do |product| %> +
    • <%= product.id %>
    • +
    <% end %> + +
    + <%= link_to "Cancel this order", order_path(@order.id), method: :delete, :class => "button"%> +
    From f4ce0293ca21975ae71cc1b29889ee6512ad0849 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Tue, 24 Apr 2018 14:12:10 -0700 Subject: [PATCH 126/252] Added destroy method for canceling a order --- app/controllers/orders_controller.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index d7624b6bab..facce0e08c 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -35,6 +35,15 @@ def edit end def destroy + if @order + @order.destroy + flash[:message] = "Deleted #{@order}" + redirect_to orders_path + else + flash[:failure] = :failure + flash.now[:result_text]= "Error: Order was not created" + redirect_to order_path(@order.id) + end end private From 316a707e885b33992c403e7542f2b39ed8e2c0a3 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Tue, 24 Apr 2018 14:13:07 -0700 Subject: [PATCH 127/252] Working on order views --- app/views/orders/_checkout_form.html.erb | 3 ++- app/views/orders/index.html.erb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/views/orders/_checkout_form.html.erb b/app/views/orders/_checkout_form.html.erb index 05828bedd5..330c4fe90f 100644 --- a/app/views/orders/_checkout_form.html.erb +++ b/app/views/orders/_checkout_form.html.erb @@ -1,3 +1,4 @@ +

    Cart <%= page_title %>

    <%= form_for @order do |f| %> @@ -22,6 +23,6 @@ <%= f.label :email %> <%= f.text_field :email %> -<%= f.submit %> +<%= f.submit "Checkout" %> <% end %> diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb index 65540a69cb..4a83c6e1a0 100644 --- a/app/views/orders/index.html.erb +++ b/app/views/orders/index.html.erb @@ -2,6 +2,6 @@
      <% @orders.each do |order| %> -
    • <%= link_to "Order ##{order.id}", order_path(order.id) %>
    • +

      <%= link_to "Order ##{order.id}", order_path(order.id) %>

    <% end %> From 3702a79f28eb89fc06cbe6f9f594338b8e4b3ee3 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 24 Apr 2018 14:35:19 -0700 Subject: [PATCH 128/252] cart page methods --- app/models/orderproduct.rb | 23 +++++++++++++++++++++++ app/views/orderproducts/index.html.erb | 6 +++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index 334bfa24e9..b17d024e69 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -11,4 +11,27 @@ def self.create_orderproduct(quantity, product_id, order_id) orderproduct.order_id = order_id return orderproduct end + + def orderproducts_quantity + sum = 0 + self.each do | order | + sum += order.quantity + @product.quantity -= order.quantity + end + return sum + end + + def orderproducts_total + sum = 0 + orderproducts.each do | order | + sum += order.total + end + return sum + end + + def self.subtotal(orderproduct) + result = orderproduct.quantity * orderproduct.product.price + return result + end + end diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index d756220110..f8fddfd9d0 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -36,7 +36,11 @@ <% end %> -
    +
    +

    + Subtotal: + +

    From 58c9c0b3ff1ee85785190be162596e6567860e2e Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 24 Apr 2018 15:08:19 -0700 Subject: [PATCH 129/252] edit quantity --- app/controllers/orderproducts_controller.rb | 2 +- app/models/orderproduct.rb | 2 +- app/views/orderproducts/edit.html.erb | 4 ++-- app/views/orderproducts/index.html.erb | 11 +++++------ 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 96aad3eb93..17aeae8c17 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -15,7 +15,7 @@ def new end def create - if @order + if @order # creates orderproduct orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.id) else diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index b17d024e69..1c3e560364 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -28,7 +28,7 @@ def orderproducts_total end return sum end - + def self.subtotal(orderproduct) result = orderproduct.quantity * orderproduct.product.price return result diff --git a/app/views/orderproducts/edit.html.erb b/app/views/orderproducts/edit.html.erb index c46ef29b58..3b1788162d 100644 --- a/app/views/orderproducts/edit.html.erb +++ b/app/views/orderproducts/edit.html.erb @@ -2,10 +2,10 @@
    <%= form_for @orderproduct do |f| %> - <%= f.hidden_field :product_id, value: @product.id %> + <%= f.hidden_field :product_id, value: @orderproduct.product_id %> <%= f.label :quantity %> - <%= f.number_field :quantity, min: 1, max: @product.quantity %> + <%= f.select :quantity, min: 1, max: @orderproduct.quantity %> <%= f.submit class: "button" %> <% end %> diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index f8fddfd9d0..92e94fbb07 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -16,8 +16,8 @@ Options - <% @orderproducts.each do |product| %> - <% product = Product.find(product.product_id) %> + <% @orderproducts.each do |op| %> + <% product = Product.find(op.product_id) %> <%= product.name %>
    @@ -29,9 +29,9 @@ <%= product.price %> - Edit - Delete - + <%= link_to "Edit quantity", edit_orderproduct_path(op.id) %> + <%= link_to "Delete", orderproduct_path(op.id), method: :delete %> + <% end %> @@ -39,7 +39,6 @@

    Subtotal: -

    From 4e3366dc25c431ff8c20ea313630703ab28a92e4 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Tue, 24 Apr 2018 15:23:55 -0700 Subject: [PATCH 130/252] Working on 'paying an order' --- app/controllers/orders_controller.rb | 11 +++++++-- app/models/order.rb | 31 +++++++++++++++++------- app/views/orders/_checkout_form.html.erb | 3 +-- app/views/orders/edit.html.erb | 3 +-- app/views/orders/new.html.erb | 1 - app/views/orders/update.html.erb | 3 +-- 6 files changed, 34 insertions(+), 18 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index facce0e08c..37e1c0b463 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -17,8 +17,7 @@ def new def create @order = Order.new(order_params) - - # binding.pry + @order.update(status: "open") if @order.save redirect_to order_path(@order.id) else @@ -29,6 +28,14 @@ def create end def update + # Checkout form comes here + if @order.update(order_params) + @order.update(status: "paid") + redirect_to orders_path + flash[:message] = "Checkout successful" + else + render :edit + end end def edit diff --git a/app/models/order.rb b/app/models/order.rb index 1c09680e20..1a79280645 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -4,13 +4,26 @@ class Order < ApplicationRecord has_many :orderproducts has_many :products, through: :orderproducts - # validates :address, presence: true, length: { in: 1..35 } - # validates :card_name, presence: true, length: { minimum: 1 } - # validates :cc_number, presence: true, length: { is: 16 } - # validates :cc_expiration, presence: true - # validates :cvv, presence: true, length: { is: 3 } - # validates :zip_code, presence: true, length: { is: 5 } - # validates :email, presence: true, - # format: { with: VALID_EMAIL }, - # uniqueness: { case_sensitive: false } + validates :address, presence: true, length: { in: 1..35 }, if: :checking_out? + validates :card_name, presence: true, length: { minimum: 1 }, if: :checking_out? + validates :cc_number, presence: true, length: { is: 16 }, if: :checking_out? + validates :cc_expiration, presence: true, if: :checking_out? + validates :cvv, presence: true, length: { is: 3 }, if: :checking_out? + validates :zip_code, presence: true, length: { is: 5 }, if: :checking_out? + validates :email, presence: true, + format: { with: VALID_EMAIL }, + uniqueness: { case_sensitive: false }, if: :checking_out? + + def checking_out? + :status == "paid" + end + end + + +# lass User < ApplicationRecord +# with_options if: :is_admin? do |admin| +# admin.validates :password, length: { minimum: 10 } +# admin.validates :email, presence: true +# end +# end diff --git a/app/views/orders/_checkout_form.html.erb b/app/views/orders/_checkout_form.html.erb index 330c4fe90f..b1ad5e785c 100644 --- a/app/views/orders/_checkout_form.html.erb +++ b/app/views/orders/_checkout_form.html.erb @@ -1,5 +1,4 @@

    Cart <%= page_title %>

    - <%= form_for @order do |f| %> <%= f.label :address %> @@ -23,6 +22,6 @@ <%= f.label :email %> <%= f.text_field :email %> -<%= f.submit "Checkout" %> +<%= f.submit "Submit payment" %> <% end %> diff --git a/app/views/orders/edit.html.erb b/app/views/orders/edit.html.erb index 7de9049bee..eb56826fe4 100644 --- a/app/views/orders/edit.html.erb +++ b/app/views/orders/edit.html.erb @@ -1,2 +1 @@ -

    Orders#edit

    -

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

    +<%= render partial: "checkout_form", locals: { page_title: "Checkout" } %> diff --git a/app/views/orders/new.html.erb b/app/views/orders/new.html.erb index eb56826fe4..e69de29bb2 100644 --- a/app/views/orders/new.html.erb +++ b/app/views/orders/new.html.erb @@ -1 +0,0 @@ -<%= render partial: "checkout_form", locals: { page_title: "Checkout" } %> diff --git a/app/views/orders/update.html.erb b/app/views/orders/update.html.erb index 21caac1f70..8b13789179 100644 --- a/app/views/orders/update.html.erb +++ b/app/views/orders/update.html.erb @@ -1,2 +1 @@ -

    Orders#update

    -

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

    + From 7a4ef00496341b06836a89c6509a072a794adc02 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Tue, 24 Apr 2018 15:32:29 -0700 Subject: [PATCH 131/252] Added link in cart to checkout (update the order) --- app/views/orderproducts/index.html.erb | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index 92e94fbb07..128ae8f6da 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -1,5 +1,7 @@

    <%= @user.username %> Cart

    +<% if @orderproducts.first %> +
    @@ -29,9 +31,10 @@ <%= product.price %> + <%= link_to "Edit quantity", edit_orderproduct_path(op.id) %> + <%= link_to "Delete", orderproduct_path(op.id), method: :delete %> + + <% end %>
    - <%= link_to "Edit quantity", edit_orderproduct_path(op.id) %> - <%= link_to "Delete", orderproduct_path(op.id), method: :delete %> -
    @@ -44,4 +47,12 @@
    + <%= link_to "Checkout", edit_order_path(@orderproducts.first.order_id)%> + + <% else %> +

    Empty cart!

    + + <% end %> + +
    From 275a8041cddcc3e97239b986339d4d7c0a209e19 Mon Sep 17 00:00:00 2001 From: Aruna Date: Tue, 24 Apr 2018 15:33:24 -0700 Subject: [PATCH 132/252] orders --- app/controllers/orderproducts_controller.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 87ebaa6499..23ff138970 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -1,11 +1,11 @@ class OrderproductsController < ApplicationController before_action :find_orderproduct, only: [:edit, :update, :destroy] -<<<<<<< HEAD + before_action :find_user,:current_order -======= + before_action :find_user before_action :find_order ->>>>>>> a7b691930388c7c6fd09ebc302f1b20a2f102360 + def index @orderproducts = Orderproduct.all @@ -20,12 +20,12 @@ def new end def create -<<<<<<< HEAD + @order = current_order @orderproduct = Orderproduct.new(orderproduct_params) if @orderproduct.save -======= + if @order # creates orderproduct orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.id) @@ -38,7 +38,7 @@ def create end if orderproduct.save ->>>>>>> a7b691930388c7c6fd09ebc302f1b20a2f102360 + status = :success flash[:result_text] = "#{orderproduct.quantity} #{orderproduct.product.name} have been added to your order!" redirect_to products_path @@ -48,6 +48,7 @@ def create render :new, status: status end end +end def edit end From ca4b8830ef6e1f68821128b7d0c727e3ab768ad7 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 24 Apr 2018 16:24:35 -0700 Subject: [PATCH 133/252] update product.quantity when added to cart --- app/models/orderproduct.rb | 5 +++++ app/views/orderproducts/index.html.erb | 13 +++++-------- app/views/products/show.html.erb | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index 1c3e560364..2e971fd0ff 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -6,6 +6,11 @@ class Orderproduct < ApplicationRecord def self.create_orderproduct(quantity, product_id, order_id) orderproduct = Orderproduct.new + # change quantity to reflect user selection + product = Product.find(product_id) + product.quantity = quantity + product.save + # assign form vars to new orderproduct orderproduct.quantity = quantity orderproduct.product_id = product_id orderproduct.order_id = order_id diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index 128ae8f6da..ff22a8527e 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -31,9 +31,8 @@ <%= product.price %> - <%= link_to "Edit quantity", edit_orderproduct_path(op.id) %> - <%= link_to "Delete", orderproduct_path(op.id), method: :delete %> - + <%= link_to "Edit", edit_orderproduct_path(op.id) %> | + <%= link_to "Remove", orderproduct_path(op.id), method: :delete %> <% end %> @@ -45,14 +44,12 @@

    +
    + <%= link_to "Checkout", edit_order_path(@orderproducts.first.order_id), class: "button" %> +
    - <%= link_to "Checkout", edit_order_path(@orderproducts.first.order_id)%> - <% else %>

    Empty cart!

    - <% end %> - -
    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 8da26fb5a1..15c456cfbd 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -10,12 +10,12 @@

    <%= "Product : #{@product.name}" %>

    <%= "Stock: #{@product.quantity}" %> -

    <%= "Price:#{ @product.price}" %>

    +

    <%= "Price:#{@product.price}" %>

    <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> <%= f.label :quantity %> - <%= f.select :quantity, options_for_select(1..10)%> + <%= f.select :quantity, options_for_select(1..@product.quantity)%> <%= f.hidden_field :product_id, value: @product.id %> <%= f.submit "Add to cart" %> <% end %> From ded5af67661c9f04b11156f1b3355bd2ec95629a Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 24 Apr 2018 22:04:00 -0700 Subject: [PATCH 134/252] orderproducts assigned to correct order --- app/controllers/application_controller.rb | 2 +- app/controllers/orderproducts_controller.rb | 19 ++++++++------- app/controllers/products_controller.rb | 4 ++-- app/views/layouts/application.html.erb | 26 +++++++++++++-------- app/views/orderproducts/index.html.erb | 2 +- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a4ad559b9b..78f3bf07c2 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -13,7 +13,7 @@ def find_user end def find_order - @order = Order.find_by({merchant_id: @user.id, status: "open"}) + @order = Order.where(merchant_id: session[:merchant_id]).where(status: "open") end end diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 17aeae8c17..1fe95accc3 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -5,6 +5,7 @@ class OrderproductsController < ApplicationController def index @orderproducts = Orderproduct.all + raise end def show @@ -15,24 +16,24 @@ def new end def create - if @order + if @order.length > 0 # creates orderproduct - orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.id) + orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.first.id) else - @order = Order.create(merchant_id: @user.id) + @order = Order.create(merchant_id: @user.id, status: "open") # creates orderproduct - orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.id) + orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.first.id) product = Product.find(orderproduct.product_id) # @order.products << product end if orderproduct.save status = :success - flash[:result_text] = "#{orderproduct.quantity} #{orderproduct.product.name} have been added to your order!" - redirect_to products_path + flash[:result_text] = "#{orderproduct.quantity} #{orderproduct.product.name} added to your cart!" + redirect_to orderproducts_path else status = :bad_request - flash[:result_text] = "Error - products not added to your order" + flash[:result_text] = "Error - products not added to your cart" render :new, status: status end end @@ -44,7 +45,7 @@ def update if @orderproduct.update(orderproduct_params) flash[:status] = :success flash[:result_text] = "Cart updated" - redirect_to orders_path + redirect_to orderproducts_path else flash.now[:status] = :failure flash.now[:result_text] = "Cart could not be updated" @@ -61,7 +62,7 @@ def destroy end flash[:status] = :success flash[:result_text] = "Successfully removed from your cart!" - redirect_to orders_path + redirect_to orderproducts_path end private diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 9e842cfa0a..086fdbbd27 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -41,7 +41,7 @@ def update redirect_to product_path(@product.id) else binding.pry - flash[:alert] = "A problem occured:Could not update" + flash[:alert] = "A problem occured : Could not update" render :edit end end @@ -65,6 +65,6 @@ def find_product end def assign_merchant_id - @product.merchant_id = @merchant.id + @product.merchant_id = @user.id end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 185b83a481..b008c49ba0 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -21,7 +21,7 @@
    + <% if flash[:result_text] or flash[:messages] %>
    -

    <%= flash[:status] == :failure ? "A problem occurred: " : "" %><%= flash[:result_text] %>

    +
    <%= flash[:status] == :failure ? "A problem occurred: " : "" %><%= flash[:result_text] %>
    <% if flash[:messages] %>
      <% flash[:messages].each do |name, problems| %> diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index ff22a8527e..1c5b71acfc 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -46,9 +46,9 @@
    <%= link_to "Checkout", edit_order_path(@orderproducts.first.order_id), class: "button" %> + <%= link_to "Clear cart" %>
    - <% else %>

    Empty cart!

    <% end %> From 4157ae90466090366190273ef4a05a81721a8f67 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 24 Apr 2018 23:09:18 -0700 Subject: [PATCH 135/252] nav styling, cart error chasing --- app/assets/stylesheets/application.css | 21 ++++++++++- app/controllers/orderproducts_controller.rb | 6 ++- app/models/orderproduct.rb | 42 ++++++++++----------- app/views/layouts/application.html.erb | 34 +++++++++++------ app/views/orderproducts/index.html.erb | 4 +- config/routes.rb | 26 ++++--------- 6 files changed, 79 insertions(+), 54 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 4da94c0f56..371572eea1 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -22,11 +22,30 @@ font-family: 'Pontano Sans', sans-serif; } +.nav-drop p a { + display: flex; + align-items: center; + margin: 0; + border: 0; +} + +.nav-drop p { + margin: 0; + padding-left: .25em; +} + +#login { + padding:.25em .25em; +} + +#login a { + margin: 0; +} .top-bar { background-color: #009999; border-bottom: dotted; border-bottom-color: skyblue; - padding: 0; + padding: .25em; margin: 0; } diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 1fe95accc3..38e3063bc4 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -5,7 +5,6 @@ class OrderproductsController < ApplicationController def index @orderproducts = Orderproduct.all - raise end def show @@ -65,6 +64,11 @@ def destroy redirect_to orderproducts_path end + def clear_cart + Orderproduct.where(order_id: @order.first.id).delete_all + redirect_to orderproducts_path + end + private def orderproduct_params diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index 2e971fd0ff..5e23d9b2e1 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -17,26 +17,26 @@ def self.create_orderproduct(quantity, product_id, order_id) return orderproduct end - def orderproducts_quantity - sum = 0 - self.each do | order | - sum += order.quantity - @product.quantity -= order.quantity - end - return sum - end - - def orderproducts_total - sum = 0 - orderproducts.each do | order | - sum += order.total - end - return sum - end - - def self.subtotal(orderproduct) - result = orderproduct.quantity * orderproduct.product.price - return result - end + # def orderproducts_quantity + # sum = 0 + # self.each do | order | + # sum += order.quantity + # @product.quantity -= order.quantity + # end + # return sum + # end + # + # def orderproducts_total + # sum = 0 + # orderproducts.each do | order | + # sum += order.total + # end + # return sum + # end + # + # def self.subtotal(orderproduct) + # result = orderproduct.quantity * orderproduct.product.price + # return result + # end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index b008c49ba0..d17126ec41 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -14,8 +14,10 @@ diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb index 279b066f30..fed4ff37bf 100644 --- a/app/views/products/edit.html.erb +++ b/app/views/products/edit.html.erb @@ -1,2 +1,26 @@ -

    Products#edit

    -

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

    +

    Edit

    +<%= form_for @product do |f| %> +<%= f.hidden_field :product_id, value: @product.id %> + <%= f.label :name %> + <%= f.text_field :name %> + + <%= f.label "price (cents)" %> + <%= f.text_field :price, placeholder: "in cents" %> + + <%= f.label :quantity %> + <%= f.text_field :quantity %> + + <%= f.label :description %> + <%= f.text_area :description %> + + <%= f.collection_check_boxes :category_ids, Category.all, :id, :name do |b| %> + <%= b.check_box %> + <%= b.label %> + <% end %> + + <%= f.submit %> + + + + <% end %> + From 96febdc5fc1d91c0512b722e242c3825382775f7 Mon Sep 17 00:00:00 2001 From: Aruna Date: Wed, 25 Apr 2018 06:02:53 -0700 Subject: [PATCH 143/252] added add inventory --- app/controllers/orders_controller.rb | 6 +++--- app/models/orderproduct.rb | 4 +--- db/migrate/20180425124546_add_status_product.rb | 5 +++++ db/schema.rb | 3 ++- 4 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 db/migrate/20180425124546_add_status_product.rb diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index c8e52e9c7f..00ed372e8a 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -31,7 +31,7 @@ def update # Checkout form comes here if @order.update(order_params) @order.update(status: "paid") - reduce_inventory(order) + #reduce_inventory(order) redirect_to orders_path flash[:message] = "Checkout successful" else @@ -45,8 +45,8 @@ def edit def destroy if @order @order.destroy - @order.update(status: "cancelled") - add_inventory(order) + #@order.update(status: "cancelled") + #add_inventory(order) flash[:message] = "Deleted #{@order}" redirect_to orders_path else diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index 6770476118..b173f11ebd 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -11,12 +11,10 @@ def self.create_orderproduct(quantity, product_id, order_id) orderproduct.order_id = order_id return orderproduct end - + def total_price self.quantity * self.product.price end - - end diff --git a/db/migrate/20180425124546_add_status_product.rb b/db/migrate/20180425124546_add_status_product.rb new file mode 100644 index 0000000000..5780c05735 --- /dev/null +++ b/db/migrate/20180425124546_add_status_product.rb @@ -0,0 +1,5 @@ +class AddStatusProduct < ActiveRecord::Migration[5.1] + def change + add_column :products, :status, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index c75fd88074..223058100b 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: 20180424182249) do +ActiveRecord::Schema.define(version: 20180425124546) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -74,6 +74,7 @@ t.string "description" t.bigint "merchant_id" t.bigint "orderproduct_id" + t.string "status" t.index ["merchant_id"], name: "index_products_on_merchant_id" t.index ["orderproduct_id"], name: "index_products_on_orderproduct_id" end From a5d7be76493f56c43a5f3300f5f80517ca1535d6 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 25 Apr 2018 11:02:43 -0700 Subject: [PATCH 144/252] colspan --- app/controllers/orderproducts_controller.rb | 2 +- app/views/orderproducts/index.html.erb | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 38e3063bc4..754979568b 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -21,7 +21,7 @@ def create else @order = Order.create(merchant_id: @user.id, status: "open") # creates orderproduct - orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.first.id) + orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.id) product = Product.find(orderproduct.product_id) # @order.products << product end diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index 371de042ab..fffcb0f726 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -14,7 +14,7 @@ Price - + Options @@ -31,7 +31,9 @@ <%= product.price %> - <%= link_to "Edit", edit_orderproduct_path(op.id) %> | + <%= link_to "Edit", edit_orderproduct_path(op.id) %> + + <%= link_to "Remove", orderproduct_path(op.id), method: :delete %> From cc44bd44b5084722e08dfb67189bbac8ef31400d Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 25 Apr 2018 11:13:08 -0700 Subject: [PATCH 145/252] subtotal and total columns for cart --- app/views/orderproducts/index.html.erb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index fffcb0f726..61696456ee 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -14,6 +14,9 @@ Price + + Subtotal + Options @@ -30,6 +33,9 @@ <%= product.price %> + + product.subtotal + <%= link_to "Edit", edit_orderproduct_path(op.id) %> @@ -41,7 +47,7 @@

    - Subtotal: + Total:

    <%= link_to "Checkout", edit_order_path(@orderproducts.first.order_id), class: "button" %> From faa529b0ebdd73f8dcbbc5a944067d5237a51d22 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 25 Apr 2018 12:23:25 -0700 Subject: [PATCH 146/252] can add product from prodocut#index --- app/controllers/orderproducts_controller.rb | 25 ++++++++++++--------- app/views/products/index.html.erb | 2 +- app/views/products/show.html.erb | 4 ++-- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 754979568b..d0b15ce4a2 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -17,13 +17,19 @@ def new def create if @order.length > 0 # creates orderproduct - orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.first.id) + if params['orderproduct'] + orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.first.id) + else + orderproduct = Orderproduct.create_orderproduct(params['quantity'], params['product_id'], @order.first.id) + end else @order = Order.create(merchant_id: @user.id, status: "open") # creates orderproduct - orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.id) - product = Product.find(orderproduct.product_id) - # @order.products << product + if params['orderproduct'] + orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.first.id) + else + orderproduct = Orderproduct.create_orderproduct(params['quantity'], params['product_id'], @order.first.id) + end end if orderproduct.save @@ -54,14 +60,11 @@ def update end def destroy - order = @orderproduct.order - @orderproduct.destroy - if order.orderproducts.empty? - order.destroy + if @orderproduct.destroy + flash[:status] = :success + flash[:result_text] = "Item successfully removed from your cart!" + redirect_to orderproducts_path end - flash[:status] = :success - flash[:result_text] = "Successfully removed from your cart!" - redirect_to orderproducts_path end def clear_cart diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 67e404ee76..02a173a5da 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -48,7 +48,7 @@

    - Add to cart + <%= link_to "Add to cart", url_for(:controller => 'orderproducts', :action => 'create', :product_id => product.id, :quantity => product.quantity), method: :post %>

    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 93eb19ea5d..b0008e9b9d 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,6 +1,6 @@ <%= render partial: "review_form" %> -

    Product Details

    +

    Product Details

    @@ -10,7 +10,7 @@

    <%= "Product : #{@product.name}" %>

    <%= "Stock: #{@product.quantity}" %> -

    <%= "Price:#{@product.price}" %>

    +

    <%= "Price:#{ @product.price}" %>

    <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> From 195cfd97379484b1fc0b41d74e68ab017934eed8 Mon Sep 17 00:00:00 2001 From: Aruna Date: Wed, 25 Apr 2018 12:58:24 -0700 Subject: [PATCH 147/252] added total and sub_total --- app/controllers/orderproducts_controller.rb | 2 ++ app/models/order.rb | 13 ++++++++----- app/models/orderproduct.rb | 6 ++++-- app/views/orderproducts/index.html.erb | 8 +++++--- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 754979568b..188dc44a31 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -4,7 +4,9 @@ class OrderproductsController < ApplicationController before_action :find_order def index + @orderproducts = Orderproduct.all + end def show diff --git a/app/models/order.rb b/app/models/order.rb index e278e2263b..bac12dcf36 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -18,14 +18,17 @@ def checking_out? :status == "paid" end - def sub_total - sum = 0 - self.orderproducts.each do |order| - sum+= orderproduct.total_price + def total + total = 0 + self.orderproducts.each do |op| + total += op.sub_total end - return sum + + return total end + + end diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index 167f2ff05e..97d6d5a877 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -17,9 +17,11 @@ def self.create_orderproduct(quantity, product_id, order_id) return orderproduct end - def total_price - self.quantity * self.product.price + def sub_total + quantity * self.product.price end + + end diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index 61696456ee..fb7454ac7f 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -34,7 +34,7 @@ <%= product.price %> - product.subtotal + <%= product.quantity * product.price %> <%= link_to "Edit", edit_orderproduct_path(op.id) %> @@ -46,8 +46,10 @@ <% end %> -

    - Total: +

    + + <%= "Total: #{@order.first.total}" %> +

    <%= link_to "Checkout", edit_order_path(@orderproducts.first.order_id), class: "button" %> From 7f87246fdd2b9f2d3d8e9dfb2e2bb9a35a3b8843 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Wed, 25 Apr 2018 13:03:58 -0700 Subject: [PATCH 148/252] Working on user welcome/profile --- app/controllers/sessions_controller.rb | 65 ++++++++++++++++---------- app/models/order.rb | 10 +++- app/models/orderproduct.rb | 3 ++ app/views/merchants/show.html.erb | 11 ----- app/views/sessions/index.html.erb | 38 ++++++++++++++- app/views/sessions/show.html.erb | 22 +++++++++ config/routes.rb | 6 ++- 7 files changed, 116 insertions(+), 39 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index ec86d3f375..9dc6306ec4 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,42 +1,51 @@ class SessionsController < ApplicationController + before_action :find_merchant, only: [:show, :index] + before_action :find_user, only: [:show, :index] def index + @total_revenue = 0 + @user.products.orders.each do |order| + @total_revenue =+ order.total + end + end def show + @merchant_orders = @user.products.orders + end def new @merchant = Merchant.new end - + def create auth_hash = request.env['omniauth.auth'] - if auth_hash[:uid] - @merchant = Merchant.find_by(uid: auth_hash[:uid], provider: 'github') - if @merchant.nil? - # it's a new merchant, we need to make a merchant - @merchant = Merchant.build_from_github(auth_hash) - successful_save = @merchant.save - if successful_save - flash[:success] = "Logged in successfully" - session[:merchant_id] = @merchant.id - redirect_to homepage_path - else - flash[:error] = "Some error happened in Merchant creation" - redirect_to homepage_path - end - else - flash[:success] = "Logged in successfully" - session[:merchant_id] = @merchant.id - redirect_to homepage_path - end - - else - flash[:error] = "Logging in via github not successful" - redirect_to homepage_path - end + if auth_hash[:uid] + @merchant = Merchant.find_by(uid: auth_hash[:uid], provider: 'github') + if @merchant.nil? + # it's a new merchant, we need to make a merchant + @merchant = Merchant.build_from_github(auth_hash) + successful_save = @merchant.save + if successful_save + flash[:success] = "Logged in successfully" + session[:merchant_id] = @merchant.id + redirect_to homepage_path + else + flash[:error] = "Some error happened in Merchant creation" + redirect_to homepage_path + end + else + flash[:success] = "Logged in successfully" + session[:merchant_id] = @merchant.id + redirect_to homepage_path + end + + else + flash[:error] = "Logging in via github not successful" + redirect_to homepage_path + end end def destroy @@ -44,4 +53,10 @@ def destroy flash[:success] = "You logged out!" redirect_to homepage_path end + + private + def find_merchant + @merchant = Merchant.find_by(id: params[:id]) + render_404 unless @merchant + end end diff --git a/app/models/order.rb b/app/models/order.rb index 1a79280645..646e30ec3b 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -18,8 +18,16 @@ def checking_out? :status == "paid" end -end + def total + total = 0 + self.orderproducts.each do |op| + total += op.sub_total + end + + return total + end +end # lass User < ApplicationRecord # with_options if: :is_admin? do |admin| diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index 5e23d9b2e1..38d10bfa1a 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -17,6 +17,9 @@ def self.create_orderproduct(quantity, product_id, order_id) return orderproduct end + def sub_total + self.quantity * self.product.price + end # def orderproducts_quantity # sum = 0 # self.each do | order | diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index a296997528..76c4c84c7f 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -25,17 +25,6 @@ <% end%> - - - - - - - - - - - <% else %> diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index 62cbf379e3..0279234019 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -1,2 +1,38 @@

    Sessions#index

    -

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

    + +<% if @merchant.id == @user.id %> +

    Welcome <%= @merchant.username %> !

    + +

    <%= link_to("See Your Purchases Orders", orders_path, :class => "button")%>

    +

    <%= link_to("See Your Products", merchant_products_path(@merchant.id), :class => "button")%>

    +<% end %> + +

    Total revenue: <%= @total_revenue %>

    + + + + + + + + + + + + <% @merchant.products.orders.each do |order| %> + + <% end %> + +
    Total Revenue by Status
    Order StatusOrder QuantityRevenue
    @merchant.products.orders.quantity
    + + + + + + + + + + + + diff --git a/app/views/sessions/show.html.erb b/app/views/sessions/show.html.erb index 1225c86bfd..eab4f8d65b 100644 --- a/app/views/sessions/show.html.erb +++ b/app/views/sessions/show.html.erb @@ -1,2 +1,24 @@

    Sessions#show

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

    + + + +<% if @merchant_orders.first %> + + + + + + + + <% @merchant.products.orders.each do |order| %> + + <% end%> + +
    OrderSatusTotal
    <%= order.id %>
    +

    Total Revenue: <%= %>

    + +<% else %> +

    You have no sales orders yet.

    +<% end%> +<% end%> diff --git a/config/routes.rb b/config/routes.rb index 9c3758c6ea..8a968087f9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,8 +6,12 @@ get '/auth/:provider/callback', to: 'sessions#create', as: 'auth_callback' get '/auth/github', as: 'github_login' - #sessions + # Sessions delete '/login', to: 'sessions#destroy', as: 'logout' + # get '/merchants/:id/products', to: 'sessions#show', as: 'user_products' + # get '/merchants/:id', to: 'sessions#index', as: 'user_profile' + + # Cart get '/cart', to: 'orderproducts#index', as: 'cart' get 'orderproducts/clearcart', to: 'orderproducts#clear_cart', as: 'clearcart' From 30bb9efb324b24cb7dac8ecc0b6418e7402616bf Mon Sep 17 00:00:00 2001 From: Aruna Date: Wed, 25 Apr 2018 14:08:58 -0700 Subject: [PATCH 149/252] added status in products --- db/seeds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/seeds.rb b/db/seeds.rb index ec3684ca4d..d9651f57df 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -35,7 +35,7 @@ # Products puts "\n" 10.times do |t| - product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.order("RANDOM()").first] , quantity: 2, merchant_id: Merchant.order("RANDOM()").first.id ) + product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.order("RANDOM()").first] , quantity: 2, status: "active",merchant_id: Merchant.order("RANDOM()").first.id ) puts "#{product.name} created in the category: #{product.categories.first.name}" end p "**Created #{Product.count} desserts**" From 345f75e87b649727f460d3947787d94cfc981a74 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Wed, 25 Apr 2018 15:16:27 -0700 Subject: [PATCH 150/252] Working on login profile --- app/controllers/orderproducts_controller.rb | 7 +++---- app/controllers/sessions_controller.rb | 11 +++++++++++ app/views/orderproducts/index.html.erb | 2 +- app/views/sessions/index.html.erb | 13 +++++++++---- app/views/sessions/show.html.erb | 4 ++-- config/routes.rb | 4 ++-- 6 files changed, 28 insertions(+), 13 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index c146a0c46b..8b176bd02a 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -4,8 +4,7 @@ class OrderproductsController < ApplicationController before_action :find_order def index - - @orderproducts = Orderproduct.all + @orderproducts = Orderproduct.where(order_id: @order.first.id) if @order.first end @@ -28,9 +27,9 @@ def create @order = Order.create(merchant_id: @user.id, status: "open") # creates orderproduct if params['orderproduct'] - orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.first.id) + orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.id) else - orderproduct = Orderproduct.create_orderproduct(params['quantity'], params['product_id'], @order.first.id) + orderproduct = Orderproduct.create_orderproduct(params['quantity'], params['product_id'], @order.id) end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 9dc6306ec4..d388dff3d7 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -8,6 +8,17 @@ def index @total_revenue =+ order.total end + @sold_products =[] + # @user_orders = Order.where()@user.products.orders + paid_ordes= Order.where(status: "paid") + paid_ordes.each do |po| + po.orderproducts.each do |op| + product = Product.find_by(id: op.product_id) + if product.merchant_id == @user.id + @sold_products << product + end + end + end end def show diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index fb7454ac7f..a0e6af9506 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -1,6 +1,6 @@

    <%= @user.username %> Cart

    -<% if @orderproducts.first %> +<% if @orderproducts && @orderproducts.first %>
    diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index 0279234019..3f09b3fea2 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -7,22 +7,27 @@

    <%= link_to("See Your Products", merchant_products_path(@merchant.id), :class => "button")%>

    <% end %> -

    Total revenue: <%= @total_revenue %>

    +
    - + + <% @sold_products.each do |p| %> - <% @merchant.products.orders.each do |order| %> - + + + <% end %> + + +
    Total Revenue by StatusTotal Revenue by Status
    Order Status Order Quantity Revenue
    @merchant.products.orders.quantity<%= p.name %> <%= p %> <%= p %>

    Total revenue: $<%= @total_revenue %>

    diff --git a/app/views/sessions/show.html.erb b/app/views/sessions/show.html.erb index eab4f8d65b..0a1a2b96d8 100644 --- a/app/views/sessions/show.html.erb +++ b/app/views/sessions/show.html.erb @@ -19,6 +19,6 @@

    Total Revenue: <%= %>

    <% else %> -

    You have no sales orders yet.

    -<% end%> +

    You have not sold any products yet.

    + <% end%> diff --git a/config/routes.rb b/config/routes.rb index 8a968087f9..e5284f6334 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,8 +8,8 @@ # Sessions delete '/login', to: 'sessions#destroy', as: 'logout' - # get '/merchants/:id/products', to: 'sessions#show', as: 'user_products' - # get '/merchants/:id', to: 'sessions#index', as: 'user_profile' + get '/merchants/:id/products', to: 'sessions#show', as: 'user_products' + get '/merchants/:id', to: 'sessions#index', as: 'user_profile' # Cart get '/cart', to: 'orderproducts#index', as: 'cart' From 2467d081ddfe88ecfe3e75f4fb39fe94f3ff8275 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Wed, 25 Apr 2018 15:17:35 -0700 Subject: [PATCH 151/252] Working on login profile --- config/routes.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index e5284f6334..8a968087f9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,8 +8,8 @@ # Sessions delete '/login', to: 'sessions#destroy', as: 'logout' - get '/merchants/:id/products', to: 'sessions#show', as: 'user_products' - get '/merchants/:id', to: 'sessions#index', as: 'user_profile' + # get '/merchants/:id/products', to: 'sessions#show', as: 'user_products' + # get '/merchants/:id', to: 'sessions#index', as: 'user_profile' # Cart get '/cart', to: 'orderproducts#index', as: 'cart' From 64a04d69bb5a904e7b9739b88c2b827161a8a948 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 25 Apr 2018 15:18:46 -0700 Subject: [PATCH 152/252] price view --- app/controllers/orderproducts_controller.rb | 2 -- app/helpers/application_helper.rb | 5 +++ app/views/orderproducts/index.html.erb | 6 ++-- app/views/products/index.html.erb | 2 +- app/views/products/new.html.erb | 6 ++-- app/views/products/show.html.erb | 39 ++++++++++++--------- 6 files changed, 33 insertions(+), 27 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index c146a0c46b..d0b15ce4a2 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -4,9 +4,7 @@ class OrderproductsController < ApplicationController before_action :find_order def index - @orderproducts = Orderproduct.all - end def show diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de6be7945c..4cb004d112 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,2 +1,7 @@ module ApplicationHelper + + def format_price(price) + ("" + number_to_currency(price) + "").html_safe + end + end diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index fb7454ac7f..c390709be1 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -31,10 +31,10 @@ <%= product.quantity %> - <%= product.price %> + <%= format_price(product.price) %> - <%= product.quantity * product.price %> + <%= format_price(product.quantity * product.price) %> <%= link_to "Edit", edit_orderproduct_path(op.id) %> @@ -48,7 +48,7 @@

    - <%= "Total: #{@order.first.total}" %> + <%= "Total: #{format_price(@order.first.total)}" %>

    diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 02a173a5da..67047cde50 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -42,7 +42,7 @@ https://loremflickr.com/350/250/dessert" alt="product pic">

    - Price: <%= product.price %> + Price: <%= format_price(product.price) %>

    Stock: <%= product.quantity %>

    diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index f282700779..a4afe21576 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -3,8 +3,8 @@ <%= f.label :name %> <%= f.text_field :name %> - <%= f.label "price (cents)" %> - <%= f.text_field :price, placeholder: "in cents" %> + <%= f.label "price" %> + <%= f.text_field :price %> <%= f.label :quantity %> <%= f.text_field :quantity %> @@ -19,7 +19,5 @@ <%= f.submit %> - - <% end %>
    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index b0008e9b9d..2ef2c55423 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,6 +1,6 @@ <%= render partial: "review_form" %> -

    Product Details

    +

    Item details

    @@ -8,30 +8,35 @@
    -

    <%= "Product : #{@product.name}" %>

    - <%= "Stock: #{@product.quantity}" %> -

    <%= "Price:#{ @product.price}" %>

    - - - <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> - <%= f.label :quantity %> - <%= f.select :quantity, options_for_select(1..@product.quantity)%> - <%= f.hidden_field :product_id, value: @product.id %> - <%= f.submit "Add to cart" %> - <% end %> - -

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

    Product: <%= @product.name %>

    +

    Stock: <%= @product.quantity %>

    +

    Price: <%= format_price(@product.price) %> +

    + Description: + <% if @product.description %> + <%= @product.description %> + <% else %> + <%= "None" %> + <% end %>

    -
    +
    + <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> + <%= f.label :quantity %> + <%= f.select :quantity, options_for_select(1..@product.quantity)%> + <%= f.hidden_field :product_id, value: @product.id %> + <%= f.submit "Add to cart", class: "button" %> + <% end %> +
    + +

    Ratings Summary

    <%="Average rating: #{@product.average_rating}" %>

    -
    +

    Rating

    <% if @product.reviews.empty? %>

    From 12233a1af0d42aa65c09a229312c4b2bdca7312e Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 25 Apr 2018 15:24:39 -0700 Subject: [PATCH 153/252] total price display fix --- app/views/orderproducts/index.html.erb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/views/orderproducts/index.html.erb b/app/views/orderproducts/index.html.erb index 83d8e0f896..cb4e23a9de 100644 --- a/app/views/orderproducts/index.html.erb +++ b/app/views/orderproducts/index.html.erb @@ -46,10 +46,8 @@ <% end %> -

    - - <%= "Total: #{format_price(@order.first.total)}" %> - +

    + Total: <%=format_price(@order.first.total) %>

    <%= link_to "Checkout", edit_order_path(@orderproducts.first.order_id), class: "button" %> From f3f0229d50dd3d56b69815eb7070ceab7b344f59 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 25 Apr 2018 15:43:24 -0700 Subject: [PATCH 154/252] edit orderproduct quantity --- app/controllers/orderproducts_controller.rb | 4 ++-- app/views/orderproducts/edit.html.erb | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 342eb853e1..6fdcc61764 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -49,7 +49,7 @@ def edit def update if @orderproduct.update(orderproduct_params) flash[:status] = :success - flash[:result_text] = "Cart updated" + flash[:result_text] = "Cart updated!" redirect_to orderproducts_path else flash.now[:status] = :failure @@ -75,7 +75,7 @@ def clear_cart private def orderproduct_params - params.require(:order_product).permit(:quantity,:product_id) + params.require(:orderproduct).permit(:quantity, :product_id) end def find_orderproduct diff --git a/app/views/orderproducts/edit.html.erb b/app/views/orderproducts/edit.html.erb index 3b1788162d..aed8d47873 100644 --- a/app/views/orderproducts/edit.html.erb +++ b/app/views/orderproducts/edit.html.erb @@ -3,10 +3,8 @@

    <%= form_for @orderproduct do |f| %> <%= f.hidden_field :product_id, value: @orderproduct.product_id %> - <%= f.label :quantity %> - <%= f.select :quantity, min: 1, max: @orderproduct.quantity %> - + <%= f.select :quantity, options_for_select(1..@orderproduct.quantity)%> <%= f.submit class: "button" %> <% end %>
    From a187e3bb8c811397858f055ffb7754df8c1116a1 Mon Sep 17 00:00:00 2001 From: Aruna Date: Wed, 25 Apr 2018 16:19:46 -0700 Subject: [PATCH 155/252] added retire status method --- app/models/product.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/models/product.rb b/app/models/product.rb index f153aa4637..bf03ae1cd5 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -8,6 +8,8 @@ class Product < ApplicationRecord validate :has_atleast_one_category validates_numericality_of :quantity, presence: true, greater_than_or_equal_to: 0 validates_numericality_of :price, presence: true, greater_than_or_equal_to: 0 + + def average_rating return "No reviews yet" if reviews.count == 0 @@ -18,6 +20,12 @@ def average_rating return (sum/reviews.count) end + + def change_status + self.status == "active" ? self.status = "retired" : self.status = "active" + self.save + end + private def has_atleast_one_category From 182b9456909703fe7321de69a036f6078b36e01d Mon Sep 17 00:00:00 2001 From: Aruna Date: Wed, 25 Apr 2018 16:20:27 -0700 Subject: [PATCH 156/252] added find active method in product controller --- app/controllers/products_controller.rb | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 5881d2a3ec..a7f30ccc20 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -7,8 +7,8 @@ def root end def index - @products = Product.all + @products = find_active_products # If using this path for displaying the logged in user's products: if @user.id == params[:merchant_id].to_i @user_products = Product.where(merchant_id: @user.id).order(id: :desc) @@ -25,6 +25,7 @@ def new def create @product = Product.new(product_params) assign_merchant_id + if @product.save flash[:status] = :success redirect_to product_path(@product.id) @@ -39,29 +40,29 @@ def edit end def update - @product.merchant_id = @merchant.id + assign_merchant_id + if @product.update(product_params) + + flash[:success] = "#{@product.name} updated" redirect_to product_path(@product.id) else - binding.pry + flash[:alert] = "A problem occured : Could not update" render :edit end end - def destroy - if @product.destroy - flash[:message] = "Deleted #{@product.name}" - redirect_to products_path - end - end - private def product_params - return params.require(:product).permit(:name, :price, :quantity, :description, :category_ids => []) + return params.require(:product).permit(:name, :price, :quantity,:status, :description, :category_ids => []) + end + + def find_active_products + return Product.where(status:"active") end def find_product From 321c9b5a550f50ff9eaaa5fc3a61d596cb339d8b Mon Sep 17 00:00:00 2001 From: Aruna Date: Wed, 25 Apr 2018 16:21:04 -0700 Subject: [PATCH 157/252] retired products are not showing up --- app/views/products/edit.html.erb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb index fed4ff37bf..3a836d364e 100644 --- a/app/views/products/edit.html.erb +++ b/app/views/products/edit.html.erb @@ -13,6 +13,9 @@ <%= f.label :description %> <%= f.text_area :description %> + <%= f.label :status %> + <%= f.select :status, [ ['active'], ['retire']]%> + <%= f.collection_check_boxes :category_ids, Category.all, :id, :name do |b| %> <%= b.check_box %> <%= b.label %> From 077094a25a0ac36aef6295cf03f6906af342200e Mon Sep 17 00:00:00 2001 From: LetiTran Date: Wed, 25 Apr 2018 16:44:42 -0700 Subject: [PATCH 158/252] Created route for user profile and user products, also working on the user revenue by products and etc. --- app/controllers/merchants_controller.rb | 6 +++- app/controllers/products_controller.rb | 8 ++--- app/controllers/sessions_controller.rb | 14 ++++---- app/views/layouts/application.html.erb | 2 +- app/views/merchants/show.html.erb | 32 ----------------- app/views/products/index.html.erb | 35 +------------------ app/views/sessions/index.html.erb | 26 ++++++++------ app/views/sessions/show.html.erb | 46 ++++++++++++++----------- config/routes.rb | 4 +-- 9 files changed, 62 insertions(+), 111 deletions(-) diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 208294932a..9763f09657 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -7,7 +7,11 @@ def index end def show - @merchant_orders = @user.products.orders + # If accesing itself: + + # if @merchant.id == @user.id + # end + end def new diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 5881d2a3ec..6b3a34749e 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -52,10 +52,10 @@ def update end def destroy - if @product.destroy - flash[:message] = "Deleted #{@product.name}" - redirect_to products_path - end + # if @product.destroy + # flash[:message] = "Deleted #{@product.name}" + # redirect_to products_path + # end end private diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index d388dff3d7..3a4fe12b98 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,12 +1,8 @@ class SessionsController < ApplicationController before_action :find_merchant, only: [:show, :index] - before_action :find_user, only: [:show, :index] + before_action :find_user def index - @total_revenue = 0 - @user.products.orders.each do |order| - @total_revenue =+ order.total - end @sold_products =[] # @user_orders = Order.where()@user.products.orders @@ -19,10 +15,16 @@ def index end end end + + @total_revenue = 0 + @sold_products.each do |p| + @total_revenue =+ p.price + end + end def show - @merchant_orders = @user.products.orders + @user_products = @user.products end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 23b2fe9625..6d4b79c0c9 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -73,7 +73,7 @@ <% end %>
    - <% end %> diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 67047cde50..64a389a0d8 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,38 +1,5 @@ -<% unless @user_products.nil? %> - -
    -

    <%= @user.username%> products

    - <% unless @user_products.first.nil? %> - - - - - - - - - <% @user_products.each do |product| %> - - - - - - - - <% end %> -
    ItemQuantityPriceOptions
    <%= product.name %>
    <%= product.quantity %><%= product.price %><%= link_to "Edit Item", edit_product_path(product.id) %><%= link_to "Delete", product_path(product.id), method: :delete %>
    - <% else %> -

    You have no products for sale.

    - <% end %> -

    <%= link_to("Add a Product", new_product_path, :class => "button") %> -

    - - - <% else %> - -
    <% @products.each do |product| %> @@ -54,5 +21,5 @@ <% end %>
    - <% end %> +
    diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index 3f09b3fea2..3f9acb8ff5 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -1,32 +1,36 @@

    Sessions#index

    -<% if @merchant.id == @user.id %> +<% if @merchant.id == @user.id %>

    Welcome <%= @merchant.username %> !

    -

    <%= link_to("See Your Purchases Orders", orders_path, :class => "button")%>

    -

    <%= link_to("See Your Products", merchant_products_path(@merchant.id), :class => "button")%>

    +

    <%= link_to("See Your Purchases Orders", orders_path, :class => "button")%>

    <%= link_to("See Your Products", user_products_path(@user.id), :class => "button")%>

    <% end %> - - + - - - + + + + <% @sold_products.each do |p| %> - - + + <% sum = 0 %> + <% @sold_products.each do |product| %> + <% sum =+ 1 if product.id == p.id %> + + <% end %> + <% end %> - +
    Total Revenue by StatusTotal Revenue by Status
    Order StatusOrder QuantityRevenueProductPriceQuantity SoldProduct Revenue
    <%= p.name %> <%= p %> <%= p %> <%= format_price(p.price) %> <%= sum %><%= format_price(sum * p.price)%>

    Total revenue: $<%= @total_revenue %>

    Total revenue: <%= format_price(@total_revenue) %>

    diff --git a/app/views/sessions/show.html.erb b/app/views/sessions/show.html.erb index 0a1a2b96d8..df2e1b3613 100644 --- a/app/views/sessions/show.html.erb +++ b/app/views/sessions/show.html.erb @@ -2,23 +2,29 @@

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

    - -<% if @merchant_orders.first %> - - - - - - - - <% @merchant.products.orders.each do |order| %> - - <% end%> - -
    OrderSatusTotal
    <%= order.id %>
    -

    Total Revenue: <%= %>

    - -<% else %> -

    You have not sold any products yet.

    - -<% end%> +
    +

    <%= @user.username%> products

    + <% unless @user_products.first.nil? %> + + + + + + + + + <% @user_products.each do |product| %> + + + + + + + + <% end %> +
    ItemQuantityPriceOptions
    <%= product.name %>
    <%= product.quantity %><%= product.price %><%= link_to "Edit Item", edit_product_path(product.id) %><%= link_to "Delete", product_path(product.id), method: :delete %>
    + <% else %> +

    You have no products for sale.

    + <% end %> +

    <%= link_to("Add a Product", new_product_path, :class => "button") %> +

    diff --git a/config/routes.rb b/config/routes.rb index 8a968087f9..0fceb36b7b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,8 +8,8 @@ # Sessions delete '/login', to: 'sessions#destroy', as: 'logout' - # get '/merchants/:id/products', to: 'sessions#show', as: 'user_products' - # get '/merchants/:id', to: 'sessions#index', as: 'user_profile' + get '/user/:id/products', to: 'sessions#show', as: 'user_products' + get '/user/:id', to: 'sessions#index', as: 'user_profile' # Cart get '/cart', to: 'orderproducts#index', as: 'cart' From 58c0f0117ed2176462cdb6ea2b426a69d84fd6a9 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 25 Apr 2018 16:46:51 -0700 Subject: [PATCH 159/252] dropdown --- app/assets/stylesheets/application.css | 2 ++ app/views/layouts/application.html.erb | 34 ++++++++++++++++++++------ app/views/products/edit.html.erb | 4 --- app/views/products/index.html.erb | 6 ++--- app/views/products/new.html.erb | 2 -- 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index d2e134f33c..352b0f242c 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -36,6 +36,8 @@ #login { padding:.25em .25em; + display: flex; + flex-direction: row; } #login a { diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 23b2fe9625..9f2ae39f04 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -72,15 +72,35 @@ -
    @@ -101,7 +121,7 @@
    <% end %> - <%= yield %> + diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb index fed4ff37bf..3aa4f083e2 100644 --- a/app/views/products/edit.html.erb +++ b/app/views/products/edit.html.erb @@ -17,10 +17,6 @@ <%= b.check_box %> <%= b.label %> <% end %> - <%= f.submit %> - - - <% end %>
    diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 67047cde50..265f5ee73f 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,11 +1,9 @@ - - <% unless @user_products.nil? %>

    <%= @user.username%> products

    <% unless @user_products.first.nil? %> - + @@ -56,3 +54,5 @@ <% end %> + + diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index a4afe21576..c8e49e1d30 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -16,8 +16,6 @@ <%= b.check_box %> <%= b.label %> <% end %> - <%= f.submit %> - <% end %> From 1e9d66986617919408f645bcd0bb75a7ebeff171 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 25 Apr 2018 17:13:16 -0700 Subject: [PATCH 160/252] merge fix --- app/assets/stylesheets/application.css | 1 + app/views/layouts/application.html.erb | 9 ++------- app/views/products/index.html.erb | 1 - 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 352b0f242c..52b1f0f17d 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -72,6 +72,7 @@ justify-content: space-around; align-content: center; } + .merch-container { display: grid; grid-template: diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 910ac45b4a..e249362e77 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -72,11 +72,10 @@ - + From 38207b0952f089b93e2f0d0954a6b83e36f664f0 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 25 Apr 2018 21:48:14 -0700 Subject: [PATCH 165/252] pricing view --- app/views/merchants/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index 43801df3e5..d268d61220 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -8,7 +8,7 @@ https://loremflickr.com/350/250/dessert" alt="product pic">

    - Price: <%= product.price %> + Price: <%= format_price(product.price) %>

    Stock: <%= product.quantity %>

    From 9fbbd294078e3b3f4cbb8c0db457b46420981087 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 25 Apr 2018 22:40:19 -0700 Subject: [PATCH 166/252] product page, reviews need more work --- app/assets/stylesheets/application.css | 11 +++ app/views/products/show.html.erb | 106 ++++++++++++------------- 2 files changed, 62 insertions(+), 55 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 447eda3eb7..1a9be3ab1b 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -103,6 +103,17 @@ margin: 0; } + .rating-container p { + display: flex; + justify-content: center; + } + + .rating-container ul { + display: flex; + justify-content: center; + list-style: none; + } + strong { margin-right: .3em; } diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 2ef2c55423..e022a6dc57 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,65 +1,61 @@ <%= render partial: "review_form" %> -

    Item details

    +

    <%= @product.name %> details

    -
    -
    - <%= image_tag ('https://placeimg.com/350/200/nature') %> -
    - -
    -

    Product: <%= @product.name %>

    -

    Stock: <%= @product.quantity %>

    -

    Price: <%= format_price(@product.price) %> -

    - Description: - <% if @product.description %> - <%= @product.description %> - <% else %> - <%= "None" %> - <% end %> -

    +
    +
    + product pic +
    -
    - <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> - <%= f.label :quantity %> - <%= f.select :quantity, options_for_select(1..@product.quantity)%> - <%= f.hidden_field :product_id, value: @product.id %> - <%= f.submit "Add to cart", class: "button" %> - <% end %> -
    +
    +

    Stock: <%= @product.quantity %>

    +

    Price: <%= format_price(@product.price) %> +

    + Description: + <% if @product.description %> + <%= @product.description %> + <% else %> + <%= "None" %> + <% end %> +

    -
    -

    Ratings Summary

    -

    - <%="Average rating: #{@product.average_rating}" %> -

    -
    +
    + <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> + <%= f.label :quantity %> + <%= f.select :quantity, options_for_select(1..@product.quantity)%> + <%= f.hidden_field :product_id, value: @product.id %> + <%= f.submit "Add to cart", class: "button" %> + <% end %> +
    -
    -

    Rating

    - <% if @product.reviews.empty? %> -

    - Be the first to review! -

    - <%else %> -
      - <% @product.reviews.each do |review| %> -
      -
    • - <%review.rating.times do %> - <%= "🍦" %> - <% end %> -
    • - <%= review.comment %> -
      - <%end %> -
    - <% end %> +
    +

    Ratings Summary

    +

    + <%="Average rating: #{@product.average_rating}" %> +

    +

    + <%=link_to "Add review", new_product_review_path(@product.id), class: 'button' %> +

    + <% if @product.reviews.empty? %> +

    + Be the first to review! +

    + <%else %> +
      + <% @product.reviews.each do |review| %> +
    • + <%review.rating.times do %> + <%= "🍦" %> + <% end %> +
    • + <%= review.comment %> + <%end %> +
    + <% end %> +
    -

    - <%=link_to "review now!", new_product_review_path(@product.id), class: 'button' %> -

    +
    From 359172fb2a5f3e98a8c805085c0b5deb4e861486 Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 26 Apr 2018 07:09:01 -0700 Subject: [PATCH 167/252] product quantity gets updated --- app/controllers/orderproducts_controller.rb | 11 ++++++----- app/models/orderproduct.rb | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 0a796df290..c61a8c4e5a 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -52,7 +52,7 @@ def edit def update if @orderproduct.update(orderproduct_params) - #add_inventory(orderproduct) + #reduce_inventory(orderproduct) flash[:status] = :success flash[:result_text] = "Cart updated!" reduce_inventory(orderproduct) @@ -75,7 +75,7 @@ def destroy def clear_cart Orderproduct.where(order_id: @order.first.id).delete_all - add_inventory(orderproduct) + add_inventory(@order) redirect_to orderproducts_path end @@ -97,12 +97,13 @@ def reduce_inventory(orderproduct) @product.save end - def add_inventory(orderproduct) - #order.orderproducts.each do |orderproduct| - @product = Product.find_by(id: orderproduct.product_id) + def add_inventory(order) + # @orders.each do |orderproduct| + @product = Product.find_by(id: order.orderproduct.product_id) @product.quantity += orderproduct.quantity @product.save + end diff --git a/app/models/orderproduct.rb b/app/models/orderproduct.rb index 97d6d5a877..22e718e9c3 100644 --- a/app/models/orderproduct.rb +++ b/app/models/orderproduct.rb @@ -8,7 +8,7 @@ def self.create_orderproduct(quantity, product_id, order_id) orderproduct = Orderproduct.new # change quantity to reflect user selection product = Product.find(product_id) - product.quantity = quantity + #product.quantity = quantity product.save # assign form vars to new orderproduct orderproduct.quantity = quantity From 04165a81b4345afc109057d73df74ecd27241b74 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 26 Apr 2018 09:40:50 -0700 Subject: [PATCH 168/252] root styling --- app/assets/stylesheets/application.css | 10 ++++++++++ app/views/products/root.html.erb | 23 ++++++++++++++++------- app/views/products/show.html.erb | 2 +- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 1a9be3ab1b..df9110ad7b 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -96,6 +96,11 @@ justify-content: center; } + .root-info { + display: flex; + flex-direction: column; + } + .merch-container p { grid-area: text; display: flex; @@ -163,3 +168,8 @@ th { table { width: 80%; } + +.home-title { + padding-top: 2em; + padding-bottom: 2em; +} diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index 2a677eab83..1cad4e6e78 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -1,9 +1,18 @@

    Sweetsy!

    -
    -
      - <% @products.each do |product|%> -
    • <%= link_to product.name, product_path(product.id) %>
    • - <% end %> -
    -
    + +
    +
    + <% @products.each do |product| %> +
    + product pic +
    + <%= link_to product.name, product_path(product.id) %> + Price: <%= format_price(product.price) %> + Stock: <%= product.quantity %> +
    +
    + <% end %> +
    +
    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index e022a6dc57..00187efc2b 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -48,7 +48,7 @@ <%review.rating.times do %> <%= "🍦" %> <% end %> - +
    <%= review.comment %> <%end %> From fc3e3239cfc696fa95b3f99b0f6f0717b13a90b1 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 26 Apr 2018 10:01:32 -0700 Subject: [PATCH 169/252] fixing css --- app/assets/stylesheets/application.css | 5 ++++- app/views/products/root.html.erb | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index df9110ad7b..595c78db07 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -125,7 +125,10 @@ .product-container { padding: 1.5em; - /* border: solid thin grey; */ + border: solid thin grey; + margin-bottom: 2em; + margin-left: .5em; + margin-right: .5em; } .product-container h4 { diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index 1cad4e6e78..8d62979d12 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -8,7 +8,7 @@ product pic
    - <%= link_to product.name, product_path(product.id) %> +
    <%= link_to product.name, product_path(product.id) %>
    Price: <%= format_price(product.price) %> Stock: <%= product.quantity %>
    From 06d0c451d1836700192dbafb46e6b2c3a91a8b65 Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 26 Apr 2018 10:13:42 -0700 Subject: [PATCH 170/252] added migration for photo attribute --- app/controllers/orderproducts_controller.rb | 18 +++++++++--------- db/migrate/20180426171206_add_photo_to.rb | 5 +++++ db/schema.rb | 3 ++- 3 files changed, 16 insertions(+), 10 deletions(-) create mode 100644 db/migrate/20180426171206_add_photo_to.rb diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index c61a8c4e5a..6daac3b174 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -75,7 +75,7 @@ def destroy def clear_cart Orderproduct.where(order_id: @order.first.id).delete_all - add_inventory(@order) + #add_inventory(@order) redirect_to orderproducts_path end @@ -97,14 +97,14 @@ def reduce_inventory(orderproduct) @product.save end - def add_inventory(order) - # @orders.each do |orderproduct| - @product = Product.find_by(id: order.orderproduct.product_id) - @product.quantity += orderproduct.quantity - @product.save - - - end + # def add_inventory(order) + # # @orders.each do |orderproduct| + # @product = Product.find_by(id: orderproduct.product_id) + # @product.quantity += orderproduct.quantity + # @product.save + # end + # + # end end diff --git a/db/migrate/20180426171206_add_photo_to.rb b/db/migrate/20180426171206_add_photo_to.rb new file mode 100644 index 0000000000..89f9f93406 --- /dev/null +++ b/db/migrate/20180426171206_add_photo_to.rb @@ -0,0 +1,5 @@ +class AddPhotoTo < ActiveRecord::Migration[5.1] + def change + add_column :products, :photo, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 223058100b..e85c16f102 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: 20180425124546) do +ActiveRecord::Schema.define(version: 20180426171206) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -75,6 +75,7 @@ t.bigint "merchant_id" t.bigint "orderproduct_id" t.string "status" + t.string "photo" t.index ["merchant_id"], name: "index_products_on_merchant_id" t.index ["orderproduct_id"], name: "index_products_on_orderproduct_id" end From 61a5461d0634ba7c40fffa339df620cd53356aba Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 26 Apr 2018 14:22:46 -0700 Subject: [PATCH 171/252] product show --- app/assets/stylesheets/application.css | 21 +++- app/controllers/orderproducts_controller.rb | 69 ++++++------- app/views/products/index.html.erb | 2 +- app/views/products/root.html.erb | 3 +- app/views/products/show.html.erb | 101 ++++++++++---------- app/views/sessions/show.html.erb | 1 - 6 files changed, 106 insertions(+), 91 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 595c78db07..5aa03c82d9 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -108,7 +108,7 @@ margin: 0; } - .rating-container p { + .rating-container p, h4 { display: flex; justify-content: center; } @@ -176,3 +176,22 @@ table { padding-top: 2em; padding-bottom: 2em; } + +.product-show-container { + display: grid; + grid-template: + "text1" "image" + "text2" "image"; +} + +#pic { + grid-area: image; +} + +.product-show-info { + grid-area: text1; +} + +.product-show-form { + grid-area: text2; +} diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index c61a8c4e5a..695889a852 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -15,35 +15,41 @@ def new end def create - if @order.length > 0 - # creates orderproduct - if params['orderproduct'] - orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.first.id) + # if user is logged in enter here + if @user != nil + if @order.length > 0 + # creates orderproduct + if params['orderproduct'] + orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.first.id) + else + orderproduct = Orderproduct.create_orderproduct(params['quantity'], params['product_id'], @order.first.id) + end else - orderproduct = Orderproduct.create_orderproduct(params['quantity'], params['product_id'], @order.first.id) - end - else - @order = Order.create(merchant_id: @user.id, status: "open") - # creates orderproduct - if params['orderproduct'] - orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.id) - else - orderproduct = Orderproduct.create_orderproduct(params['quantity'], params['product_id'], @order.id) + @order = Order.create(merchant_id: @user.id, status: "open") + # creates orderproduct + if params['orderproduct'] + orderproduct = Orderproduct.create_orderproduct(params['orderproduct']['quantity'], params['orderproduct']['product_id'], @order.id) + else + orderproduct = Orderproduct.create_orderproduct(params['quantity'], params['product_id'], @order.id) + end end - end + if orderproduct.save + status = :success + flash[:result_text] = "#{orderproduct.quantity} #{orderproduct.product.name} added to your cart!" + reduce_inventory(orderproduct) + redirect_to orderproducts_path - if orderproduct.save - - status = :success - flash[:result_text] = "#{orderproduct.quantity} #{orderproduct.product.name} added to your cart!" - reduce_inventory(orderproduct) - redirect_to orderproducts_path + else + status = :bad_request + flash[:result_text] = "Error - products not added to your cart" + render :new, status: status + end + # else user must log in else - status = :bad_request - flash[:result_text] = "Error - products not added to your cart" - render :new, status: status + flash[:result_text] = "Must log in to create an order!" + redirect_to homepage_path end end @@ -91,20 +97,15 @@ def find_orderproduct end def reduce_inventory(orderproduct) - @product = Product.find_by(id: orderproduct.product_id) - @product.quantity -= orderproduct.quantity + @product = Product.find_by(id: orderproduct.product_id) + @product.quantity -= orderproduct.quantity - @product.save + @product.save end def add_inventory(order) - # @orders.each do |orderproduct| - @product = Product.find_by(id: order.orderproduct.product_id) - @product.quantity += orderproduct.quantity - @product.save - - + @product = Product.find_by(id: order.orderproduct.product_id) + @product.quantity += orderproduct.quantity + @product.save end - - end diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 1c8fb16a77..3305da927f 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,6 +1,6 @@

    All products

    -
    +
    <% @products.each do |product| %>
    diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index 8d62979d12..f67190c386 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -1,7 +1,6 @@

    Sweetsy!

    - -
    +
    <% @products.each do |product| %>
    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 00187efc2b..bd0aeb1352 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -2,60 +2,57 @@

    <%= @product.name %> details

    -
    - +
    -
    +

    Stock: <%= @product.quantity %>

    -

    Price: <%= format_price(@product.price) %> -

    - Description: - <% if @product.description %> - <%= @product.description %> - <% else %> - <%= "None" %> - <% end %> -

    - -
    - <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> - <%= f.label :quantity %> - <%= f.select :quantity, options_for_select(1..@product.quantity)%> - <%= f.hidden_field :product_id, value: @product.id %> - <%= f.submit "Add to cart", class: "button" %> - <% end %> -
    - -
    -

    Ratings Summary

    -

    - <%="Average rating: #{@product.average_rating}" %> -

    -

    - <%=link_to "Add review", new_product_review_path(@product.id), class: 'button' %> -

    - <% if @product.reviews.empty? %> -

    - Be the first to review! -

    - <%else %> -
      - <% @product.reviews.each do |review| %> -
    • - <%review.rating.times do %> - <%= "🍦" %> - <% end %> -

    • - <%= review.comment %> - <%end %> -
    - <% end %> -
    +

    Price: <%= format_price(@product.price) %>

    +

    + Description: + <% if @product.description %> + <%= @product.description %> + <% else %> + <%= "None" %> + <% end %> +

    +
    +
    +
    + <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> + <%= f.label :quantity %> + <%= f.select :quantity, options_for_select(1..@product.quantity)%> + <%= f.hidden_field :product_id, value: @product.id %> + <%= f.submit "Add to cart", class: "button" %> + <% end %> +
    +
    - -
    - +
    +

    Ratings Summary

    +

    + <%="Average rating: #{@product.average_rating}" %> +

    + <% if @product.reviews.empty? %> +

    + Be the first to review! +

    +

    + <%=link_to "Add review", new_product_review_path(@product.id), class: 'button' %> +

    + <%else %> +
      + <% @product.reviews.each do |review| %> +
    • + <%review.rating.times do %> + <%= "🍦" %> + <% end %> +

    • + <%= review.comment %> + <%end %> +
    + <% end %>
    diff --git a/app/views/sessions/show.html.erb b/app/views/sessions/show.html.erb index 5ff31c9840..e8dacd9b29 100644 --- a/app/views/sessions/show.html.erb +++ b/app/views/sessions/show.html.erb @@ -1,7 +1,6 @@

    Sessions#show

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

    -

    <%= @user.username%> products

    <% unless @user_products.first.nil? %> From 763e8433d6b93fe2beae7f46f630fb9c8708ed6d Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 26 Apr 2018 15:06:07 -0700 Subject: [PATCH 172/252] products and images --- .DS_Store | Bin 0 -> 6148 bytes app/.DS_Store | Bin 0 -> 6148 bytes app/assets/.DS_Store | Bin 0 -> 6148 bytes app/assets/images/apple_pie.jpg | Bin 0 -> 200959 bytes app/assets/images/baklava.jpeg | Bin 0 -> 70355 bytes app/assets/images/cheesecake.jpg | Bin 0 -> 66660 bytes app/assets/images/choco_cookies.jpg | Bin 0 -> 175265 bytes app/assets/images/flan.jpg | Bin 0 -> 43765 bytes app/assets/images/fruit_bouquet.jpg | Bin 0 -> 143856 bytes app/assets/images/german_choco_cake.jpg | Bin 0 -> 87988 bytes app/assets/images/lemon_ice_cream.jpg | Bin 0 -> 61252 bytes app/assets/images/pineapple_cake.jpg | Bin 0 -> 76082 bytes app/assets/images/pistachio_ice_cream.jpg | Bin 0 -> 40233 bytes db/seeds/products.csv | 11 +++++++++++ 14 files changed, 11 insertions(+) create mode 100644 .DS_Store create mode 100644 app/.DS_Store create mode 100644 app/assets/.DS_Store create mode 100644 app/assets/images/apple_pie.jpg create mode 100644 app/assets/images/baklava.jpeg create mode 100644 app/assets/images/cheesecake.jpg create mode 100644 app/assets/images/choco_cookies.jpg create mode 100644 app/assets/images/flan.jpg create mode 100644 app/assets/images/fruit_bouquet.jpg create mode 100644 app/assets/images/german_choco_cake.jpg create mode 100644 app/assets/images/lemon_ice_cream.jpg create mode 100644 app/assets/images/pineapple_cake.jpg create mode 100644 app/assets/images/pistachio_ice_cream.jpg diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..aee8b7f99e7b8ce9cf32235153cbff09a0410baa GIT binary patch literal 6148 zcmeHKL2AQ53>-Bs1bWG_$NfTnV1j!uKCicRx9@Eu_bsu2`}SQ`HOHX_-apH?*N>^M`PJ9IoXsgariBCp!9Xw& z3cWt8Xs45yaszISWc?7Vd=g4h#nm?({xYBVn)LC>q QrxW8LkO_$<7`OlfUmQ{{eEJdg@dfnQg^?uP<5tch))UmX~{1pp2ZcEj9z31G1RuqL*F zh`==`Eo-SGgIZ^>C@T@>TmJ_T0OZc1q z|Cz)U6`%rtrGO3=tHm6jl(n_&JN8I*kRDcRl0V+TRsK8wcWEq{l-o++~3Q&P(R=~aw1#VaqyFmYR zVDJ_II7ZkFbMGa9#R9;Z*aad2)1U%_s@Y;_&=D`0R};Iypo{v=I45t`>`>HiN4$8t zXbt2@1*kw@ftOg$tp2ayH~RlRi7P5V1)fR)9WU3*1)h|(b?`W=wFUkTx13+N8RkyG m;N=+T4-ZW$e#hzg+>J)t-v3v?HgYJ literal 0 HcmV?d00001 diff --git a/app/assets/images/apple_pie.jpg b/app/assets/images/apple_pie.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1aa532997d28762112022cdbb0e4a495b12c1233 GIT binary patch literal 200959 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

    N@GypT0uJj>jX6(a2alth^v$-Mu~OF2>+8 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�Gw>KK?{G!SW2aCkEYjhX|k7eTqwtkE2&YbECr_pS6 zi+hXc6<+QYkhhG?GFAp}&biJ-Hgyh(Yt%YC+CH&jFH-ecSsVbcr_Vk{Bh*$i)xU@R zP10RerFGXv=~g<9nWRK4Y;>a&B&!QelIR{mrdyE@HiD{{TJY zhiE)(wvW^d_Tw2-`cf99_)*b!TAaGPQAoOT?rAjJc??T=I3(m`jC1@n8}QfhcJo!& zHGYumyUjigM@?b%I<>PXf^|G>eEN*ziqiFa%N;9BpI5(@Kclo=*3sp0v=7X=K5^^s z?Ob(B2XLHBoAKZLGwyk(Q`JvG+uvO+wymc1FmjrGw36;iNDtpR$n>nHJ#SdG*8c!$ zL8#qDsIz#+pD)Gs99=I5vS@_(g7;I+=T@3yZ+Yxb%ATW z1=RWuoY(i-UBnifiFts?2idXt58jj5gdV+5sd$X4oi%VAkM3z55%`DG*SbaCo7Eb= zv8Uf(u`^yHhKf_}$&NnaxmcJkBUX`!R{V-jZ@;y2ytj}ws7<~Cs~ozq8~U1M#2-^D zT}R|z6cOolS*5bV$2i*YxXAb5{plj^X+*uS z8=a$&KTmpItG{x=U|}Mx2lVuz^G7<$BL{ksx60ge?^dV-)bA+^{>+n4@XB1ra9bsn_eMvyF`UrZk)w;s zf>j5*4&L6mt9Lqm^_mH8ZKRD#?gWjw9)wWWpK&3O1!Iy2r`o22exR1>K<*jXxC(n< zaZ^2l{TREE&xFUzf;WFI{r)N$2yz0JDW5l~12qJIy7{+c3@#TLA2o3P(Ouu^Iy`8b zN;V{0ys!#6(6 z%xKW{(^_MN;c4}OlG>kiwS6UEj{#X_-Aj(7=BUyBU+Y?q_wImPEo^TC>aDCaCkrO z^`bpJ(0Vj_Z`aK;Bwz$oEO5sof_+aO{?tQF>Dzy+X;N9|Oy>%~w(R!F^rYs&Yv@hR zH3^QI65fYpV3!Z|S8y2*1eGK&z6CK}T3XpdZ#AXjC@I-9h9BsE%Bb4(^Q$qEJGAEn zB63gbS1mM`UC4=Y!A4AMoS)@J*GL`iLd$_W-0!DfTEx2~kyr!fAd*P<{c76kQ`@wX zLnh^LM%>{15;2eVYmw-)#?HxN{2}hcAQ8?eZN%~zQrYq4;cVc8?Z>@B=^mr1UoOyqV?X)%sBj0V zYgw@yZS6&knU*`5V>#T>Fae0q7(ST()JiK@=afuiLdvC`(3Rk4KkGsC+v{YuNTu-^ znjZ|vc?#LcZ-0t8q?JqQE+1@><7rjTo173wY+&d8nxxdgz^u1XU-mj%UidRBG)b04 zAmzEq`yce9`W>r5c&`~!f-*%^2H_qmEDi0D0rmqtUd; z=GCJTq+rM93`PI|9Ax?f-kC3_jkFsX6)?LVHdam>p5Gq-0HsjV3#7(rBoatr+DGNU z>_4FWMRY&lO!vx2pKt8aO+~DhA{53Q-F-iwZr|K`)%bMCuHm?v*hehKBzQ5MfCU3Q z^Tr6z%|-Ngvff0pV|~Hc4ttEAekp>|(q)!wcy@>;VH&13mS0bPGtYXVtN}R48#ZDW z?Ds=)hbBoIXm;nsV~`zK%?Ax)2C2W zJJ_AwmiY{)a7+lRe@DL5rN{i?0K*uBKCjhp~}J?io)ah^v#{%A)WdNP$Ey-GJW<^0M{C%uyJv@1GPI@v2@?!%<}C? zrjR=KR^f-(jvBPBC$E*4>MibAN~1UpwBY<#l8Gq%@$d2TN3>3_)ii63xff7pCOL^C z^gYEd$?)j^0F`q3vzdBn>&p(K(=}IL79|YK3(FA-$L>25_oh-{mLC$%cAYnFTn{!r zK|TA|nC$-m5jtjb6!SrSr`=!{c>KsusNnYfDd(pD026IumkWCh$j^}H45Q?5b6KpP z4(Yz5ihPJZ%-Y4m#{45LIod~laZBt3$-S3)Ou<$TKHEmnd630 zf#&g37(ZiFXISqcfB6|9T=Ha67Y75@n5|8nmWH}{xmUXY{(cJ%+Pcn zlX~aSf2@-LtuVENxId> zr9Q6&7Pjutl+G2ggP-D})*&pT-!rR9+_Ip+7^pepsc*&B_ZTLW7gP?|VYr`A1x$>O z5b*QIW1c88-S~Z`JP^_2HDq*E^xbAUK3-Gdrh?U1; ztW8j3ZqdAtBA#$YdCzXuS)u`zqAU-#c&irX_bF^pM02y&YNg)4o)C#&-?FU(lU0@O1IcldpUR-)?L=kg(i=(Ks~-~99m8@e zx)Xt)ilz)=RaqcL8RU^v2DFU4Hx=D)mO+rD{APkVD#R5qp^nNs5t0kYt>7{Os=t>N z_Tu&nt1}{~@WJG_xTNd-VmO^+C5YM+c5-yP~`9%Vd$qYREr3pajdfKUIAfn*niYGi{W%JV&Wvz)KhB9(((KM~lfC27J0=4mCmO}CtUKf5a4n29RbKY)?DeIBms>wQ=P2`Q)I{Dgvs$);}b1Lw3bl71IY%2++5Fb8?+JbkRC{( zTDEdOaHJt+lX!yIod#ll9ap^oE@NbU2@ z3bngi&1K=UcJNo7>M*2obB=!0eOR_2{H1K_dlAb`Q72ET%!di&1Pu270L4kCTiPb= z@`ZDd02m|@&#fxibrhO?yve8nv7sg(Lm?v{(0BbQV*dc~7{?{R(^JKnJE(D-`xEa? zX~hHss1248zUI9qsikRl_>hp}yEZaUemUl|Zl?S}u+z+s6h`7^Cu~uX$NvB$>HX^{ z)Oy=r)}C*wki?(ih>%59j^Y{7S-{>72>$>W{{UJ);nubwzbEL!_uYT5>QR=om{_SD zpymF2#D8p6cy&kCU^drxw-Q`ucZlvz^Y21sw-$~jjI+kv3~+z@t|2~IqB$MUp&rCl zn%L6FZ@%GpZW<{KmEb!G;I{-&OY37CGfM^-$06W$I5cKie`?vUh@oy`To(hD9`#pG zkV^&Ct;+3i=N}pMBj%!mM{}gXHs_X_J|o?^m;5K!k7_w*B$r6B$l*~40%OX?55LF7 z501=P>MZlA5MT$4oHLJM_a3!w=0qpMg#=LG6^T!A&N6**p7c;aWqX~jr;Ia2Z@pCE zBp~B{4u6$UnEga=8}c)Pe!{r!U5M;UXCUw}DdVC)4=(zW@)W&E?X2X9q*)O_F1h7~ zeKV1s^kzOYSU^!Iy5+1A&?n)KLuy?|Xvb`@X^=|BY4L&IJ5xLtK7zdsrf3#DJq$DG zu-wB0m=IXpgSDIw%^>GvdTta-%F|5Iw2NzPI@m*{S}2YvVgZH8J;=%PAAIxeSJTD% zo%d1)yO@&%Ll}S__#|=1J6g4Pm`gz4+|6ZXwZ}u$`vxu@;hN~|LR#>Z$#eb_$C+{1 zj(DpvK#|V(lH4uGD$QeTKm`UcLXJ0&UU{yqr9&u;B9Et5@f&FXG?~vBzf$e1OZ4IHd^s;>^8W0cN5>>&d4KqtiKT)I zIM)I#HW%8iMm$IDx7|G7rAE-fcXd6zp+INE*EeVZ3^VJG%rG&L&lPe82>`vCH!;WL zjZwGwgFFy3=J&zoy*cVthSBZyDJDDqru8uSZV&;%WzIe~3b`EC@mq&1Ue*8+VO0!f zV0a+s&Hd^)wDuk{#c?{zGx&_oVFH#{L2wi42ioc$q$CTx1;j zisuI@*S$hz0?H=uRCrI)K6 zQW&k4N58d*{W@LC+y^5Y4t+-kupXcMX6i17y|~czyGPaZp#BnRH%=!=p(OB*a(ET$ zPPEmp?j3r2rSEjZcd$;ePQ;mjK47`Xbv%uykw~l28fLvPmsaRK7T(FXBkFb+N~I(` zW<2tz{>Js7ZawQu_Bo&~0@KdnpW-+H%jf>fB@alYr~r zz`GBreJ_Rw&K4#<`doh1kk50Ijtk)B>AQ-@VF=(z$&M5#Y=1gl z)Ou?1VbtzytlnEo3zKU+*d7^w`wnt@dUHZGN7$1~xOFh=+Z(%PZRpAu{{X~4L)w5$ zf=J&5&?&h)SUedf@uN|KNyz|x`%q?OD#VY=-yYQEccSWAY=tiE++gh+K*KM& z=b9TgPqfnJ$~eaC9J=EN+PaRQbv*83_-J#zu+QA@_4uhG)E3ztV}bx!Z6u7gJ`bnf zh+cH<{B648;@A}dcx~U5r{z@$22OL&{wvIRbRceja?9#dB8)D~d-7;( z_f0F4DI?U6^{=s8Pd4cz{oHHIJDMMNDhJyc%KQ7&tEqR?0@d88e8Wq=4YogvHJ_KYmj(aHfCcOb|r)ZjPnl0i{vLdRi z7%H*HELiu?J-c?L9*WW0*QeJ@(;-8S&O0#=)Ja>p1xVaGY=7|&{S)itd??nq>|f!^l~rX@J? z`wv6Mrg@-}YBqD1Q3F|jjx@@HlauS^puT56P_y`mfZApCw58SD82Ai}jAPt?tsJwo zi&RNg^difQafRGF&$F^vmj`9BSSj6&1-@9(YMaFo?V}Xu) z9M$=xbce*7d%S08GAP)4gPeMN($v!>wcJ-WpSmhQ*iKn{pVVVNp{q$6gEMlD){FJl zw>D4$Sz+3$;Nj132kHj{=98tk7Ppf+kfbnethg#j!5<)EnQS#hi&D4Ntl2Wjwm{5E zFCUv9U}z4z7uNM%)zmH#SSvCGz}xYUaqB`gpmiu)c(#l(VtbuF)&SeQN%sX-&If#F z>}&0XoNaKi7`E=5t8VYKdguJA^|*~=u(=9S7{_(*yBr_tE3yeB)~!4Z*cl|A2GPbp zpZ58sw&d%fD*j{GhZ@G%>WM6935FaEr)bF^@A=Vq^w=SaNoBbX%t|Xn2Ll|Re^NQ9 ztkQEP_KiXkOD}E2`(~oloBm=;DEx{S_wE-3N3i)m-z3#PAtpknEOodN@>^(UX-6Yz ziUdQAqqgCmKl-5yqR(RxjU*5(i@s^3B!yBvzW)Hunr!SO)Mfprc?pKyW5|aGg&yBH z_o`C(dWFv43u>^$UTvTNP79x2XzJ6D(T-?s^d@zzUMw~++ghoRu-hc^CIH854`00| zP1CxLp)~jNB)%G--bzjY_RpXK=oEY}v+vK+D# zjl^bH$XaOtxsanUUH%$_@;iF-{b-e7B^D;&B(s>@{_yz$ z+qfJGBdFPFS%~S|+iC#e)P8UC^{yDxW+F#B2RFZu3 zvD^`>0#js;F^5##c-z3m4b`kv!Q%zp&M3@6#yizFQ8dfD40rzkTJ5SmmBJOX!pDJx zIOFe74pGFc)){+=_L6-K()ssAC+1w^6wI@ar&VwUKPdR6i^zsf+#GrV+OO#sX5!e} zNPl@AHlJ}s-(NN76gvEEp$o7s!Gqz4WAW)#?i0jAyUM`x_phlTjgEZ4a79SYgl8FS zV?N@98wNn=z_X_rKbtrrqAQ5F6IuC{(#;Gzg=ZxpL6krWuSGs+*_>HSH@V+ClU!4`En_u!>D0+6)xv#5+~k~huO!lJ;)y3nKj|tTg^vE zyUnfC*3u5o8EcBbJJEwqCzmM4!>$ER;fWs3R%XsZ;NKf*~MW7F1@@dtdm zj0L08%Cn28B>IyQN_&9FF^|9AgWTS%&O*Zs1a~`gxSzSA^UZY8?O1~-?#M|4`B3QX z0hx`!bRck8a(}1I2Wl2NUr@@N0kbQ3m;zgwqbM6`Dgxwo916V^)*BM{~Tg7f=8z-G7}!sh}{2M_e%>kRA^isG8Ufi9SJ&r)9i%04$si7C!yE`gg8| zc$tB9Q<0pXPqhk^NgBpLEWOH-JiPLMtwi^wFq(>HMvEMlvM=! zk=mt!%b_Ys$Mh5i+T^M;O;m$$@Bt-HW4lu!ZSsA zyZ2kycf~_B<-NN(xR+}$@Zgs1>?kT`MaNNKSAu>^q$L;*Q7LuwS?)QiW35mdS`t^SpRr9~^QrYnM04Dkvda zBLtq+&1vnet)`Lg6iV0%2`A^ZDPCM%853mDMIHb-Y&YNU$8Ytj@8pbDdmf=+3}M!| z5yiu*=lF@ne%}88rBs&eIAFtQ0OgOaD1DT&Ng45hl6K{!Vh`Kw59wVlSge2*+{Zj_ z#yRhr1=ycZkkT#r$o(!RxcB=JqPuFaSgpa%HstsF)hVt&BZ?{+F!<0p?^^cL>t84l=AW`B)$6=|UG!X|D?gA%O&E*T4GG&b8F=+8dU(VC?IH#dF)&9`qW^ zU7mPGt9Nr8C`l?^zpY4P78}&?(2v);g{s@T-`p6S<7fjrzu)=N_M_H`ZveH^AV@$2 zG|mR^oO@EHr>$Mxpc-YZ#ls%+IoO}f{{WRP&!KA z{{Y@Zt2d#zb64wd%zmo#$0M-c{_$09KN9qvBSyNAN#k8N2@-Ni`}=+9SN??29=nM>0rb&aCpcx$$bLp?I0EifDTF^0DhoV5qkku@el#|x2o>I_M?NV zu913_pC10pN$#w~&Df3-jYy)=ozZ=)^g^9!pJiKud3HC=k0~vjM!Q=k%*GN*6&fqJih+p7n4+2Rk0+omJS` zNi2`K)o=*s12_~h_sKAgRF_;X2RS~1rIYIQ27<=k-Q=E9tPwdl9~H86Cq`Iw!pEp; z?P)%{aHaJ4T!%q}{{T@&eErAIwK2lNYk$%Sk(9L!{lVQ4_)|K`Z+)-96VC3q(;dpP zD-4H|9Iv=iIrXiIKA-w1;?b>~1mW&(SIfKCl^DmS3jY8qk57i`*Hc+uXK)9d!p%u?7Q?TRSd21f((s}s(D!g&~?cZHtc#DWDEa)pep{jVC4=x}g;4|)>jF9GlE z8VMn`jhfX<7g^f_&dR@-4*494w`eCbtIryK)xAuDo?!}l`G^~UCxCewuI@ySx%2jV zK_lsL+O@r`TW6kl)FRB@ssK4doE-M65=_XeF@ooGz$A9S1K|5JfPMb}h*#JyquQW5 z8)%7$CP)0s`za^j`AvMhjQvwQ6HIQWOu`v2-ovM9Hy7798hx7XS8p+XIb)NF7uVm4 z%&(-@HLXT>)b#xeS+Tue6HFGKmKQJq6EB z=~w#fK+6ryt-u~CXY&q0Jbx1NpGp_|8pOqSWV!|XP~FBZA(AVDCy5|AXvoj+S3aCD zuJYPm*js7Zwa-A9FAD{^lHN_Q?I)eXgAAGV92$io(e8SR^FVzQU9qr<1>94{>?c?5 zNl;ISx&9@f`F`e^6GK7^vAly$p4U;6MCzLxhd)g$a5FSP4nZo-oMZeCOI=0yCDD3} zI>+qWy+XrOg4o&#II6UoO22qD>jEZ=ZQ<3!ewb<^umdY8E=%;|gB=g{Q-Lf+kt za;_Wti(0S_i8Dj$ufshrrFt}6S=wFQ-@N&KMiymzNO>m;4n`Lv9`&4EH$dCH-1keb z4FWjN(MK!Dzgu)TE`70(NBb4(DQ&*4b8B&L6~r#5>lQ}I2to4W7ofd8{64$B zT`O1Vdt`sv5vpn0JH{R*8?a>j-e3U-oSrMW7@8cAPI!;v9&9VhW3%_U=h&u(=R>wj zxh^NvS)NJT!9E-i1B7V~IVX=W0Am^Es7+%X+z9;36N1V?7(SdZ@7lC$-9KKkxYfD_ z+WOLK%}Gt>v#hh6LWsF&v)BR01K$)9^5#uHrZi1QQPXUNto8=OP0-+x!$>oMa=;Aa zw<9MemXzzcsI?22+te3AhYcxVs4eZTWo zD{<&SU1Id=$Z&C=P(3OjFyOarWQr|uXqY5B6Wsda^`Y{>%76?Ul1&h;)Di34tXTL* zxcgIAMro4EcJjo9<&bzW>=`3Jn;$si^)$WUG{qu~JjVcfmNn=P!)}(2#t`#m9b#2R zE9ywy{QG{iHfBJrAznWhmAsqKhcqn;`qx8+F0Q4uw+C{^76X0H#%bq5>1n2x8>x|{ zhz~1F+>zKEj>C@LwR@(zZWp`puZY_k^Sy^H-?z7JDC|P?U2@Fvvtl$rHlV@mKbJJ3 zrY_w_w_U_(WlK(13?+E-a5!TsI74EL{XQxzdzIAW^k7S< zTWIABGDFGY1tY(FdQuj#aim_{i+6-s0^VR(ZsqkE914BD@NXcQd^V0Z8%S5! zao^LuW!m|XR_4;Ms^`Q>cM;<$ z^Dy+t_a61#;cGx8@fBDDz0`hgdy((l!uP6+M# zP%TR63&^7>wOI@$kH;d9-Q4{`m|J3(Xr9ZB`wTAL%zt(+lU?j#--cgW=6$oSw4Qtpj+6nZpQ zxhh6k+??zl{{Vc^Xy&-omeMNh%FT+9_ca-hnfZ7ko{%Wk&@hK7E zuoQq#JE?-^@>!&L#kqtOAwlOPef{VZwVI|u=Z|qh<8x}rFt>P!&=PK^_7Wjr59q@+()ki# zCXc!AkMC7hN}U-t(Hjsurp?IRy*_L0oyEna;!STfkxIO)#>GheMR#Gi;r%PAPd_{# zPrVt@8Zv@A*qS#_ek}D4k1D3299pys$M1&Oaq#2(!L7TZ{{R-c2VC&2E;SpS3hB(r0W*~6$3W%v63PO{inC- zihi~K0Ek_BXd<@Ow2Nz$PB+Bm7>{F+b4l*-j=j~~D!k%4Y3fk=RoqGPJwtdK5_< ze@k?d6VBFb?LO6R?!qRDG`@g5dq^jZpn83~)d+6lje}3Q)UI-)IX;-hT}?{LSr$h} z-o1iEKqvkG0D35(Bc;@@`Jhi`L2ocIycTw@6$frd8Q_oi?Nu6kwQ~&7lI(N&cI4+7 z=hBWts7oo^5sD(m8(uM<{{H}K<;A`9(wCY)s5@}HV;tuka0Lxz3ahYA;Wgv}f3y_$ zehLkniV*{C?*= z?fWpQ2RZhq4upimVRspdK+)mkEcxz=Kwpd+Nn3j+@f|fd)z}nqtte zwXHn;B(@O4^;=|~cbQpnv?$uZ@}w^wv_>_2Ta&@^7&>uN3~CeHeI)YjVn>ky$veI% z7`c{xIf}oXO6O|rAd`cTeMJ`3^(i5l7BnrB|242RQPDJoDSVMP`H- zmT7Un1eIPrfx!DvQ?50osVyO$h#R*IlaEY)KkHH3bvCVcs{ZOSktRk|U>3$Ib=OwG z)Ppl>8oSf3P%N9bM&y9roF7X1(>K!;+yW8F_&%T3zR9Xi+H6ou5X4#9ThzDt^Hgqb zZep8mjmDuUab&ql>VI%ULi*AB29C?m-{{T>rLPqF>j z)E44GJ4MJJ8UB>Nsda%!)+k^|f`Y}nl5yMZSoQbfWtFte;W9}1?ZGses`d5#83lo=@NU9f@Isf2hCBulOdx%?*rIUg34n8QA${R3=vPkD<{Oa6)EPrbF_t)-#+!+8F zB;Wu^^{%MvqX^r6gHp zn%)*h112R?wVNG>Kiak3TTQZfNtKb15~IpN&%vY_^|!RS8b$ENc#3xCZ?H7W8Jug3 z@E;)RW>H0RYQw;dgA>7F>OZv`66GUkS~Zb?W&mLn`h)F6@2sMXO?Pi3QYbi>BXf`O z0o>sK04^%LmML!|TwB1t&Wq*;jz}E+_@@Mi*5z$n4{fR4$0X|E+#HlDKPW%>_o5K$ zO+3wSG;z8x@XKz(u^i-kSH!l3rHX$S>6I7E#1dT(ae?30iu-#6ao%3ZeQX*eU7=tZ zDt#CO>G$`q8Wi>*>~vtojUGo#x0SY+J;C(IsnSV|Vir5q4scKRs?ZQGB`+DkR3ND5 z0D@1+B92;E$s$WLdE(qQu{glbKkQVRo;`>=*01bIG@i7(>8)ZpW$Bx1jS*EpXd#dr zsoQtwiMSvy9#O_S=DiKmnxtB@Ca-YN-dr}xtt?tKj%#&q%4AOKf!T+rCcNm31}XFqO}BhM&`LAf^(nVE1NVfL?%v4F!F8;2sIREqWD21vhP zK^hBvr!O(b{@Z8H2;i#>is_Jr4WzO~ENbjd`L z83&DbIU@mk;NuzNjmzpP8(FSkNHrF=Nhg!{7SY0_ZBF~L!z;(|o-!)IiqF8F(j^gq z;qGo=m%{>H<#C*;JbW7Lft921?h0Ns6RnIY6Tv=z5w~Sq)Hv*S4=|z@&v+p)JXc8e+uR?>M{J=uWm&+!f`sFKoBWVF7PI3SUY=HLKh zf#z;9N3$(^)QLNh-(10Nv9{#PWLP4cw5J@AoM-<4iT19oB-Zh)FDz*zscVaZxJC59 zB>4});=9YLwAPJs@Wdw!MXkFKcMRiyl$@`w;qO`RTy-7g&6Uqi=rG#fTo4-T$CJ!g zyA7m%^)cpHw(kXY=;OZ%}-yt)TV0-O)pKp(BOBs)NSURM(C%pWd0NX0C3}) zPoJc;!+m}(I!gB1*G>KPt;7-^6^1ek#;4A{o7b8j7Kik+wbi#v8?7q#BOA7xb~h}Z zz7vy^k;#p!XV((bPKx;~x}FI1iA}1sGVL*jz$B^5A@$mFrkAtw?WV$-J`uvdQbBfg z3H0l$n=YvEH5k5{M@!A?7z2%soIiic{M7SXUD)Z3ZknFC9C{P@uwSjXCj@>#O72cS zgyl&U4W^r=+FQ?U7g=j?e$owcd}|_CJ;;_YzC+Irv~N%ASfaOsRJiI}yLha(+OjlD zA-GNkL$Cr+Kf-*%xTE(b?m*HAHq%s1GJB0vRqDr$^)NQeExy}!8*o7K?X`5YY7m=%@Ns|lBvOSua)mVG&- z-sx8eCDYc*WioFAIZWU-4|v;<4;9L$mRds1aSHU7r)@Tt%JC#*seFzEu!EfX30L*5 zSETrp-~NB^JyBz<=sLu6X_mJe;<9ig`gsboOPr4n2P9-3D*pG6RgGkMjm799HjP`u zR2=7!LP@mt>~UBoovmq_MyYGnmOV3l3p^sxCbN*=Q#JpYCQ?ox1B|7 zbi2D}k64Gzsu^Nsg${5OH(=X&{W+s)$q)Fqxs>vL5wU@?t(6}4?{aRY{5|Q;uC!Lv z4#b94Ym1naME98BqqhZpKK18*qp?jVs`ZE0v^(2N*-BgJdSqeBN9MV;p3f z^<~_!&m6JK1a~@QBf=rUkh5?$y5o_^JE(rGqOJ6?OC^B)rlF&YP=yjl)795$WG(rZ zk8U$u$i)^7te1!LkBWHPvOc@@Jh;P7hW-sRP1LnGB)PX$>OD=BrIAF3EeHf;07f(1 zlj_UhiE{hs=sy=vwwCj`EqZg3ToISSiG z2N?sN^t*#0n>Dh$#n3;G?|=PE{ddxxHDlA3dcQ-(sOt}NaUHusZ?aenuY=)kQ<&If z4sxXSq)ED79Yb7?L$z7cS#>3};~O-QFgPl}4i0~xr6%-OR%%^2eLcpBuge{bv4s}* z18Pp&vNw*|2atX}E8716h0*mr=SJG~Pgc*Q-Ssu~xJxURv@lAsHh*_MKRWIUwejnk zC{11ZBKp^%TbGzIj~Nh*rOjBVNouhECJ zOSF#LQnR;^+QJRd$bX%LF!RTp;l3*o{8IcNn*Hx}zMIhFeO7qDO&Ta-Na95}X_pu* z2*+-HO;L6eAljYDV0p^2EEU)|llMHAHkm4a`y;6ygSIGr)r+~qxdkRIl{{*hx1 zsRk}bq?eO1s>protAkOl!zr;r{@5G^Z&6u=Be6FysEA zIv#cBYNVoirsDP;>l=m2P{s|em-ig#;t7x zuD0aKxE;#42tL#bC@-(>5Zv7OIR5|<&#$1Xdu*)k30ZtrP;yAzTlDm%KnSqXH{WtM z*6%jFYXn(fIW4>OpwnFHGAl^ZMu>95Y90s3_M%Z-G?KF{ejmud)S9qn2qKB%G;LUU(Vx^{%&CT#>Ve-ixpUBB?4fRgF$spvhA9)>PebZj&Gw za_kAtamGe_0aHZUYs@~3&0t4!8|6s(QZbqg+I6^*qw(F@hDHzj{{UvDODN)f$uJlI z<9{D&iwM5N5z@<3xKv0ax>=D3+RS#a`{#=9HmewU8QUx{0Y86Q1!HRK2%TmQ+ko?s z!w1vmx?e=d_>`(J2RjZ1C=1iBqMPdju`FEQMJ(XkZDmv3cAz?~#4Q7`lO9}hazU#1 z7Y=}vGLi@I(%z-0+|O?8hYUZ7Pb2iG<6@R@U=Bcm{{U-D+L(p_?CMEX1HCcYU+U4I zGTKTB@3;H+svRc;Ynzu;XUfZ#64B4e;x? z7W1A}l|-wzKA`^qdbus)JxkXVk49;?PpDnmxP~+bU|fDvocf;Ll#{7iMz9d~aYR=v zRUgxnfJc01(z?T}{dD0qtLYX1qYNZ5_?&aW9D92As^?JYSz(vNyoxwTJ`@;Y>^Ea1 zfynGT(P?--p*8J2z+OC9bQiF|IAU2yX80eaD;vwZOUY%j`XU&dZ;N++-OV)Irk!?V zk59Jo{2&>^@;xC>;==JvMoJY5K=&a1s`~6!mwbwP+!v^&?d&F5FVrw4 z-A@?(1q8galFlMU%1Q~~AuLxv){b7Kp;eYC1Z?DwD{#Z)f29YykLj)yK;~%AV54y# ztuRkgzF$(b0_JB4Zlp*?-dh8=KW^Qtv|63rtPg08RvC{ikIm`Dc4_S}Ou}UBOF2BB zlU#XYo<9*w06+?H{mpf|_9Y|`b|nd$YO^$)`yTWr={!f^ZUX}V=9sRnCtGOlnFoZ# z5F5K=+v1mXC}j=fM;QovpPH2f6Dz;^cPL8f1o8-pXu2KQzQu$V{$N@O_BO1^)c2a6qeZPLf7W;0PVR%9Yk~PILOzl({?{ki*#b zsvjHmBAGw9Y9jtAVh(fL*A!e@MR979DIAY7pL$vSpbwnnFz!dKU$NE4h(<=w>}YFh ze_|6|%jn21E#A)g)v{5!2BwU+hA?*z>MHHnhWiYS=f>~T)~J?iSxiz5zvyG0pheH8CbSJF@RBJC$#=R&?m-x(Sw3SPldfBm<^;r& z-PyKWz%6{%i8TDk(KnTFVYtC zleQ&L4`4fwe9-IsQsexyroesA9e%{s?ZH{}+kyW8;Hq-j+#})Pkw?m!_FMEVti_f7Gwje~n#TrAguH zM$=Y=40u;j1#EmW;Qs(T(^Mah@vZ53`e2B7A!E7R-#yd~`6V1u;(07~gBW+@hQ>^N_= zNjx?<{mz`*X6io^bW|JUzrAG#@|$yy?@xU*4Ubo8-?g-zLJODy#E`6?yo>(;l6Mv5 z#A7K~kEd^u?N+U2ywmSIOG}xp+<)#uS|UtJO!6)w18i zpM@ok+F7y(=a?K5?eqO9VZpV(%O=$@_cV(F(?_~nen7!0xf%U?RJWFvaN4!S%zhef z1I(iYdUO7@ok#e9^UMu|_Ng8>7V(thp4e<0{*-nuq_ViSj^5_-D~}V5NZYaNj2}va zVqAx0N=_zalj z1D@xP?NxONBx{J|vPX*PN%ICHjB>0yXV)~&r4=1W=#GR#7qi2ucr6;Eq1gT_a!4HG z9sPUr%^9(2Y@>S{g=bueqafggK5hm(ABrWd=&;Fc`$=JmZd_(tc-uKppzizQ(x8pk z_A*^tM7I)KvKa^`a8P`tA5I9*+Kn!(I-d3=i@O%M($%3=EiNC#QG=dx2>1U0N}+QV z%z#YD07!f}iQsPsAF0C*KJ<1Qd9AJSaTde86(sV?c?bE|+uIk4IjvO#K|3k$-TQ{k zP%Ywh26Tw9+vfSvmniCX9ATHskTLP?_o7j-F%=SQOl~Z5jy)=9ETnFuR=160+BY*3 z`FoSQ--`J5P+QGwG~|ISMcGDJF9#p5AJ&O$M&Rw&Q|$1@mcAtLkX}584U^AqJv(6i ztGWHP86?HI|cdUfO`2xggH5|~v3u_KI%E}WO6u>s5Rwcfps=d85- zTTaxp$FtM5TWi<`;eCG`n^ZVBVZr^|1JC$PP5U{VZ=gcV47LhHRBP0)J1;dNBebUIXva}%g5itjDFg&O2Qd%d7 z1EteNrlAq;BV$V@dC0&hbHVf=*ULWw8#8At(oF@rX6p8HlKAu|9%26gaQ30v*HSHw zl$xc}Lj%VXHKZzcVlqPbjG+GUbA!h?uAKq1Jc!QRRzuZyap_ugcV>Mu4ME%KZA8!D ztZcyJ2M23ox1p>i;A*xP&o@zY(USVgVf9xQS3)DO@!~!R+ItY|!S$z0lX=uP*V=Zq zqS zYF&GCJx!mD#~6rI_DqURJ4RS0(qgvP(#UMQTl-aJSq5{7kQ2D6?IKl;H&N18QXN#? zOR3q&=q+V}@;%$rJ5{+KzFhYQkSZM~PP@`?Ogc|eYF107+zAj}!?Gy@43$=K`=>sr z-cyeBbuX7wl6_qD4vQ|4bgL6sUBqEQG0&Ly@LM>;FO<|2e&J@o0RjrRxYlf*<3N6} zvoo0%>eQ$LBAc_e7tUjEO^?M8O?o-ymsip{gGDyp8jGzjQ-f->fZ)3?WzTKt#(ULE zdwokxx0cG{Jr7XSB0eSLQw`4~2b}T$09kR!W#m;$s~Ilup|sR`Qo`dvyoVZe)|0DA z3wuK$#(Dk*u6mqR9-|{GUKr)5-MFo`*_Dua@I$FaORFQQ zMX6qEy8V4Qe*GF5mj*=Y0hK9knAucfLTLs-?=ZFyh0MJnE6+;BM^v(0PzhLEjoeXMCQh_%gH*jvLq zs7O`rH!d)T86MnLGj*fg=o(ZnsdToRCWq6PW#?%hVbv}hu^Aa`WE^(m;-=I!F=juK ztH}~iU)btC^j}t7$)Porq1sxu5;Adss+b^-4&&+16l+KP zQ-`Nbmrb)=8w+PIm(CIT!bM z=jr5A{{T)!$pCzJuTgb>SZdu(Z`089_eg17W1)2njR%U?LNqEDaSTojR|9Kv>UgZ* zNa!Ac)q2PO0Lhdc71jD>)r`q4-1h~Ij-Yvcmn0Llh{z5&IQHU+x|MPL;GQ!w%pRDX zeTj#wQlO&ea&FS>p`UdrwfquCN7lX)0*Cpj7AG1wnU%6iwRwEna~W1)5XXqwKMaxSg{ zj!F*iZs-2e2|#~J#v;G`f>YubFlIrfl-Ib=db{=`Hj|@f#J4wj&HE;8x&&0sj_*UF9asupo`s@8= zKBN3Hm#?*XZZA5oNqO#kHnO~gELPgXVD9se$v@@tk;C|UFiB|BCBB-F0H*RbZKz}lK#F03hxhO6 zPL23sr$?b`lG|^v)ip$MCapS#xU`AFlN795B;iQhJwKg6u|=J%CXeDK!W?Zo2che! z=L;J?l+)q9&@KA6R$i5bR&BA`l>M!G6e&;u$ieqMgYQ}gO#Ua?+rg!1`u?ppr5(g3 zeMeYk5y_+Fa*%=-EscN>dy|Tz)Ov4F^j4c?s!uFYe#~~$bUQh1LwJ$x%UrnK>R4g9 zB;t^|lJfhf<&U7|y0LO^Vz|G%v>qePD_{tn{{V?sE!(lpQ}Q(?8gS|IslR{yefpbi z%!_v$+**{3Pb;#NKowPwaHFhQ@4K&OM{Y!S!L zy;#|8cXABgAmDIMdSS{fA%X5yYdLNrE~_tvgU{vX*i?VBM6l*%3%7z_x%S02LlwQG zEg+T3vi?>%00HSqn$D<`Y9Xyg;=EMumoQJ^gDJ z>WC*d60tyt4syI_6{KJ4vQ2rkxbRmynY;XvN_|8kdnYiKVDz6@#5v9f83W#!yP3<* zjLd)b)MEmqj^$&Oqqis+lb%LY(64DHP#b~zmlE0=WDRp~yyMCN!Tw#iueWPuG+@OF zMx+2sd6@o{1TfphbsEnhXULJFQ<8b@_xP^bmr>f-B1G{iJIe^iByrsQ)npdvMV8iE zp%yj$EulUvOu!OA0WpE?NLP2W+e-1waHk-hzZIv;sSC>^D?~$bOFM4o&|}{ezb8w} ztfNmX0vN#6X@gL9BUv?Xju@iL7VQdwVrEH-qfJgJqG1&E_w(*kySl2tu zl0Hs-#(Ai3KMiiy2@EHA9%6%oP}uZk%r|4ki^K$E?l}N^W{9}r*f}(&yD};qK!jq} zZ?((c63$EOiP&uzBmh0R^rw!R=-p=i+(mMQka>zS`9^;AW2Jg#+DOE$YGMnL8A(!p z$I$)jcIl?IwX$1T&>1#uUCXrozW)GvOKriA8pec~w$u3&GI%;CSJSO07I(K+#10fl z2tJ$wK6_Mh#c^+Q0M+G@N@Fv}9vK1bcKYKV*0=l1I}5EX=kNrCCU(Z8l|LVEip{m# zZ5}zqvB~mdW#nM?!*lb+Sz4HG9nSvZh5nN@^F8IX_Sf*ki3EX2@mO|N8ROvbSM>cB z&Q6|9L}|A+mvSIO1_y?Yr#Mh^-@mm5y|`UFRBNjsM>r~^s;~zc~UDc z5IB=L86zBnmh|-Ys`omi-BZ$9^_Ns>D7w|UiLI`z;9bl}{FoirAm{nlOa89Y*Gba) zD^Q%tWng#OY7j4j;D9izf;sPu(A`I^FKsODA<%+JEcWK!Yr?Cz1Hl6vcF4|sX@V$W zuseyBF8L-_H7O$wB)5#Wt~{h4gF}v^Zye9{7V0++SY(gTQNoQAnGKT58sL!2o;!0u zFJgw|vM5y~{zmRN^#1@#YMT3v_Ge4T!)XHb2oX8i-vsmi`_(Ae1P%)#?#2P&ew7@e z;@;QkreYVcgSaMSdIG+OkhP zVp+~S@+d#Z9@Vz!ojn{TFtLYzI3thNv0hjBike%E1Has9Qm`M9nQu(~5vkfQoXmT% zbG1k5>sqdd_-|(gviNqYBVIU60Z*Dvfe>|RVFTD_ns~9&fq)I5ApRd}$lsrlmQN;~ zdqVn|^_NGBWk>K=9>W|_*mMsdL{$KGAahSJX(+02qXMiggi8>7j1opYs2}AYdz3ZX zh^?Xk#rF5*kEt~s){MK+mNUuQll{#*NoyM^3IHSYsNTRy5{Zr%Yi(k4&&TUgY+hQHlSD1_;-drtF-7exnkcg(fZoT_yU!6=_bTJwtFIf1f@ckpe*VzK zFNcnM_o{6Y#*TL2uOf|2ZcK(p1ckuk(xZ40qHKZYQ|VFo*s&r=JX<#MIDR&1`!9Uuq zM=?obnj_!S;+t5UhUb;x2ZR~89|Jz07186u?*r~C#B#?pW zL9-!t+6T>7c+Vs$Y4VS9nx+<&EBtFyUF9;A#^r?5ZLs@%p39OFHzSN!axWFKQ)odJ&rzoshH{AElx z1QCf0Z;TOLd5QcNK342%XMmZTcYKUj&kMwJ9EX)0d>Sk;lo2I_jouWTsTit;Ic=^= zs3ZpCbhVM#0D0svB8km5RA&!T$iPif~Bu$9gLzrlWA)G_exIWXU68Mn3)Ojpmj05kwYQ z#lv8^k$_bn_JPkH=BTYl*^JN;1}fV$i@A(NPo3FIWRuQ5!lVgmU@aZQMdByO!Ia9r zhtyH+JEIoiCX#E^h8TY{6Ou-K2dSYtj+E9%>SK({0dk61U^WkO0jtsLEv?HA&)lqr zUFHBb@HZ+p?4J1_G)^5}YcL?ZNhX90A^fbL>r@gcrqmS23VDC_qLY9zlZNN|)w?Z1 z(krAl(7na5{K~^0$oy5V6pib0Jhk^5bWLV<(xsBkKWHpvT1e#KqZ#Mdoc{ooHfWto z744hCVp&6f3uPFuW6!;3H*o1sdll}E^2SFS04cZF1Mf$)X@s{i-1$6M&z~bZ$EYLU z?dwZz$5tGG)Pa4E$}(Pb{4z#w>|tg$_%0E!$q7 zsW!KDtojH zwFgX#Xkuw$PYOe{Fgf7xGxpE*rRcOXY1B7bRF>dJDwuY!VllzUtzGOK#9@|D>ie2E zKldDfeW*^erft+I~!?|*9$XXw>$tb zyZoxQt)@nn7fN zX18wy1yxbE^Plm2U{ejnrODG0Ia9?|VmB4@BInFO9P``%0IFElWxj_|j^(2$R}&+Z z#?TM9tshOC$nG6pn8Erj%tA>LSqsIx0H05KF56~gXyJ)Q(yE2V0rx-Y^Fu83E7@+I zNmK}n2?NA<+Ij8oj8i71Wo=_-Z;VL`l`j(S4URvk1K-w(EDQBLdo5~O1hVQlG)}jJ z>ZOhCq8nH$lC6=+`2PUvwov*+mJP3HQ(0*HqHthy^k)F9~X zCeWyzxv(q%To@=Xn zeHPFH?4$uJ_X-H*4u3GT3&S~reoAPcTbYW^3*gET27^; zm3b`z>_Ns%PgmP-Bc+FU>=mlA_734wryWgo2(_M-l1rOJYnuz5KI1JYBZn%CGoAr; z=7mG`mJ+3{({&71`n+aIuVa{8crpQuV+CZ!GnK=ST9>D0i$#{pUV}l@A-j%4YjJOD zHe!G=<&+l0EuQhW2hyuwTWPH>v7^bUYW9|~+%BMQbAMWnD_+N=4qq22| zVbi+iu(_5v?b%3ca(P@I`iqXu!wgr3$ecPx>MT#E7!|JO=`Ak#RfIZ-hJOWP;{f3K zpnUp+u;#eUr+q%9)0Z79uG&Ew$8ig)F>X1;il+{~o+9&BZ!ATQs{%*S8jZE4r2{3) zS7PrHdB96I~cVcZuSiatSzmzJwUDHwX8_7+fTO{P^XyX&vC|Sl3jk%;_ln( zwEY};jh?7)NQ@bAg-2dWu|1ga^Hu~W`$`R~QRr;SmL;zQ_E0ZR-iyRH8cdepCy3#E z`xt@)XOf5Bxk2^q8sgVcy1BRLxT3zXl_!QfNkf?-BO93k8TG`A$j3Fx@nF3XI5C?4 z0Pz9;0MGl+P6=M-^TIO3x6YWjlp!&c2R<7N;U5j_LOO@1?D~&Mdks$Cc8zMgqEODW zq>INn?zlP6r6}~*;-}%qSM@ZVEz^4Cl$y1~QC(g?hRB!W7-WdC1h~)T9lt|P3w;!p z(CU-v_pw{RM0Qr56a7R?2|~_*`H=D6nVmS%pFOGGhYr0FFs{7Ox|^h$$5NZ9E+y(4 zwre|iaIBU#C&`}_jtR)~4o5YT{vq{T9Y53ZbXJpc`ksLm*NpctMiH)OK2|D5cPKo7 zeZJM|kHigkrgSch)h#-wQ=Z%E(-(~sl0uQRn_}Yx_9X|+c-ySHDoq1jmg_{;Bh{?0 zV;4Gh#xVHte~qI&tbw>Ajku-P>xwE2j0`O6que!p0t=oV4}>!x39u zj9_i`j!gb_Jtm4L}7+upPGQq{EkP9Kw}GJ;Q9 z_9p%KFV+{`N2Oj}^-i|edQ|smWov775(qD5E1iH5xn;-DF3 z+pe#PjF3ZQLn`9|cAQt3Ei5!uytuQ_W7ThM;ejml1x~ETCrfE=?Jsn@iiynNScD` zI+fmss@(Kun-%5Vv5A}odnwQ_h_0s@is4G1DD~r!+8K4Ny@`MD{#CdtP@V7Va)jw~ zI;9dyDO3RxA%fic{)03}PU*R>*xc&34rY)RSk&iY zkDv0QcX5ja-i?qINI%1#P7PDD)Y|D<6?nrIEUS~px8Lnl_19^JM_7s6>YDA;nv&XEBelYhHr4IhIW=zE4Q?(aon?|@ zLnMii2*+=8O;v`sIq@BBp^L3S?rloKNk+>v{{WZTguSqq&18|!grg&ZHy>l~M66w| zQR9v@UB?I;lE3}c+p7qpf-k6dET=3%+6c#}_O3m@ODN^cc7dmr z&z@!j0REIRDBQ?eP?AU+aV_alLji&Y4nWBK+j31@jTK&DvC8Yc=5MEqBl3=N*dMPy6vnaG z$0>|NHUM%#&Q35tOi=dOuB8u9-k`lpQkE$EOJ{6&fl8ioJ;%rOrcDm&!u|-NxK%Dy zl#&OO<16}7hNmK1=u8V25*%(MU~`dy=shdFs=QiKv0xnGmn3oR_BhXa=f)X#Ao!rH z)O3k0h*;J}RBUhul}~Jj>l$C;)V}T&f zJC9Lcbgr(M^(V8xcJU&7tfk1o&IdmK0Mivg#qV$UQcrA{=`_;)=^$4dIiS9?NTG;;lz|M?0DK12dj>GN1J&$Tp zyGbmWWwnspB#Ib}kWq(xA5rt``cYj%=1a(YYu(0GJ{XakBmvKF)`L1Sv&9MVBXD=Z z81eG0{*+}~^kJ;LM5%kNMRy8BAB+3n&grdk{TK=;K_yRx^K zunV!l9OuoB*yGl%LG>070_SN9g<<)M^WKX90n{Ccg7qky>!e#*)+NUQ_y^*b@0wIk z23XMGmKeeQw9~4|r|kw*J}Djc@Ob|8wQ!3Ol=E?J>PnK>DfjoQS9+C$s3!Bp{{X3i z2<}{ipK6R+_|73{mvWy|f_^eP)VM~oVugz1${D%M6Vq&^xV4r=Rv}k1U;qI3t~H!Q z=^K<6PcfkI!2l01e&E$v;gvychiErF$mfa>_-j>W2o+ld56tv?RS+8wD&j)Kmd|nRLXEICd4PGC4b0q+vi#G0b{uAZ zG-xvuFT{#pHMTqh7TPIKHSPDd7 zdsYYdgUy!RY3ee@#}$pAaE^zf?Fo=c^sO63(oiVe0-v{P9iwT(YUM`m)c2=al|==3 z92)uX4Rh?vY_n4BrHU%VxCd@9#eb*TjzbRI0fAKD8zumatB-0i3~3=z%8}Un)4Y1i zp2u)EY4^Y+41T7&HMz#o+rR5p|_}yxuWR^EWnO^s&5T^J*=Rgn!3Llx+YZC_ZR+`0OV)Vt4(dYBP4N5ZEmGV#tEVF z!WLfq5y|$TZ@}XuEZkSSfr!RJf-~E_R%i)zUc=wL7`cUr18C!tY6gU@+?d;ia5+8r zq>WJz>RcL7iq)E7zsk7&bU`2{KnTtUrCN>?!IR5v^(JJNQqqQg40PYSv3+dNj$ zf2VFyxkgW8O4^o-ABOU8J|=q)T2R%sC-H{YZs(f1$MD`6<2N?Z>?|^@oz(juddcqe ztNj}M!Fw4fcv%N*{{X*A_8r!Z;*y~c9sQ{Ts`@_O@(EZ#26N@cYenOH+o$1YViX&G zr=5~^x0u9FmQQoqtjjAj2;_ppf_>`8RP^oMkt@g%nk7B|0K@+PiU|ecn8Za}p5J=b zryGRL1ox?oW-_CYq87Pe9a}!U)CJT=U7MW$05L+^X&nCYLyGMZyz&U+ z7$@GY6!9I(g}j?eJ;HYQp5ho zqXxnlELCk34-tU{2O#yRz0M`WHeda|hid(vJ` z?KB9Z>Q{qImR6XvI27nT{#{xPc8rl08qQg z^+|3P7!AyX`Ea0|)#j70$m$k}zN5s}ahQy;Bzptz-lUFugCasL1`44r$II%imcZ=;U<$GCu^WjPEhLeuo$sFYjBB0MTsthvD$9$!k# z?z(xQGF{l*CCVNoTzRqIcOT{2pZXhC{{WMU((K|ue3A}#0sdl^<&Z}q0Lfyj&1Q|I z6m2D~r7J6^>yh{M71rtrB+^{Ew~22cl~|7H*!}CRk?`f<0;P!zqZm`%Rh79ZD2h#_ zFe=OZBmLr)3x147Eg`lgNMT!Yk%9{CDyQEJf5_1NMiBPXz{`Te%GvkrUmoqnvayju z!r%qSG!Ocsr8t(OSuKX z#k^~55}FUe%8?1ORQAgwAXbv<6|?9vNMak4hsm}Fd$o=69heMzY2H)PKD7g8i; zxgqo7H#o}o$Hh&p`F`{vnAjyW`tC^urIp7QQ!ts>b1Z=5dhk0{=Y|WOn$$Wk$ARp% z7L0|SQl>XX^0JZlBL|P@X?j>Ri6LicA3TuQ*mK55ZhxhH((N?a?yx5+N%Ba*%YPtqv;NrUZ{%fYMLt*TYK9k+#)3Qkau5dFVTOCI$fTTWubK} zGEY2YO$Gh4v_>Zf%CZ5C-+tpYt#pNrp0ul>>N*qZHVcWQdkOYGe3H@U_p93@xaO0; z5&r-OG&|0eI`2biI*yxvE%$}{Dp-q&K_mki?!Ww6v{f*44zoLOG`|rWgf>^&*}J@c zsI;G0k0$Ebmf&!sjE^kQpKr{#qI!;@qLES6IyB#K2m$sT!E`4znA{ZMs?Q&(MMNxHX|-C?}8zKdZl zPm}6ZPmrF%RUX-{gD?4c0Dn-ehQxyA>Px*dQMJ?@3oCU)YHe<@k+;OiiI07!%Go%t zw~41FgKyNA9Xj@1NoR5*x{Az|N6!pcsU8!0gV_9oLG>+a?@)WYKBDN@x z@T%~lLNFzajyDd~de-*B(g<(W`iDuoyog%8v#VXk=t09rkVMfA#R=TLl^{oF^N@fTZmCnQL$r)kgr;(OGoufusXTD`Ab+sSJhn|p=S zEWvqHkQB%`SyX?Ce86*2bp6H5P{S6T*D$~A$qPvZ%6NpwjJJeN3&)P}o>qxnX|klo zYZmFN{XbN19>&pI!;DRiS|>RXzpm54}_Ni^+KsLxT_Lm7KG)I5vyfF31`{%xM>PDXuely6JwdmU3!`t#Mv zC8nba+fSzIXt|DHFs#ISAMvQiy>hr0eTj2j$MJA?{lEQ5e-ghBV$du)d#O4vMbj=i zN2KL5-RaG`+V*+T!DsP;mMx5WfsE5HLVhh@^)FCcXq{`ON7CJIsN2bNp!nm-Ewq^` ztO5Mv1Ipd|irS{QyN=#Vx$V@c1!J{rDVIEKecTM3bMsyz{C4Rczw3X+U1zL1ccitO z2hyR2JG7Ab;==G_$ME113jO$|1aa(4B_rkN{Y@75{wCdZM^tpjRCIl&rC}UV-X@zI zfuu5%k#%Lex`t3$2freoaL|%)7~`JZuzO~_ z<@gP+>fefeK=$2x)taPM{V8g0?6ps*NWPWB0lH^wGp;xpGUFQvAO`1w z$)$Oen#UxX@8RztGVB#xKqFe2{g2{qtJA$>chp@r&|1fSxEfrUXarlawnfjGKp&WT zllHA^ruv%WsXAinO#`Pi$zjsv5~h}p1?8OB-eid54;Js?=hy9CbVSq|{iXT=_19ZN zTMsMSpz?-NPd>bR4AhpFb7`8q8m*n>&5fppf1xQeLL8)V06E%|BGT)nod1pH3?!rP2^zd~VD@j**|)bgW;r!=w*ZKD?l4MopA!v&bDCcK3e|qAr`qpWzPW8jT)CFw z-pW~3p_NsEGh3(dV3VHPnJDBvlZ6*GzREFZv$>H2ja90z!I9Q}UhmbS;>HR2{ zFE8Br50lHk7bD^a`cL=K)Wq+Xt~zsE(`+8^N4LJZN78i2Rx*Ot05I1KINDA<`K)8C zI^Dk!*k_=_FGgB zr6C+EwoXuxaKqBPv)5fUt90hN_R_tz>{-5$B9Us=0JvAgzYC5*Fd!|SG>x+AP*&=jezE*{YX6HK(9f9JvUY4}! z-m%g(8FXH()Fi&t7+gm40?@D|5ggIuWO9O}Zd?3mOcH>aB(d4_;^#+Na1d2g#1&}+uR$em1k`&`SA9|}2_9ugS zj6aFIVkLhy9Y5>$8KqHgr%x<#mza=Pdnm5<@_`zv?g*Z_;QZHX$*mq1=j7z%VrQ48pLJ&$&@tf*zGM| zSXl0SXMb^ufE`0!zmTMo5T|h)k2v)sumX$E((@(GBDgOK{&$c8iaVp}mhr+oER2oL zas4V{@CM};-C8d-?8T+&$;!tt+*D+p!@t;l>ZRU@kz9DwNFTAIyAaFme zQjbTx)Khy~sD&~{@5)I30Dsc7iL`~5@+jmOA+i%4^ZkW%>Q4hsvSp8Gm6r-f8wdEY zRU1#xgf3RdRrY2#)bmMa47N~8%WyE5z#tC%{MKGB^jET%N?cU+I-j^xc8}KfX8UYE#(U-2RPg@ z&lTRn)G)DoHE0{ zVHwXL02mLSU(%^vNKiEK_+_PSpo5mqGsydYYK|Fh;l6fxB;Ob=3Y=#g;Qs(R=BXsH z2;yWgmIh>EGlPx?_pcS%l>Nxxj!ad5XH3)jj&0dNOD9=-iODoZo}Y1gnf=9=ZONPUaZp zy@nYpvpw0C*^Nf!{yMtzD(mcb`)lq=^6khHL}ye*V-lIW45Q@k|RA zUxi{$2l`d3>T#!6h$vN8X(Qdrsm|YzyH1mM5?q)aucQqRTBe_#K)`aaNTp5PV#5XE4iiS&{1)g}5dhOcT9;9P6%a>)5 zfnpdA-k|oXvdqYj0F_@L5)@+ueAf{-00SlOx|6?=KolMZD_!ZW6--gF+mdmQ^Q1msJL5vTlchFy8M=2#Afdqrjy)?^ z(R9GhrGOrziUrg9L65@+48Da&J?l%-teI4!C}s3-iutYfo2(?l9knlMmLUiPaZL8` zG)hXNXB?jSubOSFMkP|9=Zt|zVz(Qx20b&HHx~$z$UvUX`;@KM#E2JBk>%rq#S*t8 zA$tt*&2{>GN(^J1XB8-1#vMQh+*1mwDehLx43lF;ah&-`&NEk|IZP9uY}H6zWQh2q z3_$?>g-r{L0o(6Pt3an?(UlXqZa?~fj^NbcGvAtm6N&j9>iVt@2<_gQVvb9rD1MBp z@TpVpR3wE!Za4yp$N?ndBB@G0cE|bDZ>dO;3}BgU(euY0=wFAnUG2zj=M;U^tU-9j zC}sg95rVwpv-$Yo5&MMJXGB~bp-2Sw_Nz*SA@JA&2Lz0a)HotgcJAi`2iB~*?F*cW zqNP2PEY$lM3YpJ1?~3ej7d^36XUBcc20ZMhR#2Uoe93>mjh_yB%TFT zmNU1tSjhl!o_%YnBL{b_S?o?~1-ZA#;2-5d?yN+p%2$t?Xff{h{VJ69&4cV{3n<*N zTTu%8Olx*+(c|0-RMe~l&@u!$?ZB-*?$M-eq+*w~EiE<)LJ+Ck1JCJ8?8jhszM*y7 zFn*-zX(fh2P&i<6glCHL*IIPd&V_Q*MH35R$0Pg){VUmegi=U`+2SX6XCo)|ti!6h zY7Iu-cv*M04nq$A0P9bDN0RQ{#W_jbUjEcEY|Y$JD&~`!x{cF z?oYKnX~xlR8KXsgpd@|~?0xA^PqXmVcb0Ypi~+#oy*+5!1+r+beQ@sxZ~;&VAf5*v zov8*x58U6XfIE}R5^5^GJCLcs7$AP5)`{5YmP1cynS^EghF}Q&E2X`htr|rbNY^;r z-fVmdm1dbP{{VAp_b8*!BZ3#_??ZAvftM(SEqZH6WEWPpkxdvFX3lVG9Y)eSd-$b> z9ou*c2*>GGbos7zOH@rcd=_Fo zK50`>)U8G8JQ-Q@v>Pq04pZt56S8$CYIM}2Ff-@`iXaNoj>>x^(#k6CK=rQhjH3pqI`%wjF}3@~bw>u`wU zlG=ELZg)mdf$&9KiZ!~nU-@Bi5Wp?Fx%L^aS^HrDuyx!yWqSgyB)2d-d6|^rHv6xk z�z-KGG;|eyt)t3$Er!j|bOs{P9bAO^gt$Mw^a*HN3p2_u&5kl{V>C&0!k-D+3>P zw_~|~L+MH~oCvEWz)~X(rm6d&f>iO4;Ahv=H`<9yBQhI_T_a?D`8~eWn|FB?l!+>- z@WK3@kAGimRh!PCNh}E87*mXgT<87!(t8i&H4rmtx{y8OEj7u8K)x$6^A6m9;8byS z6i*maAT75i2jFItH6Eb1v6kXVAH*B{fkyy#?Mw3YG=}-4K_1q@QJ%x!6?#z2n~}Bl zdYc`k=*|b5vB32CGwizD|m^u)1V>lZwSCe?YrfVWgm0)eS?BA$H{lNY9|5NgL-49b$+VW zSiuO6&M*41&G}=`p}_Mw>LeQYo zG;koafd_%zKhgCp43->M}$YQ7nrf<$M$$)7qzzlk=bL^%-GTT7GBTzjGdu z9Ipk&(4nx)`7ztn{}=j&Kib)s$3#c6MWwxi!&+uQmHgts_T=aT&tCHXtXs$NAM^e+0KU zFvk$U8-s1z^V+CEYaQf{ZQzr_1mT;$D8;6b^V=0$dv$yaIb5=zoY8-RjTy#q^%y!^ zU7JVhdp%atMv%aFDld?+!S(shKU&fBj=h5KTfNkmuI;0JN*&5Bt%AjD>BifL*OepE zQNi`BNvyS9F6YDW+i5xSa;G)%ueD7BsV()r8^eX=$&fOFrN4J4TJWp+L4YTt@oHD&mxqCt4KT083cSle}Z9NQgJ8QryVC6Cu|03Wa^){2#n!UZ8Ju7Jk)T1r#oxNd>X9tNb+q`Z@ ze7V6ib6(PVds5P_^bK;)S<~z+Boaj)!{NBcs9;P|W7K(Aiey+naV?mSN8m<`TIpWB z=}VZbgIwQO>(&G((pb4LT?fE#41WuZ=WpdWrx@DeIJHil(>ki$8<+Z+?QdW(CgO5D zEa1a1$8N^455y0{k0l`IMhi$oH-Z#k)lFnk15H7uIlJO+QWQ7L20a=4+s1X(Svf z&ZGXEgODX0A6kxGHfw!0XtfTFwYt>o!EqJ5frHzT!?a@?fFJvb&m7g>qUiRAUAWWb z>5F(;NX+_tx_sGbk8%(k2~$77e9N9Fe3w@C14hXaI#u?+Azo=8v*cD72*86U!Y!xhza{{X4dVvnaf z(sYwXa?we10S_!+#Icsf;g0b)w+5-%&8Lxjq3PXeacIpa)WUBe*$I5-4Ui4I*~ri3 zG*;VKy_$P%S}k8fmI(p3yGytg3(5Q|aD#!KK$Untwcup*0ojtvd93Oh+DmD5(>IHA z2$IG%PYB5{?(vo%yOaD;9u0D*kEgnV;>zZ0u9?xb8^{TGp^kCl!4WxJo;*ayW?wMH za;5=;u^Z6T(0>v7pQL)Kc?I0_8Ke}DK7ag1*X83CA`D{d2}tGwrR=g zU|of2#7v9v6aE|eSE{<6J$FjCeKt6wd38%o9|4&{9am4g zl)N*?j2(dFBVh8~kFIOcodc+KjF9;t0bmhjvRV5;ndu-`>3?4u`C3y;l7*sB}Go=@yKR zT4qBfnRefpk7tK)IbWQ7QGU7TsP#UPj>o6fG`$kaNiJlww1aZ$G7-3JR6DX5A1U|s zz@ZxhkuD~Pe;1lU<2mg8@6i7MX^2={TWJXm{4;9$cC9tSn+0zWCZDH{OM#3r!#5p{ zD{$#g#BQC}q`0#ZS|m})^!CE=q-(0SFj<2D74iWmY* zw6Pe5n`EPSR&4(7g(Qyn6`6H!Qpu>vr)kl=OCFsU&}r!s6A@wFNfh?nNIQ?P_NXpN z#xmFN$>zY*YyZbLdkhyV5@Y}Tu24PGJ%j5KGQ?NQ=d4_to6_5T2QmP7bDVvgfgnhC8sdM_5`XSq<%lwdH){1Y+2!9J#) z^i5M=wCTjxH6Ewa>`zoH37S}dlHLfEfa`<73*}Y!BiA*$N20+UnnOL$)>^U!nn{9x z`oXYNEWCbUg~9%Hj{YQcm7as36QbFqkS*HX>ky{XG%%6~g*O5MXLlpH#%eZVd?T93 z<9`vKCc_^80DJ4#ulI|3cB(IWZ|e6bAq;TFF}Oz=*t@V!2>^Zbng^%J^up+QSnn^e zwo2!b{pyaD)X{4FeX7NA8bJ54_>o#FfVSwLkp=)5+uQA$DDkQ-#Cw10FDwQ~z(3IY z{i`*ap#D=p)O-w4hPT|i6z5P7K&-pAZDk+B>VIE~Ck>=FamNQ@`7OCg`*Zr@m6qXb z-YFNtPB-K!JZJhEKYe#>&QYAytx0AzSvpxtJ=N_l}cdI&8o9a%6?o~%1XP(2?A2lVj zL%A2A73AKdNWEM2Wrkd=WCEx1maCT1T#Mv|QKBUQ86=PNu8`T-*hDdi(J)w?9o0d) zoo2a`C`n|C5$ARbl6b~B`_w*0V*x5(VFys{%(ijE8bB1t+_NtNi0QU*nGDW^J`PTJ zUMXp8?(b)eBW+T0$IuT^O%UBhWgKzj2-SHWhxMt8Krl>&;-OIYI^A2Pv&*PWBJM@< zE^+?NA?oF|3)YrN6}K;(=Z-(hqUsK<7utleEVzO0nl#H}HKQ}5WxUzX9B8?@ubQ3o1q+lo??9;nw z>v=3o;f7F7;=|k5HA?$Jp5^9|2`l044n{Wf$RDLzGE~bxbvy0J8lXn|KA`R#j zmA^Ru0Ds<*o@t=CXw(cJGT>(!^sNu7u2s?-L|$XVvkc=s!1)!QO$^U@B!_!GOO?kT z@8XH0Ogo(i@!YdxGsf1_oW#VH-p3fo!N>EW&2X0;KMklU^$8}{QN}_3FXf6AYi)6K zEx1_%xd%DEOc{$4<#5y2%dYlGLk^ zSIpTynD+kwI<+d5n?|(&q+e5_oD%GWC_*`A$0zh6hg!KnZQ+Tp6F6gV;B4Gw+HR))v=2LXca>Br-Ncxx%Sn4oC;LIQ#QgsP+u2oT+_ld1Y_n zqB~`IP&=vQeaEq?kxV>T*egthG6vk>`{4foYQ3r5T|sU1bEeRW$(8%y^ZryC;^Ip$ zrjj`ylb2#S2R@$|8U1R|y-JJ8ZtfZlK|yoAFbbS^Mjn(l`Q>}F6a{2`rN}}s%j$8O zx3AA>ZnoYOyMsHD`Q67DJoD;*l>xk6nw-HIWR2HxY;Z?>)Yq{f4DBYO76+0k21vkG z8;Ka~PsK;H91sJNo4ltuKGo9YAXZ0)JVM6=XD2^;DWO`ybR@NwUj%Z)c<19a3kXHr z=sW611)P(^x-#9tKXb)Ov&n68TP0lv52bx}kSatR2TX;>A7h%R(ixeL<<4`TLsWL& zd3hvu0@~EHb@;H9nbYZf?UB<(oab)inmCG&($@{a|V?MM_Rl=Ig z&VX%w#=e`=GEi+Cd{(*Bnp+U1V>tw5fxxBSoYLVCC}k#N#t#4wdewS*$ixIfFhC%Y z@$1ce&&y?-Sg0|Yjsi6F)|D`f0T?;;H2b93J0XlH13#LDXwdQz6t2gim|ZgAm2-ZRDyYqmco)PP+H3n)AhLuQRucHo|S8YuY; z0QK!dCzKnkV~o%lfDkt=sziX~FgW{^eY*i)5saB-UdN0IsVf&f@=50vW#l&SDu6~u2k%4iA`1_TlSUVi@o zYWNvOMt?$Us<2{n+;+uDYz@?owJOU9bteOk)H3qX3Z2A*gMmk1X;OB8bI76hD6ZZ1 zkD9903N8OL*4=BWWBfHx_my-wH8#X({R0+ZMZ zzJy^*^*r)2b?meq@{5j<~pM}p-Ihg#{koPjRjFuqhzZELP+qQw1JbkMA z+jv`49Ljw=;D4P?AynHPx(OY-k=%Tbdf6Ldp;R2U=Q|a0NXa9&`}wIn01)_Xo_4nH zPxtRvj7t}iCB%cwcJLT`u79Yh?Cpi!;z8jFQHUuj9tj7r`1{lv%?-jR$N3x}`-l2# zOxbT50D;NhD|-)0ZnQXdwT3m4PDW4VU)HK=b^&5{OzbRjPXvl?va^M3!ib8*qagtA zSv=g1PD!6p!liMl3O=NIb&OWf$NS$E$>s6=0Q=K2++ANZP)wmw2w2pOqjB~F=7hsI zh^*>3Q{`0yx4jj#n%rJTB#O+#&b;z5@9jY=7d^uf! z*#&5UP!M8tdogcXz3?n>;Z$>(2P64bU3YZ@Ua*!&pCI95ViiVzwP}4zZyVdlps5|e zC%!vYRjS(RV&)|ls_3MW5aV~RC)%P_OlOO*C0pBzSm0#?Y7xLzCkBLg&@@jRE+YXIa8X*blD+$)goBRXNL5}JLrB0 z-Ejo!z;U-d{kWwWsHA#}vguO3q5ip$!>1dlCn}pk3^_j_{*;BNby>C2_A4E%0+5H1 z=xL9s@eYEKwCyJah+~im9fAF80qR|IWbX@1%At-&d{DkO3;BlE>SOZT;wNzCrPQ82 z%*@-FixIoH_Wsob8sU4m_Q`|;2Lt+6b#bfBHX^sTjySyu8{}{Q01@r_Vv6Z4GtUx< z3l{D>f%mObc*LzD%I|9%LTff%LVT`H(cOtWC=|JSeKxhMKBcI$_+jxHXR`Vz#Sf6j zYZEKn0Kq}ZFJriZ2kBA8zIH@~{Fw{@B<(-zORB|6iD4Yn0u8h`XJLQTy06p51aL%g zE1Y2$J%K!DS>Pvj=Y! zso;7a^rHHHlITj*275XYj*Ks;|zyY0n1YWhy1vojmGh5$G)`s1I2L*=oRVoR$q zrs6*AKvisml09kd1PI=}Y6H_|wkpgt*|5VlV3C4TSq*pfD8a3KmP#H=8V~-cFYCz1`Ym%5ua?-t_!G1Q>kusisZz^vN7N{ z7(eXdhH5%YdX}9gn{b5-jK+Nfk7MkA&W*l{3c%MkZ{{48)^)jOngv1ayv!vL)nGCh(z;bd++jv!C6_qIj-X8B#qNSau?;I}u_Y1TN>I&}!O^v_&<|B75yL zv^TGCfsC-@v*3|DUb+0jqqWj*FYZ2yZk^FG@c5c+aL%sG{GHbBM%PUDjgCMxo72CD z8aG*M4`rtGb)XkW47xkq2wTM+-r4bxNd6PSG}7var6#$*=_|OTu(>}>A#IF@INNa= zAKkV;_W-VFLW>dxrK_Djdtaoum!x%@9a42$c_Xozl@N~Y3xoTn&v=`Io-36!m$ON( z-dNvjn)QUbjhHeUxO_;VzylJf7x-UpsJ>Hw7 zYDsylUNqMm!%ZYDA;|Ik$A!k#e?gDEGTXrwj1Ol8?a3)4NhGtdc7a&#+qm~k{M5|1 zFsW;KS;sQ^!55+9tcx`jYrJG2BRFM;Y>{VUUt?Lcbk= zK9zf^_4%#!?LVe&I#KlvFH~70RHw8!^Pco^>H!FrbH=(Rgr8KX_E}Q&M(|TlTb7?w`p*m?tOqNp+nlMfT ziZ}z4hVD;n*RM4#BT3V>sP61~rg)*%;P9<<`~G5)z{rkeBX9s?Yh)E8x#Ee>_)%-r z{U2=);v>haYUg0K)MJ3#-C6qWE`*bUFt78UT+rhjvus8gK0zw0zxMYSG)qk)+fJ9J z^d6+1>Ps0+H@8CZX1TIp18j0~cI0wCXw}JSF9pm~G^w<#RzRprk}$$Z&-jNV*O{lV z>Hh%1FZhJAx6^uysC3OfNR7t1b$1z_+U((-Asl(-Y!SGg?eANUNPZ!7{{UU+GV1*? zZ!2mx$W~1X<778BJdjue$lMPH@}4NgUleH46>u025D0)9<;hgEBxR(&6+ zr~EjbwTSMX2<&84Fy6%BfhY9wJHn$X!x<_Rg8%d2o?~ES&j(#a?OZ+#z z>02i2eNq#rUs}kK=-OQBk{6VbmKiwOax!z-JOLY8InW)~_Q% z3Y_9QXo+r1d3>Y$8XF$Bqw+rEZ#A2Z5UUhlJ;!RA-0$- zGqhj_5RBzmu77rYn;x_#U;4!qILOJ!+CcRO*ZnB!!P1sm44Q1(wx;(M_kUS`J)_8$ z`k5S&8~*_9N}!J@Ao)l+&T32TKkD>2x{BLWxzzNzO%Vqek&~NHx|*AwT@P2e=#{d{iqea%xQnK!9eJD0>pyc<27=7h)v8=vb2mm#nS~> zKA$xln7q`I1W*Rxq>ku4>M3bYbJUQFqaJjN})+h?~G;3YItn2h{fe0P3u-{AcUb zqYoKvxRdHun)VjDV+mGl{$=bBz@j!YgjbPwHZZwwT=%708@c91TX)GM#uac&f8w2V z^|yvJ5456!UvD9s)`_yt9ZemK6l!Q)I4s41Y1Lfp$^%eezGf)ED*pfqj?^aB`UoJ4 z>Fxsu0KR{RK>>+Ru&v{VQm_)FWdoA4~_3sdgjOW3^pvC z(T&!^!$eN{39*i7w~%C0xkfTSl@`<3jc!(99AJ`mpHrNiduN~LK`aqrb_&}D2;4id z71vVMitA5vB&s(i+z&!A{dlI;U$)c|)FwDtU)Wu0lG&g_2|iEDj!z%`(GS_HZz}yl zq_BbzmW&gsayM_n1ALmU~ zfC4RaAjmZxG6JO`vUXX#-YF`J6K8_M-=6;f6s4+Y<4nD@mfA#^g$T?^CC?nwCC;ld z*s?oEA}1qx!1Ms)>`&g7H9clKo7CDGSi+aupzx#I`c-_Dw>+eX8>sSK{74_gJ%RZd z%_V9q=0&!742YRjBm5*}{<#!?UA|)R2@9xI-NDB0-RUn=xG$)9sI01RHv`z3xg;Fx zx!BDe#46570T~YO;Xfa(ShmvSys>!%E~^TH&ZoHd9`qfzqb9{{Fvo0@MeXmdVYGWs z71B8r0HhI$<)DH1&npkP3A70*L*i^4u6WH55XSKd6p+MuvVCjqu|~1l(vnbfk&&G6 zKb3UdD##EKw;PQP%uhx^-@c?WPF=xagYG!Zd;~CJpmW>ax=-XJft>#UN~bO4&@gz& z4YYuLs!E)_N*c|3m9HHf73_PHp7aAzmA0$_vUAvaRol7AVh(fMnxSbKy1X(G#(1W* zrv>C}OaEIf(F*jB&Ons4sc$(&=8S#LR? zphV_1Tt?$hPH9DyNFpta1BE8EeHIpJOUN*A6-IGEG)qa+BxtgMc^EjST^`NMie*e3 zWPm&KSR(%bA>6jZ8gyG+uv}-{)3v3jSaMf^?LhQvWC3``9f|EsiUP;UBz#tj#^Z%f zO%`0+I-S)5^1Z4>VYu^AL`yz6&#|tPl?}imjxEG;60L8k%Z1FFfb<5SSVXK`gUH6- z)n+#Zw!SbwrAWIJ?NVDOk}4vRV{($@K-7g{QO_eDzZEXijD`SwS3n!Y+n=^7Ph5{d z+OA4R(2*@WhuMh&@^~VrSr3%1dG0Ej$W^d&ijf?NHvxg{XoNbEgnP%kA9|}Vm!A2q zuQ9;|yr;j#ba&kz(%cSnQMB%G0wjz>cRyo8FB4%K6O&fAd9V(C_0~`vV2*uF2XFX` zsbchH1YPQJ$2sKpud=`Hz{WG4DsmP!CvJGgK&Tnxc1^qxdsRVru8+B3J2II-u3fk| z;Cl~KP?y~R|pM z%M7n$o+_|Lzr67pp9F-iFimu2Rz@r^SCNl;?(LP^5`abqK(4av@Q&>6C)WcNG#|Mb z3s79fa(M0lq^(f{DchBh91l#2chnJvWw4Cv~?h}0o;%2TP4)K0!fe?aNCC*ibU2ep5#izuVP4}Fm2#N z0~jx3MtPS~v^F}E#IcfDiC;oKN6*DmE|4zP2gM-%@pu{b_%!j>dQ-(C$sA#wbBxx1 zG^JrOs(8JGs82Zg{{UM0W)0sxVWO+k<7vq*9%Tv;%@elPc*h|84@3P8G4!^HhzyF% z!J7o0Gxih{PPDgKOpvsz6O1@+=zWO!;|8?8pRzE)8IzXUPt8~4vOX&KtZ(2k`Q7q2 z)H`El!IB-gV}QpT4|+bn5S}>lz8D#J$8*jod@?FLZ{g$q-2SIEF*7yCjS3Yzxox?} z+Olj(J2P`(>r&3LC%4vqiU5qjm3BjwSG3mjp=pY$9blH!(75m=CpGylHWKsV8y$v50sShDg7%4QS0!HuZtgkHs2#^ViYWKd0rc=jrO<+0pD*e0nqsZi zryqQ@C&3N9vWr0)s05N%_`g~md8$PMl-+{o%*C>Co+?S*yjF8586=z>=j}js6u6o* z;3Q~BB!Zk3ZRk)srjy-$V2MV4M}9NM~yCb;R9`8gl9g# zrF2OY-Kd4x)p)`Vf0?cT<0$KTq5>$-rLM5n?# zhR~gvG5lEr*EKSA100Ex>CmpBcubNi#OO}ofl41^>?zwxw3^z?M)#KHKIya$56(HH zJr+w_NG^P5W)dk1QHf#jN3o_YI_lv?v6sx`XSn?drTHtd2fay!_3<3~B$3EZh>;RI z;QappO7iBsTH{=mBvNqrBzCV+>bCDDj?I@SM93u*0oIor|o3742sME^iEDasV|Vqs+G`&R36i|Gnyr>)5fgs zV~n2p{`BppX}8xA7^96?^T==O?TVV#zzCv+7TGC1h&(IjC|nNQLjUJAVioQ>=c}VpMrg=!Gg-W5cI}z-lgcTw9CZ^QG+NW&F%#Z zzMUgbEns<|&z)nzWjNy_)KLaoe+ii_qB4%?M?Y|ASr-sVy4FJ``5cjvHdExvC-O%?!O@F*{pQS`|EIR?~dQ6yE**E zMe>4u`+MS!X_i}Ic%*RQk(GuqxKSwjf28$}jZ2rg)U6`1+-`K6iMZN)rh9U6zXWo= zy{XrZf00UlrEQdP{{SU39o2NrL#Mic>GysuytbgMtjBt=KDq2c2ZQZIdULCFPMXw` z_e;E3E&dgTn*c6v=m_=z2x`cG}han!byBAMQ09M}elV z)4q=KTeOjHZDW_if_Ond%jm!#UPlyBQm0}%qav)z_&>S1^e(-ub#>j^*she<$W6tz zmi|)-+k#j96_nk^c9_WYQ{x2?MNgnE(sj0@s1e|JAsi! zCESM=iL$&)RbhI)MP97v&ZE(~$5gt|^zA@e5DHCm7RfBsjE%*39}YM*fAIUS@2_>M zhUzY+)NLmacmq{e5-KlXva5b{{hB|T1;AaFD=;Mh#A4> z*JE+%#U@|=5_JBxuG~k{T}^CclpBwumOrNPfhYHClZ22T;XfEPJ$11au(GF`E}4C= zCV@Xr>D^7H>UxYsyfDci+{%2yOIZhUM|jEj#d5IjjOy?I04IGzf2MUdikI4OJ1%tF zg)1^JIQ`rAMjiOBRfE5|LuHNZC_A5|)0?Y(N5U4S;%k8-Hl(NoQ7Ai>DLK!$$n8oU zQP%xGq21bPcdM)E(M2bR43_ZAxf>ivo&0FIBL_I|iWUC=<$t2C7w9aysw*hoa~zXu z5N{G3k+w|Wgd?<_{plj^>+uszw7f|!w3*@4FNBtg9i^K|Qr=mCJhTk0&u|wb;+R=@ z*W)vOJHxuaEQQzhJwjH(+I76?-7E14q}5*F-ADlIKoq}N_<`fj@hze3lB(w`o=7xV zTU69gTUy;{U0tDG#!l5?6q6ZtV~Fil57z@OygL>CF#D>mR4Gw9vI3F5gPLMwFG3+S^b_vW3Ra%Q~EA z9mxJwA>TqZ$sZ8sXRm)z_IAGefLf+M8u)BXSln-}{3n2e~I8 z@m{U#opV)_P=;=n>U}p$Z7xIgmRAY6F%8SLNCtM`xGpL!1=i=8agc#I)UUnPUH`|Gd!LH_`SeSdM+{V}Oe zuXSqZy6&P%M`v>~Exhrr)8ktyBW$Wc_3w{PMzy2p^YtdXrEA)MU(I!6YXOE!yLeF~ zxpZ&Iap-&c0ncn^yiL`=gtuJ@py^tssM6~iUBu=wdt}9%Cc$Z%3!*~mD~-Ye7p z0ER!0Jr{p*rF3iB>b4qsM-`@DNHdrzR~P+swjDaM}JO@5i7RHKFy#;m)vi zi`3IPUs$z){{VSB^K4^mB*`enKQw+^ZXJNZtj`gfh}-C$ZS7laq9MVV$>r2~1A=+u zZhh-7Vm)u)x%ZqL%xs)stD?H~{{ZHC3-HUV`kSt`bkH@cO&OBrHo4S^wQmmR8%E+( z;yHbD#&8FE+jUDgwVf(>Z(@z?nS2>v>W|08=i{ObBo1sWNgGmQ7k1D{NNtG2av zw~&iTcQntmNH=XG9gPmQxG~#(G7%eRf_ogEz?vN`)61?nLfDUKau2A%BjU4fS9^vL z`EGp^-rCHF-ZaSYvFYran}5=ij{ucIR4?7Kb|2@6{cDE}v#>ZCI?&7;V|*Gg;DH$1A*& zxoIVAoyR2Pdi>Q6tku4&s3e{=Wr9p?W5#eX`gW=U>NJf?C}O^cBvX1Q;DR%u6&Im2 z9-4{;24fK}%%OcfX|L)dND35;J`Vs80rkyi`c3(^NTax!gssR^=rO?`J@Z9Y@LV~S zrI4|4jilf)Wy;p?qqD0Wl&B4?t4D7L{++2KU(;lQ_7zv$3gdV=2k%ao z)4&(Pj4W|4os^s@$^QV(XJ_XB2Y;r;CJ== z&@Eo#7oB90hRDfqhk|l@)qO)%Wxf`%NHZW+-bdv>Z_=t>N8;JZ^-hT!8*b$Jtm$WMjBU++*+YQwyO7Jxw+KOz!wjxGpmB%Ik+Z4KQ|-g=cPYzv z`_NmdNXPERcLC3@-mc3dC}mt^bIHa92f3GW74>Q|ir`rmXl_xxk*Bzoi5We}_x2Q5 zL$WMa0*5WLc(I}Ge9SS(^uecYoUq(fz1R2ws%4Qw4hr{ltyDGE*j#(A%q`5c37ghmJPSjnYXM-r-SEODIt({7z( z8%hf?$oAr?X?BVv!zgB46NBkY_LhibjHnIfz%GihAnJ@DzGQD5mmx-l0|%i zAR`OG0;iHcD8TLBwTVzw=s*eXRx7y*{#Nwjq1fv9BX`YQb-?r|?@-}6QcmxYLs-6~ zfsuwFjDdmg-nzDShD`7NRrSF=h#2i%cLqEa$Xt}gSH*uh1o8dq z6>=AGIrh)Bba~Yd_2hd~8pz`+B1~T|&*@z82Z#aA4+rE>>zkJ@7!+9X&$%_yE9Gzr zJX9UlOfOLBa3jV}F^r0dKq0oCN2Y3=bA})z2FUH6^*nAePXhz_)JYC?BiNrjQloQ> z4B&t>UB03#UeyN$*uywn$J(?UO??HGZUl22RsEw#}zCN!Y<75~PAWpcLRg{@m%)os2%~5mp{pHoqk-u}6BaiD{fd)2dG6s1y@-enEhRN(Wuc93A z&D+w1MrnUjjB?o=f$?3o_?t%Hpd1?PssPRjBes1j;4!L#z<2B_Pf$N|o1F^oJ9`X& zI{LANT#yH_sU3MOyKk^P%|y--RrZ$WzqM1tMtgIT`;2GetIg(3yZ{F^VZ*o>7~}2U ztI9Tp80}nbi5#lx{)K_m}q$1dy^9cA7L8Zvocc>o_@wR#t+ZBkennmiIPe*X1?^)ydy zezV5g3ck{PHlKRl_zaFihUGb`IP#KN0M}5)gl$&?KEL?~`c|Q$#|)?o7F7g**v}r- zmT1#McYLdE09f;$Ff;F3zLf!z8)(S^S-{7)rhlzl<&KC3Kky1ZGQt%QobiL}^Hw!T;kVQ-B8`mT9wf#A;~j_l;<{bfO=lDn%ECD17z}%7{r99y zH>si^?`C|{H1}!bxt*Eh$=XMzJAJBW)&j^{5I3mF1bp_cv0O;esz#f$!6z&{wO*RmIoM(2^q1#|tVbc*XCbliamWo5|wb5?eB-0Lp= zNbZ@W)LueCWo!Z8H87OKrb%}Wx7{c*w#f6yC-Wa_ zAPtEY8}|&X_Rj(oBxONi>688FKB6Ix5=2U8FWrV%54T}clu;3y63dPgcW;qaBeS06 zcC>K=CPs1J{VUs)k;KY6d3C+;Ws#9i3##@cdSaPAwkRVh09mIa^M8Zbdw!I$s!tuP zJ_VneY@PmG9Q+?#*IP-Xw}C(9%(ssFg5z>Vza!qMdV%ew77dNZ3GbzZrM25M_mZI| zAbhFve@dk#oKrzEIEjM}OoJew^r~<|&_vC0;#-+F89C10dwkbMzK%&P-4Ve?E9T`` z{13GX^?&J$Y{y$Yh(7!9_8Wuai%5JjaL%A|eJD5ni58QvfgCa%5)b>uYdS2DTv(({ zAs#D$GJk|}Nfci9Nw#Swom>_N%m^4|^%Og0-(Tanj{g80p}G?+(X^>;H6^pXwey^8 zCp?2%C8myTr%9}*SZ5>69?`Y_^$F7DX|~xuB~QvbsKM=@(wg*}a_2WGypRU*$3JRS zmuuMGI5dBJSQaW4f$K|?LjsDJz_X8$Px1D(SB@?f$dGG zW)1IA#yc=NFkE`??75`1)TEibF@+#=5cCcGIieBjmb!(Utdnorp_$_uE5<>kNfs?i z)rPGjBo>)$7e1rDKgrrn#U=WAyl##i&NZq(T;R{sE4XAWNGfcFs3V)4%a zy9c&8EDwBpoPM-5EF`kiWL-U=ySCn2W1KqVcIVU@7X|cpWs>4JmV;kRj8HUn}+D-q`P86Ca- zsK~j01!wUJNfL#WH=A}wau2R^Lgt3r=_a?ivqiW#F-WIwPq6<0O6wa-G=|P=d`QX? zDI*{*N4WI=0L4`6%d#XGh~;4$oZgM5BP@;pLcO@sp|Ty5#6A-miHoEtBs*# zjku9<`hiEUF0@O&oQl!9rRPm1T%>2rWCQrEX7u2L;h$>JZCq?XY@+OEC`bGE5ifc- zQlCq{)ikKF9kZ~xv{?gOTCRVMI5-~tzSN-c6p@_Cl2;H!M;ZA408e_@Ceo(VI;ss> zdd@pr+w2=%VGtxU5V$eTj#5s*h6Eha#m0wgbrr-9aSgt+W?Tp)kzO0D9!zXF&Oe0r z^gfh3*RI5KiR3r<*ni$h(m#k7+C72M^=o+beKK9j)>95)C)PGR#@XlEw2PF~ru;pz z*JH8MHLZbB^(ftULb?9{r*sJOE-~lesjolGlfvx~i)@o;EIA;0gYQTBU#)e1neoPx zs7nkJL}Iu{KAg;7`0tzZucQ9}ywfjwH>J9VSo&>qq_t~1tB6g^ zSFkv_F)-sG=lAh?@#YoEv!O+8)cp+vJqy&bTTf=fS+slCUlcO((^|3or`!So^~G|F z8uzWt+hd+Y7UE`qr1e$Bhf&(~0J61~^4s@uTFn@hXU~^xpz+8j&GLO~&|N2g(p_zR zcX6h4p08u7NoJz@=E^{SWfC@cXr$%hY-eZ(k4p1Pyf;@;WdXjB0UV(+6c9F{9*n>F zG|kbH_062OR~-R=d-XO-Uh4iiGvK0}m11}!*PMzM7V@Mnx|>fm;?p9dXgYEJz|Gr4 z=*upnn@2qdg&(vg zz;77}pUt^WK*7kMy${w_9c|M9=%u1)IMhUtnB@`?mU!?Awpbjf@0vNAchu$vvPZPsCt8`bdH(P@6M$y!_6!{ zEyVF}SndcLN<{e~B=y_xSo_1Fw_A;P^&e9RuB^kyF@iyRVn+;aQ*WL;U}xL(HOsBz z(30^!G+a%#^arlJ!#COvpK;aq0#Cxb`C_@TTZv@1x>lCONX8*5aOh8<=hwCcUltl3 zp$>(rbnoHC^{%EI$#12x`gr7zv6&ok8-Owo2b>YkYCRh7P1EkQ=_czvQCCL~x=59t z8;!~{;7C^zFDsZ%NXH$kUeMx@tLhiJ(Y=P|P;GM%iZPHd6@N0YAm=BNYO3qpYveP{ z3J3oHC;cEjJD_?+bUW=av|#J2p#7q^VVmk#cI~rauqN{m7<0h(tZVT%@SE`#U&S7m z>kq@D47OG+6`q@--CG2QMpXq#c>e$?T;;d&auoB$dPefjEv+QiFr<5dxtY;I%B!Cv zpG;?iQEEE1y^wilzO=HvXo*&sU7dY`ko-(}Wj&V(w+N3sjnxN?}xVOERsT1n7 z*lr|Ng5WqA*Z{#O+VxQZKNmDE>gF7UVI zE^vIlrw7+HkNz9}B+vLw)mqZ(9X%!ejHPU3(C^c0GKb`rBlmJHJ7b*loB{!RNIYBA z)ZtFAehJ=R>NkkS{2v0 zHU3)6XCkB7_x_)*r=5kZmW|TN_q{U^(e%6D7hAcVqu+l%?07MM*r1L-`=Fh3e-4dp zsA_u0N=I#|bwEL-TC*>SVQ#z^WLyx;Fn^e>^R0SMPwJgKrP3H}H2Dmc?GuRIt`C>@ zpo|W7kpAC#@^|8Or(at248yCfE+*A3Vdmme14kP0yBKkUk}y6=uJX@a{r+ z8(`SY4&wh*gon+^x8t{{V6N)yp|exOKdWGQ0+DznFHxp?ysxD*{6n^$rUXdlBva z{i$G}t%Iq05Ljwv*Zv_uKQe>-$NAK7W?Qt08I^kuIii}4y2rO*+=X+V*+1n~wA*6S znTqFNDnU5fJsXN(SE#{k)F~9#Eplz2k4x9ji47t?jAG`$6+MMCZ8%X;Uy6`xuO^$4Z#m3&0QXXiBEVXEoSY5o<= zDLVx6f;mq>e)SxRf{g(OdwSGnxYd$-b1lKx90A9t6r;wcL0ARYcWxt)55MxN@#x}rDl7!2CBlxOiJUgoJ&)S1>KD*l z*vt*eMr?Mds9z@5)7r@QI*ZxWsod! z`Ei`p=q)9vFx2B^iUu;xWKQ05|DXBZxa0 zrQ$U`h~SziVkJB>LXPf9z#ns6S_uF$?8GWK7|SoFIPNHgeF(2A&Hf@*vVrbz%aP7N z_pLLgwCs3(Q=d*LJ3z8&Cj^e?HLrBuoVQ_xPq= zHU%x8Vd+AxA`1fKdSj7~){j~MHsGIXe}hlt35%^gLWrZ%yOYS{HPJ!i8O3&NXB72^ zT|q>Rh$kCY+*EiC&VQ9jBBLe%+DENNumSn9K6s#ANoip9D>5EOYJiqj+Cfq8R^=s0 z3xYlBCd&iZgYQ)E@2M@wT0~YPoacahiluQlLK(Ax!NpHI5TvRO+?>#hiI}SlmN>>J zp=S}JI2V1%jmnXY!#(IN?c;B0P`F@x$UQ#Q4aLhraL+5M#s>q`_Mm#ssv>5XJ`@gr z->IRmuocw0y3XTno2kPz>K(kmZsv}CT7$QDE!zUJ0k20K`{Q(1?!dM=_NHqtpn2he z%z!KQ!tN*iDvI)WjwV@VDILe7bbg5Ai?b@9|ndHYi0+}n$xK2@K-?^0{;?J#cn z&H%`(&Pd!9tNlh?tiY)NG3PZCTbIGl0MPqe^qMgF;GA*sMGUL3GB5)kVr#Eb*f~xs z6`kOSXR*ntN`Co}sL2F_@m~_=ExW=fHw`|qfeB&gZ+-9jWu1FkUVu!Q&(^X!kE10qsOp11}<~UB=MD%^LWJ(Q}F|@&5oB0R6yM zaS@yjJ?LH1ZiI&JJ5jr!3uGzIJ!o9VDtx)e^rTl+#E>CXv{}4>u|CwLtXm0F%sivM zDcb)401?`kFCz~d?!Y6|de8@>sC7*;je6U4yCyi~^XXVWTG>XI3|(@B`GEDWN9)k3 z5&#D|tUIpkNw<~2^sP65$SY_DUvT7+A4Gv;)m;@pLI&P2K>7KtD$eB=*`o@;s{UYh zOE@gj3bN2i~zu3dJq2UA+^*d zw$!T?#Oo>gq*4%)TO9M~D3WR*yitdfwiju}4|)M}slzNmH-(pH(-r6w2(y zB*?=P$miOK6%z^vlr{@~(hkLBTw!=@IrSAjuWxRa?{MsVHQ{3iBoo|Zcc3>CT*$`Z zWSV7MkjycI>t9i>L`57D#d$1pN88%174``;#1q`Db$=1?(KiE(ZO8Y|t$g~qWVP_p zAX$`#e?jZTayZpwC6$%3Ta(E5;PG82zA)RYNp1oRk~5F@&0Z95snWno@x&ES;e5PNjY+1fndc*;0fU8`NHOK_+*61#~znEGILqBpl<)-{SGFiUBR2kRyh*p0R zLSkXzgMpHLaB5pgtD#qWXVk9;4<&vsXIn<^YMzi4A%DTc)XM`hAdA$r@b$+0c}AosB2n|u{0$;RyRNdEvzt8J`u)|#3`8CWVYU8 znm-hvE4}-s2OYn?GEX$EVr{@aB4u|oWE0={QZ&ChrPgsWD`o*tN z%S!lSLw;fptp$qiZ8|t4V&X|9JgM@q{{Xmp5%20M;yyvYxJr}g!`F#@9fyZAw#e8^ z6Op-q`~LvG^(B?d+{xmy_;R@}qi>fZ86)}A1Ne8EJ4+tYp+PU~NCuZ@6QaGeoJ_K- zLviRsU~NCjsH)z5A98{@dJyh}&uP?a1dJVD0Z9H54{D?MqXsW*o+f2rtQnAVvpMhj z_M&=Kh--hWfMvLR_viSB^9GqFxLroc^qHc@|ql2KBfZ2jIH5F77XQ73}k`np2yypx@)X;Zl8=pEtS5dr`$f*)8~u#XOGSg zbbpbGz105zhPt+srQPcAO>ci;Wwtw)gY&}uu_AZIe~Y&wlGa&m<=PVxOu5)OC_OXp z_ouojW7TSM>+89_TU^=eoi^I-pG#WHsM^k=NfDMsXi3J~wBsCq?g8^(Bc9Jn*VjsJ zhI`#6P}AILlfmLiY)5ytoPX3pJj1>#A<=r0{{Th3Gw9d17L%fpEXmIGJP>^uNc1(T zbe5-Y)EyqS8dp=zZ>d$o(=Vmd#mN>L$A`7i0nddn`*vf`9@MFKVRdRk%BCA90hU>p3gq*+9>+f8^{v(k z8usFDp@XS(iEVGw=gXKOk@z^?Jp|IVU98Y?r<~np4Cb?bolfQ zQ$^Bstw%`c`1VV0W+UHqsX0%P!FR`XBS(UgcNn4Q}6~blccElxdJyT!E)(cJY7A zNXq%~C)t2O1x8PQPn~8@#ceN6wUSP#x)yy+6hcXCEoBm|xXurTNZOL^ZcvkuIXSE| ztoqt-+SGp8JYoy!3 zXs+@{q`-;$`7#(u8OXsH%@L8U<+zy34)|n@iEg(IoDuuC8OUyUKNNZ|5iuFLO_OH+ zrMaX?qLbQf^&YLR>ODQFblr{4oh_e@3Y(Sj%%A?~kT)p6 z%J=8g99Lep)^v?lE4>R+(e=4JJAV_zw2b(+%5s1@=gg#z;~@Iu6o&-;FR1ByZSK3J zbxnnpiljDLLkD3axx!CvE_X2FJ4pl*J~K_Pv&2VUGXPYg=N`F%j4I+x)#iParZe_=L_tXXTa@7M$dNMG>W+8Nk5%)&OI~6Dzv0GxK?MA_?K(!`W??I>XLpe zei3xOn6m3yc9GNlB_k!KL#Ws0k&BJd_mj(YS*Rpd;5JOt@UdN zbqmcbPVz+?G-0+ZhX6jp4$;qU^mhLMNz%2A71B$4T}MW1a<;lmmdg8F6S_#l{%0_USZ|WkdvzYux z^-o6rAoVX#+TKN@>e}|Jp~{L@((c_IisWr3Wgv%)?gw{oOoLetsGTXUXz=uv_fYE* zMQLzEv&{SBx>X)_wVD3_Av`wB^fFlDKJ^gAviqLe6 z3$xXIVPk)HrTB8iq}rmk+nay}*vx>A03@GsG3n2udM~CX*F-vxTy(aRCYx-s+gsn= zZSh1%b_niMk1$>pyNnNd?f8e%(_Cq`olm9dQ`_3~)OfS$%d0%3n;UU;*nG-V1D<<* z=x^k;`K)~Z0L29B4#VHs+{Y4Fw95-0r|R8K*YOVW?89><)3V274+{P!@sfct&vSv> z6z?9j)16f|t)}T3mAI2gL{WNnr|pCJS=C4JZXLkqBkw?Oo35LvF7#uj>DN6`)^Le# z6rl0!Ex$6MCxi^7ou{_Zo^e>O;vT(Zk73f9CY=_QHi#N0D&eKMxChSV$H)W^^r#R0 zBy}mb9WVUB@9VKODemliQoBKo$pN#*dwPFbTG#DdN+*H$qNobL;T`cyeJj>oMbwwN zE`fTMdWNNQaM88=vn)AMyd<1pxFd!n%(m-b>9zdCHb}-k2(Fd|3N7 z+ZbE-Z-7()ImSpdyLEE5lT0jjlJ#5yiUbWF{vHCD!SB`+^D|J z-`*{kZ>4#bJFE;F-gUK#*TE0OC(FM>QMUH<@h z{)e`G>O|94Jwi*hkIvj6JnTO81<5ks2qux02LK1^>GVLvlAsxF_NyF9QHWqXa>^M#0b99-^a+ zDcL`S=yA0a9m5{u+*Q@JgXn+;VQmgv0n3A)>x0OtLKL=E+^ymqpj_=E+<%1Q(zshf zEY{AAgHhvw*+=f1PJNCu~Vn7|6#pt>~8T5Zb4XGHVm%?kwa(6lr7b zlWu`y+yEoeob<#2z&P#2EonpQQX;?tsuYkgPCe`if(2JZQW*y4*6joI8 z9lxeMC{@yo0>^33fBaEwI+0VO7PX>f)7fG81UQ@d|n-X736;AW#p&xgSv{iq9+D{I`bdz}P93g9*|p4q9< zf{cyFpIVkJtf5*kKt1!#NMgv(5wG8xm34ij@jp|z4(bR)&uZ(=HkHY)n3^e6K1zCI z*K;7>wU}-mlzJWekRwn%=upL!9mBexS_^k8FeO(D>L~T`!?7o~G`V&|XAUvznn{{8 z$55J}9Y$6;W7tyVkdv@s^_@hGZB>H- z&1Ai2Z<{%hlpVt$*3+yag4kSt@)$Lg^?X^keZ#msif7`OrNeNdcC!M~Si`I`=L9`y zmNJ{Yh}0u_33MYqp$;umcha1Gmo=zw!yl284KfcuI9P&B!??-HJMU<+_c^L$HeAac&j)d1#`x}=u zdH(=e0h+=3E>xP7V*J-nwc+7S=oqTuE)5soHV}wOYQ@ zEu_0?8J$=KIaBTHQ7zTJoQxHWjIMLL8DsbMqmjYvLIsC?OO{uLD9SXYS2)^Eaz5Yh zy+J(kOFG1g>Y$!L^r#}5Ic9!v(hRUC7{|>=Eb+bWA$|Y@2h;s4queD7zZ`D&B59)% zc}pUb$Ugr7aqV9%^u0@{Z+sY1I8k%|094~3cge52(kmoMHmZ@p4T8tlwHDDe7;RI> zBV#X=9B?!DuNw#(Sr^=+cc&(wn>$r6I(be9B-FPWmA;#&tTD=xOCTf+_CCMXqSf__ zbh`0_B&@`rH+J_K_W7Zf_EX(lwfxazdu|H7uzPdtJ*vbT8+i`Q`4lEuo>p_?oROXa znq;xlRpUpIf`uWBxb??;Rh=6{g5pTy8Ioxq4aNW-z<*k0)orZwn)BC`X&;`w9;8D2&MJSU5fy#&9!JO%RsySx7<@Ws7zI zk3mtaF_`0i%HD0*=aWPL6i$|qJc%6A8;IIGji{k}5!>xn+TB0&+#yV6SDPH;x7+#G zS;BI~gCQrMRyfU5vb2U-=DMAv+W=6CISj}93{``%vngW^&ShSlku70XX#W5_r1Dgp za6RfBHtyQ$2+;ok)OTf-Gmr)_pdYV~gJbB)-9rxXOdWGUPEkJ5?RO!m5XxsfC;ia-aj`TNidx#x}E z%H2%3V;^kf6X`^3?hD9v0sQwo9A0ycNQH!*)YsfC{Uof|L&T*dSBj5b$D~q6PC9;W3 z&Ad^M?=TYkRj@oodX&R@33Gr0z zW6wXW7wHR#uB=iCfifY>7C*y|Kl5I-w7(+Ci)d~Z==o%5B#Pm7j0pe()3N^me>7WF zmK%FnOg%c9h1_bhL2wyKw*cUWjQ(htcRq&|D!{h45wf5Ff{J^2NYD9FKUwSd{XNzi zeg2npW4c>rQI*|+l0RNO54C&8KP-Uo0-rPJN0~H@F8=^qxUjeBeN#?`=Ev$Tn%-Vx zTykT<#L@bc?maPC&a={eJ$KVrny*gWO=W#<;5D7WCOK3#3)@IQB$I+r@-s}G8`U>m zL82y)Y1Fb=-^C}1Znr8F0(`_bKek%AS0#!h{I z*0#>F=#58N>B(*9(d;MIpmm)tY#eWEbDS9m0%Y6TMdT69WE$5_>YYCDPpa5U95@0N zTrx^MOl&w|??W|ZOwdu}E6ZITjA-fpuF$_`y{}Pdv6<36)>m++?*jvnvM*^+jDz7c131qbG#BT0OaxPekrp= z>uqaE>B+Q+^#zkjm<2FOcLbBah@aqaeMMN7Yoi9s@t}@%dyW@cHi>azs0B&vbuB+4 z-%yeV@GmfP;mU_49FNfAxlXnnLms_vrgbcRM`ZvoeI@v~g;cxa3TKQrnNMxwwriDm zKzoUsCfd&txc7H$)S7o%T3_7U={Ma`s9KR7oRH$%OH5@q9osAsKp9>0}NSD=H({S(V zYmwT?Ca=EPEp9FdQ!L1yP!!`a58!nNBz$lvhfV0RbtS{u-b)6Pr9v7jt!m(e*s10s zRqo8da0e`L_o`J(oe1M0(;0a=(1kjCriQcBOKo*@H0?S@5#8#Op)VHo?ViOkz~p}_ z^atVZRCM=7*j#DSUq^4!kX#0_S&J>@)XWF(BSpXo!94L<&XuU!!P54z$*3UFbgQ!- znW4I3YuDen%QB;2Ap~;7`ww!{ewyXaTwg^lucTdSuVv!g+)g%IX>sSD3poXq4mbw{ zpHob6{{X@4dzc?Kf9fRHZ}k5F=k}h5ORHU5Px0f_JV>M_NUtF(%WuX3LP6T#5s^t9 zL)Thc>(9~f>lc>uHMZB(R@r8^n6eek*OY8xcm(5`!@vBl>peARWz)SaC7qt0v9f1j zV|^x0`JAxG1dv5OXdP3pNz<0My)D(cHlZ>|BGxW7xYcI20C5!9Jf=wkPUCR&qsCyf zr86o&hF=r>TL!`P{{Y`oL8xi^jjfim2jWHkpC3imuiuZ0#(`xk{LNGAZ+;wAbNaLexKK`u5M$v>75>ZC1(1q zKE~POYls_(JZPlhWQ@t(G3tFdrcRdW=&o(7I;&La>pLxGcvwAzP7E&O?i)e>0Hr2W zXB>{))ry4mDa*=Alt1gx>K^FrJE-*i1{r#fScg-;WEhY_72*fHZ;#FaADe@kHE>$( zniQ3z+lSu~A+z5odl8Y^syy;ZCkXJ&>AFd9jP`>W+aS-Gcq1aKT}>6V7ZZIQ!^Ikx ziqhN$@rm=iwZyUCM(d2ap$F83mmCle#S82GZ=|~R9ZN{Nz0@q{ zgd@)*#VT7}Mh<)#fZ`_}U#t4@i@vwA>P@KD%_EL}nsb=O# zdy(8{9+?0uEar4QO-=`o7|1PsgZ}>j{C?&G_|5ow$6V8O9*yapb5Eb?Ja*6}wrL*B z#&AKCzO>w7LI1|D^C1j6x5fC{bV~+gS zsr3zKSyN}ASoMCNbF4vi6~>pSNf=ia&wxr`;z9;PMtLI`&!k_9AAt$gD&0fVEo-E8 z#F?43TR9%xE(S2$aCmkcnyo3{Vp*M-Y6E9P{{ZIWrju_Bb~ZYHPW3gmqo-TS(dxR5 z#BtmU&kqRkOhFrE3$zA3@N-1qYm19C)?u@{i%*R<+vvs>j!Q{na-u{ajIP|AbGy>K zvC=Yh=iq1jLfrIjtJjl7)4#L4ZF(!~Q}owYA}!lu9rqG&8^7MRo|XJl>3*Qo?)v`U zSB5T{(_)GUq8=h$*uUlQXNY7xZNmoi!RNgetUXNIh9`dFx8f&EYubCaQD|3juU+a) zWr*0%;HB&_j1w9-{{X7US21TeT#VO@^$9g)y?sYo)7|boS61JVCUb_|eH%Xf*Q>hf z`=CD&bt|oA_g>YZeFp7r^?f?d>-SfYrV!6*FZkDToD32;z$6-7(?0|+I`i=_QR-W6 zv9Q#-X8n?QZs7zq^jQJ;7zsLz3^p=OXj`b?Yc(D($cn&A&r>w$eH&Ehv1!&#)9ZUB z?9yB5vE3Xq&9?$U7j_YokCv_Dr`qeQ8MSkI9A%(=eg}! z%+cuDcTsf?sV&9Mfq7(7JqJrr?8zqWqj7A2M&CENYPPqXQ>M)yNOY#XZLRA4P^&Jh zBx*yXr12k&Pn7M>?`%*CzdE<^KQ-X}@u|Q`1_;;qX)0LHP9?mry}s=*R0CR9up%nv+@DPG7oX-RCS#q z??TmH!s;T>2FzDVr)9$N=0oZ^A8PZ|7;JiqRoY-4nbd1K572|Q_&LY+>i!Oq4uTQtup4$)QDr+NaUOm#V@v=KA~dZdVw`t zgpWp&*zf)6ISO{*pImy1LTgb3?d1heVkz5ELvw0LiG->0l^zja0U;@Y5_F9CZ)OX#GHE&&^N$jShk9Uab$()YFcB_E>O39JM31@D>kCbF{+xk_A;f6au5>6L(Jw1CK~xMzl3{{TwqQe<~N0ESK#NCS2UKc!2TWo8kRp1_<}c;P7+k+J|D zqM?>&F|g%8_uzjjkP`syKoY;(*K)PV#7FXmCoDe828D1y|1~mW!AwG+mA$OwLUfQfrZ3BUk5CE$K?nkKpwPNTV;@qs0q7&R&)3qxY zV2It_z_)X*LJA`j_=e;UxdI#)%IW1Pr<+>-u znn0&)Yn%WNYAdDn7}KM+j(Z!0(aLQ}oi{r;@BaYd?lIdHbJQ4eNR(K4Y2k!MhCuSh zvBsN(7U6*{kK#k>J;ipK5p5ed@aCRh{jheckUc-cCNaejxJVw_JH@p#DNt>pMg$K~ z$&teW{3pNZNe?VH!fTyM3D!G#vGoHh;}O|p9*#$5AFWcg^7k!b1lYP>2j3H?lwfYp zrE3}+7}x+oIs4XK&~w3iqe9UcN-$6itB2z_$oH*JNP3bB-vm$6GQHGhL0NktL1QAvrQ0=i>&m{bE5pjy7%>z;8l*{{W?E+U}qAFpbhV z7$Xbw#wikgC&F^Cm0m)#4F3RHS$9nt<7-$?o>q#9!(WyAz;D*R$c=;;cy+|OCF=~t|3b&R*E$NO2i{y%YfTQB!F?xxuAEw zBh=S&7#ijmhxnc}A=~vxis%RaPA{hGmhcwxIbw`?U z*b{@!aA~JaXO`hqDv%o`f#R3!w3#E6Y~YiESYUSkl-Hui91}=Bn|U|`%1HV9()H1t zejsW)=nr(y3XvFyfx+`*jMj}~6mlw^%Zy{SXBrii;ha2a>67Kh1m_i{X{@0`ctw6O z+L~d2dND3Y(du84BjA-qDm}p9RX0gj3$S2%fr==s7-TRf*!t8H7F8#ak7J6KRyvWf zC`K}vkPHxf-q@&vy0KX{A5ou5`y-<%bMJ%CY8sC6$W~N6&*eGDr3Ls9At<|r#H!wl z$EJ9%l1hb71TY=DiX8D3P0C5*wMPW_iIJ4#b`(nF>!Uhr->Dv>B9-wKMmuvrW>VQ@ z?T$jxTZy8OGB#C<41#g`(3`b;a%7C;ckfGbeUqOh20p8}Cj^$y^rkHu=oJyR2cgXX>IFagnqo2O z{i?-;+ZZ2XUrDh!(!c2`!n1{jXc~Rn#VIOqM`8^Vh{thm!MAtapHWLuNQ5Yif*C_8 z{{Si{WqaYlyKvo%VAgu-zQoqiZ%~x-M-vEELc72u0i5Hv+KX6UtOQAgEWCLLK4I_g zOHFvJ@qn(!IXK{q`&GD>OGylFHk02U-l}BlMl(m;D|vT4!7@Fe9w%eBhUfcLDeZ0N z9&{mwNo7C9$MdO0&xLHpS+c8wQ#=Fl?0Zo8uHk59l^mWh0**hGSyGTXmWQ3;D;&AN zM^+$$Ju2;nm31Ufc<_Xc2q38in0kzTseaX`ywn8blB#ixoB@v1S+yIqc0kUtvH(av zYP!X5K*B?xLUT~JhFh}o%*w0g8%P*jXBF`-C%ug#fR=?gTzb`QMl&oi&a;^U^RY(_ z_o`6p_b)MwB1IPL?Tlb8PPN+ZSQwaU4Kgd+g_C&3a0Yl&_NI6(t&>k?n(Ge{3egWy z@0wb)op(kNU70y>`~^OP=BJ+WSk_c*NW=}Iph07;&gjOCGhec?W(hFef)^|1$Is14 zcQkj98P-;l#KGRfJ-^;5J5I3FZ?6Kh5-JwUG2;}{&^$0(L*b2!lKjQ8B^+H#LPVC*AkIl%`U{{Wp_fD1i0!0^KfJh=&X zb$h7H#U#veD8R=#Z%VM(mso-uX-l+zWiRDCaw@>b?m&&e`dyS)-Asb&N6oq!q*A#Y zU?PuSe9?_YX?1N_%I}6iv8h49KBm5DT1>}Mn^BGA2|Jjnli_+{dv1 z4}#<0KlrE}vu<&S9l&Evo;wk8OGmgCjzP)D?Tl6ZF4B8FEqo#jrcmKobGZ7Nd~F#g z)1igYNc`-;a--0GwbET82%`+L0tP?;XVaY5K;#bK#^7Rgnoky)b!eoP@%&6N!sEa9 z#b49)lXo<>x0c0Z@eHxal0e6G$Fap0{hJ%yo$&09haSBD0Op1zgGGHK7Qs`K&wpM& z&WAORxj)6HP_}ooPA6UBM%Wd&+wGA{2Fl}0x|Sx4JTf)`WBGgYOjlr9>gzEL9B#Z6 z83g>*O>W2PFAIi!hz8<24ExuD@o)8$UZ9;d#CKC^_fnZ6owg*0_!#zJ52k2j*H_k> z{X9^SQTYZ+}#!>p?!=K*uvcmDuN52Zu&`cTwX zHFj~maNA1zw{Kw zC|2J7*_drJI9CdA3W~0WeWFbnSL7n&JTJNVqIUL$-qz?A@ZfARsOKji(-l*<xK+(#K!Vs*$fE0HB0JP+q*mb*gk_f_WRt~NU z@ro0#XqsN7Z>#BAw?%3&>Ne2k*7n4!Tm&N^%@{a%$;jTmo$*KbdU=w=>IFtpQ)bw1 zV+k_|8GI6nZ1^a5)Me++G7=COpaqsJ>9<}9$MALSIT>#;QLou^zAC=PP*x{)bAyoz#4+3 z++aq|$2)l+^3!)8;cCnJQ?Ipdo41nHqP4%%Ze+#Hgu}=|9n|+m{{XmFg{JCyzffq= zU+K42cM@4H+qs@LdE>V~!8BO?`T_h{BvApwL|GVbj@ur-j6>@ljI`5qsI{#JR)+S* zXWJ-z3GI$QB#G<)0LXA?9+ zqch*?;HXVC7!`QXunB;8$UF|ziPRlgqTTfFo1y5MJ)Cnz6G?MBKIt_X`xaLmgct;S z^Iv}uwY>^EnLqT#kuIO1K&ILuAaOm!fx+=)1pffi&md#aR(e+A!u~UPW8z&(H+VMq zP=S9ek(2AmI|m;1MVD{!5#NvTAgI2;ckf^RdxR!?pB@Me%rAK-?&Z2*Fb8mjPiG|H z6OP{X-%h`l!&x@-Sr$l1d7k4Z3{LD3-P6^xpNbV6ZHJA4oofP2L}S&?&e-e)Q&2p*j5Auath4(4e|hL{!&}~; z{6n+TwM*zXd+dz}NfNh#2-IQWR3i7<;y=|iCPrC9XWw~@MZ)-6qt?D3vPFbj^fsBn-Vh)7HoXTM|HuStA22pHFkxQ~v--ekt8w^$a~b z)fTrA^*b?+IU|JlXc=+^!Xso5emuSVgIXMXg&&K1pBVFAD%U3JhvGiB>S}FvW^O4(jZ3 z(^{6DaKA%)s?4P$yg0(ec@X~qrzTF&-k!DI(@NIT!t+nn`dY@}bTF41a(Ih8@bDZV zRlu6tK3&|9e$+N?C!nr6LtW|J7WVGK<_F(%aKcF7)i8Wd4n|>woD8lwBhw>*OQ7@) zn$+*%>Ta9rJy2-&cCN9l!|j(vY;HavClWwZFazJ7eFjw}wH@DjS5afuzqkFP)`QcU zOjdL2^Yp4%c<`mg#*Hjua_L^y_#pZY}SvuVOlED2CqEBLNFwvdI*K2atJQMOQC<1@*?Ke+alU9|F?O z8G(-A1Gq2``6L{SXU&c%^_~DT1R6eBW%>mcJAA$bSd_036`5{5R2L(Bjc8BeOEd+s3MP<)oPj!=rBF+z+-r zcld|Zc3*`Z13sbPPj_>5xC@7bws|a&%;S;4Dj5F&m3g13BK#}XI*u#tM?u#fE}*xF zeIaH#hKlODgT=ecECd{!`VK0$U)Q)sGP4bzQ=K)|7XJW>m%5KlX}^bUaiQKuxB9h> zn=bt}=OG&A&3lkZ8>8$%J*(0-Jw2nwX6VzTSU6OI>sf^@UMoA`7sK5S50*vRq^RR{ zd5flcH>|$_diD;mw$Y>N7`1rhwb3qY=4H&Xh47_l2b``B3X$J6=)Q>Rd)~Cu?sRpx zO*dGzl&4bIw8bT}l#V8~+m+f_Wb@yQ4r_?r==+|%iS_Ci*1A(iyVVC)MQ0qEoEF9n zDBQVN-a@Bh%7h#`wg_YDMtfJ9X6bEHN|y6My6LT6ezDc>7UBtHAd6`5S%?VP+(_@( z3ibMH5nXA+SGFgzfmGyTi#rj&i1W5$?JVpcz54$E>Un1Dbimf_`g=+04MM|3Xu;R7r&a;k z4*i}MJqRcP<0tvCX#Had={tLUcIFLMDW>{uKEc@|lS{T&+w}%Pz$7rjo(?ii6V`tX z`kSM4Yuimidjr#Ok*Zx@qy&rE698NH+{#8mh$L-RJpTZ(QRzDC^mo;CeV0t$t@YH~^@wf(c+vz=LaQMp5D9Fb zUOA?#jTYNd>Fd6z>6xQ_9xOo+oU%yF2v#H!!6fI~9-#44C>(w>KapGGHyb^D8I)hx zT*J9pBg&FD0k~uDL9R6DpL-@_VsdfoPTH|+OUW#?8)WAe!y$Wehl;)Tf_qr^i6 z45N^~-)a=rJsH4Hu@dLguA%}+f*f{YaB8X3=DL_Tjg{Affsg*_y&y?Ri~vx2_U68w zJ~Trjm0TR;1E1+$_*QV(e&QYGn>j$Q9@oz-zTZ4lOQaBm%V7Tii)a|9E1M;gY-Z&V z$vb>Qw?3yQ6eIR@btO0f@c6?w39F`>d4|?Q~1^|k{M<7>Wk%QZsuq}K!T24D>&e&!?+4QFk zFQsF?&~5cGsM**-dnty>dE`5;WCQZ29;9P&z@}?{lhO3q*4^YH^4c}Jzqxnb_I-#} zj~FW4jl(^v#jKv?He?F=Ga%G)XqNu~R;?3UHX)2-FO!V(z+aO=HAoWS?_o_&-Z*S< z&cKpnZrfCU7dhs)O<$$p)gq7&0pz=ktTtto{W@d@cn&a7j34yPWgS7&YhyUot?aFD zG;2UDkVe}Kl7M+|MsvH8J+XsQ38_k4EaKQFvH>E@L2F!$;j!pB8;5F3doyWmEv3ena&>oQXw)1mNsZYH+#0cCs9I?n z^|NW06MZ=Y>gJdh51vRX?dU(9afba!TZ_KLal6tj@APMZ;<@^Aa_tiXxc3`~q{6=QR1I>$+|Bn_hhokOg?W$i(shQ@u zmD$`$B8SFEIsGx|?N8cVH#)|u_m;YqwZ)Xt?UYX+=OF$`{f|673c36~)h;#E8f-8< zw5lFCVv~BZlglaf0-)1wt+XzzyMb=zk4}s-yiz89tf;^Ren~%SCHS!XeZdeiAIsF* zx-lZMyL%gG=1AlH*p7UbTyS|k$0G;Ywl17ih|1Fj+Enc$-mqSS>b*Z#)h(7Z`d5gE z#k`D5#<=%CnRA1a$n9Q%)1vqv3`00)9vHyf=O5If_z`K#clJP+qopa`%7 zxR&-6VlY}x4?g~awN-YlAC*V%Z|FJ6tw#?L=;$eq#VKo(XPq@l=_khHgNT6KTW}0{_r(LBOKF?IbpQZHGuWQ^ zr|abL2aVjG>^Pt>*ev%VGmP)UZtMreRu2=QEcqMmFKOBW+gvKRAh07C_vh1!YO>Sf zy0r=5qs)p!lB^kU03c%+qgsBO986h8)+DoI)Ec;Uc*>sR?k&aB zYVWg1xVtB7Dc3J@WS!ZVjN=}@ zmGa`?k%jJk>Y$QTX4@!IMgb$WLp{m}8*?`B2d5gZ8S@ zN>eZSaZt%PEDW6c;P$A^%u5*FLxb;2d4}8|E~T+`BSfyQ7aV(6P2(lba(}H-X*X`j zMqa}nmDML*rFWHY@S5+-`;rU#k=})3#~k_tLuHa!lh2Yn@M_(~_k>wlK~w4NLf-D( z%PZs83@A4sor5h^Fn#^f%s4^_9fbq9VAqB)FdY*dMkhZ^Yc;T^7TY?A!nzyL{+TFoCsgVBwdg$=9605HO@(8b`A^!jj z5A6j-({35In0O;@K5<16!>TH0#0La>kM*VKZZQdj42$m3RDFwY zsB$-wE6t^F>T!eXM%z#q$gL}`jw*R-;(s0XM*dIA4u9Tjq){T>$Mp~UvB^+>H^=g*8~##Agk;E9JG1LoW@#=o z^teI*&M}Tasg8z(C>dhn=FU64wj0Dh!oJl5NN1Wz;GMT1$z%O$qQvGc*lu|q!mNp{ z(%oco%E57vI0xpqM!iewZu^rgO?7Sy%OdB?w>SseKDE|+7g?Px;7Fs$Y$)Tsb+puC zm|#i0h7Qmv0o5VtpM-A;&HNUAA5os;% z+ToFjjLLFz{9oxrTFLG735ZaqX>w1kSdKQ_E~SaEJgNsd`L4Ru`!xRm4N;`VSf(@2 zwmquv<_j=c!_kUgS|u<;5Xe{F!yiA?(;kN`cXO=e4~m4Nmc|bsln;Sbbd4HF?UrkW z{pmhn4tHnM??*Ja%rYv4K$+fH9Bw)7R^NEmg!fw9H)v$HNNw;EC>z9H21ZU#Z?#?1 zB)5A>orjZm0S9kfe0HHXcb1Syl9I)M1f1k&{^4ELSnbJ*)D|bq?Vd14YK>NCN*Q+_ ztXeyWwxqjw7+ms4zw@f-jTvHqc&_ANpHE-yOZqj#;w3WVl6PR7;Cg+i%uL4OOQ_`- z3!SWc9RC0hzpWQr1MUdv#K}A;+jJ|E;#~302l`O^)kf6}8$oPjpHatuwH|>9N0F3m zIC25x{{W>eY9=w%;4XHR&-AY-1exVM^($T4c_N={unGVx{eMamtTB*BEM%!ZW3b?n z#{_%#qdL~4v1!DIDlv=$jG9@ymTB!6NbMO5x7e;uf3;HMpkW9P+#PfzlFS%EWhAh` zuaG-|+ zCBEYyrBPSp#6my}BNdJ8C!|iC-dSQNaO`utC;AF8rb!!FtdEVVPI7aMP16}6MN+Kv!$>N85MB)1qX zkJg|*vDP%(J2LvAlv>Ek3kVc5;j_pDjN`c;*`ZKs_S0HHtl0G~s3Fo+!2*eVIpU0w z=7Lrpd=fu&*f_}Ml)n;nb(dPV)3O3UrPvP?zN+9dLFz?X$9mS4ZBZ{QNaHIp)am+ zgWj`kTkxBx7Sd_7%Mo`qpl7_Wi2nN6bB`(f>)QlonKXW{vFjKkwZ75q7gde1VG|@F=*y!+`O?CFXh@>1bSqDrA=w5U1?W-ErryuNf;o!5)~{DrblYi`irFWEkaBC zZ8pPPj`}!0p>8ILnD~bztjIH*j?yO|6`1N8My011KDrBt1E-1NI-fe9T=rp9kU@^= zy)RuKf8ICPb$*FHj|kNC`5?Ww^TP145YLbQ081D=G3~v1^~FEKsOdIF9YWUUUbdH5 zV3WZte^Zc0J;6(q?ZF|%VGLqXyj&v|Pa>7Z)A2@ncdfOqn1#MuX9?9eCAY-%`x`yK28ss(X z8yP=p__DU|9nrRk<{kMbAoIpKs%fYWkGNBR5;kZA{yOX4z0CKg4dtg-!PF2(eI4{y zX6oiQftuG%v(5%v8Qryx(74(Ld)HpB)@5B6RnvbD^_JASap&=G)&t>A?l{428IYbs zsoHUa&wl>^h?ko7nbVq=PHG78zP)g|uBCGf%w$B_rQ9aBr|P2L zb8WPe9ubHbJCyt9&7L{OBBO1feiK9EaE<5ri#4yI>>vF4gl{h5Nmk^$jZQ_|13K;& zXuv2(=K+om8y|WY_Hdcbk7YH>J4z&)661Zp89P|{csMQ3Vd>2?Y3+a1l6dwh8|sZ~ z`^c06#~+!Dd}RkdQIY}AAaU2G^f`5Xadcm+io)1}mpX*tu(J=z3d6elu{iDry$GmS z%`KTV)P%QMkZBqYqj_&8ryq!Va><9Qk}~^PkVO@CHw>ZfV-`_oZ~Z*tKnI zrgdF6LbtVb(X?PN*A9nhl36pB+#4j1Ob<>;=zTw+>ylhW{{X7wvFIHkyjxgjjXYcF zoj@}9dw(%u$EX?Onu}VWUcc6K4x_lcgH-ByW)bO{c(+*=(leD=BpKMRkQgV%N#hi9 zpg}R2xkoD9pRe^F+<&}Rn&VN?t{+iL?NR#3&%J~0jcg*?HnDjDZN*q{a1;)CsWrZ% zx9B#xvFP5Rmhx%sL>jiI5K^+g49N_DZtieSL2v6<^$wxbe-0mC>3cm>N!4{tLL)Y_ zth^N(KV&CmecQ&$8gF0+2TYXkji~Kb5GWKoR-}&4@2nv zcWo}A4Do6fHxlk;jdPv$&77$UMqqAuIL=6{G^~-@i;opr=0mhV2n`nDkO@5P$FHq4 z^j}!Z(Q)XDn z(=>_y0AXu(+MTN#o98|izO@ho0Dv&J3Nk|uaqufn78e%NTlD^oW|r_r62)<-1dc%w zjBZG$ObzjsBnJ1Tj)Pq%N9mZXG#K7!F6J|z25%eb7D2d1&69`5Kw-zdGhWT86T*?fC%-+3r*$9$bL9R{A)e2S4FUfEo1Y~X*E2{V((di_ zohdwMY-6@LnetjWZCMYPpD@^c4PL+MD=jZcn^)=wwX_a=TQMwzEXWsfhE@Y)g9nds zReTp~<+i!ANOY|%sgBKH+Gm_7k!H4aY>~LIC`YHQX8m)ob-tz4_Bw8v()tfl=^DR? zE)16$g5@DO2&%*PS0f~CJ^j6|9YwX*@-!PSQ|jGI)UoTj4_x%-t{ta}WU)o+Sqt|*&P-*&8%^sOE_;TIZ!i0vlYyw^<1dXRS z7$X^~dUs89{{UR|lXSZN8ETeVe^1=PV85O(2@toOL3IHm#XxiB9+kU7);e(dD-Ryp z(!_X^gx!^1ND4?kBz@Ndk-)EOa_g<&ycP}BBYAYU)!@=9=o{oeN3;D*{*ISh>nQECxa=icIV23LrfQ*vQ*Q23P1q-ljQrxB zyh){bu70^KHTjUGnR{hCIsT)~|VUj?_1pGVvYS6kn@cT&8I`dV(y4S>yVs0Ny*>j>>l>t0v zBP@h%AoIuCpcsRumX!=SEc8aFqT6*2mp+ZFM+}yd0Jj$Gfg`(ep!ktEIab^_KA+aG z-lqI8U&DT%*1F42YpcCbO#sq7JgKuKh&$JjmCn$41QG9BZK~R8mT?nclj!k6l3U3F zBg1&-3?;WJ#Hq+WQ^pN+yuXS&*!3&%GCkzKOKmE|=Ntb3f_TRZwSWP=&lT%vTL#a# zZ;tY};hrjg6YNhc+FRM(>i2y;FI=iYe+awQbsK~#C6z-sgl7ehJoW^yZZTc7j-={n zG`%aTZUu+zEeL%LrK`{2{ZYZ)nE5P9kXWAet9~JVAL;AS*Bv*}_HZn*PH(kX-a+HW zm@F|P4pbe(Bc4aOtZPz(Mwe0@NpsWJT6a$vO|F>*u|Q{N)C@Zw`8=}#eTOuj%G#!z z>|DA$g?_p}y-l3k={H2q3+p6oAkej55qz^TWOfs&dV=4Jg!^(nBG_$Dw3|ker z8eX9?3v^dzx{G?bE1bqt^DcApK5IL()>A~h(qy&ji~DY+yqv?RHNj;TR>Z1ped8y~ zf-%?uTfLW6^w(2scU?DOaSXaDwnVoGpcZu6K`Z9tzs)b*!F6lY5onj1O|%z} z3AivvdKr}hmL-dDybR!+@m__$j96>Ss(nY*OCpcima6NrL$v<#6OSyLS%Fe;{Cui6Z?~><|IsI0q3(0VXrIzt3aEO3Y5b7%nf8Qu@Ew>`X3AiPLdw z(ju;xEXLkDfd2rVLHr?mp5xOM$n@hcRo&CddxH0^5g zW{+8x>6ua>%rK0-*bTeRed&7*9T}>p4J}S;ea#0-{6Cjg(?4iMs%c+MAq#BjIdO8> z$wbaP;{E2_8VD3FDtKirV^XUeUFEGS=@$m&Ux*V_&J8YRZUzFpB44@;=hT zb_PiOD9RGI8b0Q8$c&tJB!5ruQzGiFgKZl{*R}07)^lkTCJS3~Gb&0*0!MM2pj@zE zaB>F~kR3M3?KInYpI1x!hJV`=1Y&KW+y>QO;@}23l5&fTN{+j-qacBr&ibRGj-_FDZPS+!uC>&ACzO)gCbw26F)&-6W+f32* z{X*_i$@N#-+B-)ztc0^HK2hgTJicx+-xUtAYpB~vr|UO5eVx6Yk+VpG#(vk+pgWrY z0^FVFIP@Imhw643wT7Fmbey+(az2%D`$tsNB7E;81y~5c-G?o}<0SUQ3anJk1=#fE zF6NFtw&F;qYkM&Ila{l1{71EGR9x>Z$Ash^q>pYzN2pjUNpW#Dod~nGkCx<_9E=p1 za90O{7!2dJE$O%2Ox<3(J;eGuCbwvpHx>?C!Lqbf$P0o3<}sgqW1eZ#Pu2Q<>!;%C zEi&%rO$$$91Sqh#jT>icnN%MHebEBC^u83p-2qc39NLK)P&T^W7W~ zjji#5b5(HePMp0BG|I0vdx`a?ytkdKr$P)y-^vgU!ExG*bp7tFu5~unOG}lwKrW)V zj|nkR-Ld&t`Z&b_lG=Fgo+b+QlgpzgwoS6{vG3YBrwlQ7U3*v3( zibN`qF4hx7IVLmRhirq$G%m>QRc<*$#il6t+NVwRlWN-jle+5Q{^hrA5e?X40Pn^? z{&nl#lfGN+2HrrxgbE9L`h)s|UVZ92J3gYGGc}aS5roNasM?V;$C}- z(tiZ?wwt5lvABKm+kA0rv}sTsBp&79LM{^e7y z-Nd)0Q~Uh8sYMCKQPB?zZ4fi6&S2d`APiWYP!IPa-$gbuak!{#QVx0;sgVl_JZ~& zgPF&TX|5hTyR6_V}rr ze=es8*xWg6Tx1+^&MN6}(41g>s2n#%E=Voku|MZm1 zs#2KzHs=J64No+oy>bN)xs-wB00Zqw?$9P)uypduT&PkB?0pS!BoU}tNXhI;uaZlL zDhU9N$~#pTaLg5fY#uT>A2c#I>JSF{gw{}(K!sp~xjwbtXOArE0reT7(awr6cMdRp zN7|-*I&c~NI6eOWO1qiXr#R|Wo5YovItNm4J?LfBBXJAq#%O_&y98~$s*Ticue~J5 z#!h``XHK^+LkBvPB!QfIniZ*BF;6n&{{VU|Gh`BZ6uqcU$iyk&`&B-=67dCJzUZ=` zg(E+DLF$Iap6WA_4r%LAlmHet1r>>3*S%-GSt6Thc8~xDkHbw^H7y>d5qgB&yRwxm zcMSZRo+(y+I#>#*Y=%JI{=aO|Jy%Yd(QX(Zk=ODjaLPSL&OInBBt<9;MhWB}W8510 zG99Rtk8|Ksql}Cm#BwV9IC#PAMOBfUF-L96Ka6{SolkB^lpKr^kbUcnHX)S0j4f*u z&2SZ11B~XZz*V^83QG&wY(DveDW29jPQ7?3a~S)VVBA`ed~qHcTEh86k~#arfQ8JLL8P4xz=l! z4ydfGJ8jSPs+X@kcI*~4c;A9Z&JVR*SP5exRl}wU1E12Rc8zTaWf%tp0i632T~ZfX zmxk_r>75m}J=>!UuaywzpF+pbSIK9WQPkGX(nc6NNgQL`*GYBBtm8J8ToN`OGmw2h ztzXftWR4?oBucY$k>71qZy~pD_Lr&dI@%(|rx4N-xX#u-!lZpaP`wmWI)W>|997s|S&k7RCX=x72}fdJ?NZw=wN(Dr5#2&OUKdMTdd50`e6q0Ki<~{7}t(5_sU=!{BRLK;ZCE7}c7#JO?Z%exe zY;!O;Ia7~Je|jYxkX$qFmustT1p4BP7HhL9ux>a(GQvDpBg16C2h4b+F09ofwAN6P zio!gxU!06ltBr6+a8VVG)ykhjdtiK4Yt?#`x0=$$DyRqoWOgL?sbkz(&izVit+{s% z++9U;((+8W;GRjz9P|As1-7#+kWDO;AtBfRe8h3<{OO}h(yWuG4ZNi0KvybqIi$GWJCc9ahijzV%NK^EVHml_ zc?TW;09uOcHu1*eX%WA0JAMB3Zqn3GcMH6siBAz!f=4H|KdndrpOhpp9m}?Y1<|Z- zWi7rkR2{g^4Kmu_oj}Dhsbo?|9fl}wwtNjTHA1_x0}wwb{{UJg(_%4V@ha~1C3|9m zu>6t%OO zbWjEu0y_hqKhCXaZEJIPai+3Gf2pOfi4}_7BvWsGRn=T!fX8p>YuI?k`$PvK(1Vmj z>d(WiSl?dEk}bxiZmm7lkpNDLJ2ZZh#zqKb&lQ`K5K%ZrR>&K3liQQ=TlCg9vfJ5e zmpvOD-NJt3QCms&1R!7)!3}R9DiCPS>(1ZQ2zjeR3DrV z@u%{wVW)`F$>Mn)Jy|jvd5yf7ib)aNU}Mvs-v{QLx@)WwE8Cd0+q=mv?jiblr$Qa} z_5iDSWFLNgh^5_EMAR%VTop+XBxsW1If_CLJ6Qh!Y8n_XGML0FGIRV#{Hg$v7`oMZ z_cp5yTH5x))sI$c3l5g~x44cCu2cU2-AYDy;P_AMa7_``tz~DQLA>g{CsDN45YG(e zHTrPmf9@jrp_8%Ryk|KTk7zwXtmwC5_Q} zX*}P$Fq7Ifl;kp=+Z=wPtyc%AqU=j4Jcp@ECBY%Yc5s^Pp-8buO-LNOnd=Oiyb zK9pf3mJLx7O-A0|Qk6t*sxu3Y_#3;Qjw&eCW4^t!g8q9ZC&iIiZdW+$0pNe1r4&cp z`9)T;Fd}*D@dD3MmgeGBdyCt9nYTg%sAkZ#y>i~}>1UD{A&{eKfP`C9u9qhXOk1#{{T`z0AGTCT9c|_>DJV=tusoV=k|7-sV=># zBr>y?b|ioZ!Q03g$C&f$S5^wAMi-xYWLyTiAKUc~Nz|H#r*CboUv!O)^a(pyXxdx@ zV#z9~W4T64s^=_8!!c2iGeSCo@*bGc^{oq1(d2%#y`ROKQk+JEPK4q>Fo(;MeFp-p zXdP3a*mS^=^=qvwST{yao{nW=*3qynx9x7s-CY?iV!@aEZa~On zKG_6&@spaNJSuS+|1P?x`cG-sAbLL`vr3d)Cj2!1QGWRrAR*7EyOB!Sf`s@)!;ZJiu$vj0( z;u1zMGu#Z04{FvlK91J9N2vb*WLjvNcCpnr_JD?-P5%J0_a8I3#?W>g^PRu1HF`Hp zwCMQtEh77)H4SgA?k(`K-9oQ#WeX`SBkegSoE+mE4326xXf-aGvK=L5t6N2Gh}}c4 zVnXtXICL9H!YCcRahfi=g7-1rM?LLhT8%IM@q?!Np6{eOZ&J}ZI?8LEY9lM(YP-e7 zxQ;dl5vUm0S2-uw`fJ@W)Rx^*qFdN>B$iO=&;=TU$gF0Kh!44AeE5-Mvh2=z;}wr- z5!!0~NvQN!Ky_Pby(Qq2dwG2de$0KD{%R{kaQ{F;uDqW=Ks{a;zJ zySe&nTYG4UCul5YfzbI~IR-Yv4~om}bl#oSx}#D2Ch5MR>K~}RypHxwRwZd8oR;2U zxC}E4>M{h2>O8}}FLXW5i`4oyv!gdw>M(WAtnYhod3rocYpDb7en0DMb?mjEi z9Rp#i^#1@z*`frhC|5OG7e9zQ_~jlbzuZ(j;tN^2`(pBn#hnGLPkG%5j(m41$Wf$bnQPwOU6n8z9E%>^2r%i^Q!`Kr;)cD)_3@m_-+3HsdPPKM$y{COzPgCjc2>n+TGeK$RR)U zLmZSi*jWb$6`|eT*rXy`t9wIWB~{bySjJ+ym-8zoN0LCm_rTBIsLtAtPiT@z_j2m8 zYWKksN#kS@tM(2TlymtvfsPcO#MD>=?oA0()brO*elzudN!aOKI}hQsT7OLR?6GP3 z;#m_RymR^D4haTsZ&z)0rFByB#VlgI|XMLo+(2km{&N@^DOD=@IMnrLB;PpG?@Ck;KA z;qsw@-w7ds9ORSQvmUtVxw?icezedn#CO(APMKo~j^f(+6}&+tYn%hi7F=YXwLWOQ zSJ9nMpv|fDma11y(k>o5xh;!$usmmW)dUjpw?1CP9QUXvj>w<}VyNEg+76AWXx8haYIauo88Pabg`BEomgBe!BAft7$r$t=Twe=6rBQk!cv8NI>GuQdSw0Jxji;n(7(jq9vs@9iE(b)HNbs2w)m_G?J6igyi6U% zPD+IphRM)9XQXwN?@TJ$-RgR>n~8O~m7Bn~1-wDLj4tdh$%pIu8?lTp+p>0KT(ExZxU znPt5=U96;HK6WLNHOorP5sik>IkonSVO%2Oux5Xt}f2 zVA5_UxH@(8`lNyzc_0$SZ6Xnk?~Y-Ru2d0$z|CM*S{Az3P0+etv!t$-(+@7GadsG_ zOEAXfX72c4P#?W&nit|6TE4HQ>H3q}e%;qCi#tJ|q_(rh^+|&_1(jIjd4OTwjHdA2 zG|G7|4%CwLcE6$ZFYDbSYt?Bw-s!WIu~TPe?yk3S&5#U?Gl^HUo5ww~SwB|v9fw9< z0N6k$zv)xz-90|DV`mfGYMO|fKT~q-+alec$O@<q61zuo@nzXKf?CC9GSZsTN;dyH@j}zMdr;z^uWy|6VJwvCiR{mKQ{_aR03vXmsb{0PCwc+feb%!`#G57GinE zJ@ebQrD(s0R)K*o>8DJJM_gQ7-Z}E3 z4CQio!9LaLS*%`Vd%MeFWq6GwdS#nPjU;HJ8|~O|z^5S_*Wl9LrJ&nh=)bV#TPxda zFuIm9VRR?WgtVBAME}^_t)9*-F?d6C^Br-QYVhI@qcsV%7BC$OqR@C%6;di9pOK&Lh zw$t5xRhP3V_BEq)RQj(~-%SGxKcRud=>P|HnI}8#&nE!)O!J=9K20LZ%E7Iph$rfL zuSmFJ6yRlW2tKsW11<-IcN}@EJLxT5H4P%#@ni(!!*h&zhaIW+PGazG3^#sVzZHSL zk{GFpE?pSKYzl;7jFCp+ok&uIjxbJXSll#m>|#TX7=hZZ+uk-6cjWdTYPTC8R(Qqs zAu*k0P&a12{X!P*e$*sgW-z3T9!*M&((<6=;+lNq`h)R=T5!$5&!ELslf(>ic=XSu zeTOL6z|J#KOi2flY8H~qvm`n)7XW41&mN=JqGDKY_4HBcUnF8q#;%+B0ejN7Zu*w2 zpJ5~tdG@ZsKn2@5BBKmK?7+{zt$b+$$Fz}?R<4v!9^_LG%tv!n%)og_d~U~-VCmhr{9qdnaI&6{WIOi*zdshlFrrqW4X&H-gVf-iCFjc3ZZH{`pih58)rysrY0_LiPuY{{U*QG~OJbO_GO#Pob#%oJ8pZ z>Ja*s@tZlpK9zC{t;1lTRO7eXLPvaYwE9gkj0=$yL*NkGL%I?T=xaR}jy0yz&%o%|T*ppFQTwtBJ z^B>A9plV1q=heB6D~DI$5yv$~?sNPcf!exU;pS4VLk~0Nm4R-;+L-EMS!^^K6pNcg5%sFOa*$y30B~a z;*dI?LblT4He!E)MoBsBK55@loXA7D&p9TuZnnFcC_uCso<`dr+>!wwZuHm1*UHt@ zx9TiQ5qB!=?R7ZHfC{cX{{ZZKQpNR>pm{CZ#f=Wud|-p>7WaWv_SFCaaUq_8I;ES4k&9AagA0H3BLX6BR*c(CcZ-pyxug&C$`_3iZbf> zCxU9oU`MBO`q1n(7*}rL2%;AOk~hn$f)gNQ(3`uLhUQCc-epnA=RURGDI|(>F5oaQ z4tX{9NNwI`ytr8;C^%I($^QU;pL(b$Q?m_MoYHjJB)R&TmyQZ4^*;1+?(kVyxs0Ev zd@1(l{VK9us-pxMX2Ae^1o9S?$XSL+&lN?rhC48jd+u=s z)y|?`Nf;xZ-V}vhy^n77TgSPA(WbeW$txVN+t0=^RgvPhR7R60 zf0YkEu4}d9mx@mbhUFRKzv)0O`A7l;n$8>RiR5|T13Q3Y+t_hdgDX!QY&If-T2ALb zYOkduL8BH_VlFIqV9r09Tkj-+e&*H{%6n4ix->qH!ZMiLOFim=o zbh13m#EgZ&01t|%JQnwNEjy~oft4Pf=7K{p7jj7KW08ETyO0N_KTOp2w?;{3+WV1| z507kAh$GbQwHj?MRy$V#Sg^w}Cp>y%+Lg6f<7*_F!Dw>%82rcInl2`UL<~4Uzyien zU?^Uw_afd-5#t_Je2(XWKdn4#W?tAZ;wn0Y=_Ds&Y6y8oL9eIy?-F7DI(+ zADh3WU7trX=qh4R(q(whEzc+URQ5W0fCGhZ4Dx-bpOi9cNZ2(b)iyq!stEy@24UYG zynE4|7$u&H(W0wmd2j4Ll`39MD$6pq7#A1=fHYzYul55yg+=N-0F*iF+&OP= zB=A9DZ3l}at%%|r7GisS$*hy9dLOTcQ|cOm!*>MMs5sJ z5&OVBQHeOGzBe1QfimUaU)_)P)*_nQ{}|5Hbal= zS`#*veWb~yX+2>b!a=s`+VS!tB=S`x?*rq4rz&`*zM}j!=xe=ECw`!JxxA6(6GZ@s zD`zEUiy4oT!2=xDZ_|BQuXHC+-dgGL2^7p!+A-Y(pd4V2P)DsaF@LySZWj=;fmD0B%LkunmOFUm8*Wpd`Y)U@^xAOT zQ(s7ReWzMpUfIiKVFJoR#iYwQM}_hE;FBIhpH9`@`p;9gg5q246HlJ*)zz;`;h4qh zW{eJf#EFCNRWimn`2|kY%zfgP1HIrPL*)ySFh9uGU>C~+G=z6&{t@@BR_ms0uTtQ} z({eSn)J3f>EiM)2jFH(-X;dFWh60f<`b${T^f_;u)xMJ5htx=?CKm078Oj{{)g=gy zs?AsFr+pKutt{=Pv()WodpVcFcY;!rVE6NOb>JPWG3-SjeOpey(bG}0n^Lu(OKe(g zF3>XPI1DoIliUJG&TBgph{D`R*<(-EXJ$guc=4gm;{Bz%VP^s{_L+ z^#-P`uXDEI3p-D9Ot!e`2Q|P>`=315T}v}N zL$AwdY(>a*3mV`Two%D$e5$$rW`*AACi6zThInAqE*!JVs9+xp{4udV#0R!G_w}=V zw#%vo&(zHY+=M5Lo4h7Z;=mc*k;kz3sV(oUmsOtLOQ~(w4D(z@s!~zeRD;HOKPMI9 z0qDyT#zGllUW0ShIxXB9oK0t_Y5Gh*NouS%rODr%Mh<-HTZ6_(!KnJLLe(vLZ&=fX z)|C#AZ9IC8vhs}0BYl8dSig-U)O8FraYRW$7&t)?{tPJE2f_EMmRj5R5$HEplFekfVpxswH?ot)JxZPl z_B_|w!_Gdc28>TU_8aKNLKgA8O;VsJ(=}o ztyKc2)ML8S?hT|mox?_L;8M2HxZI4Ob_e+KP6#}&u%`_-PSg5NqK8;Mw++8rNcgbR zqi|Xshx0P9i}|@{{SWAp2qk=01toP`$a9C zS!vbM^ruYqGU{5dP{SYXYvn75n1dt4^8$8-QgT5Yap_k&Zr7{zUXs>-4mwr~6wocN z8ckbYOO}QM7*m10yC)rh%X;z6R#Ve9m$rQ=aiRFq*-S>Us8~MtmMF3|BMuc*5LvP2 z_Xdo(Nz+EB^pm)U>0wWsK|y(6VVcXpRw`pIMnkcf;i+XZ0a zLy?m0#uQ_|PqlAdAJ;Ig)|;S9s@q@ddX2d^TFbKdF%#zy%y$nFvA7l(BRCnwE?D%p zS@e8T>ELM^_gVD}S)M198;b@YmUblX6euU9i;T{iGOD#w_2vT z6N#Dj91sY=Q~;5ak&*6dYim?@0KXE9^x{YR^*vpt-s!VTCYPm2du3&&ZIW3VczvfV zg&l$MVeSIwfs9rAJLr<>H8Xo1v~wQ^PqgvWL2`L0(H;u18-pqCaqUC@@D zZN;XmW6@RxVuJ1bN4R;EZVV(-x0dqwV3iBslUp90t;>0$F28vmpLZ4071M2Pm?T$V z`J?{;ssM^WK^fyG9~923g@dVr&+*pcHk@>07?Nd?n$%e?yKsuK@5(FVkgmM#ZMir< zp{RtnHrj!ATsQo)>Fqt`@bK>L3L?v48!qHa zrB=%f45(#lwE8IwuU)slN=-pp8x?O?$8v9gi}*bz$oThm%cSM;R12T)Ac z*B8KCTf^j@eJNx+JZOgnqbFy|k4`DUrV&6Qh{lm=(8nUQWs2@$j49+82;4nNfkSm2 zGWz1w-CA2mZ?4T4jovp&4x7AeX(B8<%0L-j#CsZn8<#26z@f35@I&#o%Tk^VM%$(= zbk(z;SF}MY>k~Sb9yrbh_XGknw+r{JPw?~cJEXr6^tm<9rbw^!=TiDHZS&i>z*%AJ zd@`p8jB(8z*R-yl>WvNbjdM?p`f|v#Ovf>*l^cZ7kZ{OO<=g3AcEWeHA-7y85xk*%(nW?O=euxt6;b~H5B(*&`3Lu&gTDjz?7csCA(K|t z5v7(Sc@{ZsP>@|5aTMD~<2;4=6q&7l9(31U3tdjzQEBXS_h{Z&c8PTv7l)15;H=qD zGI9vP`}gS1zF)-qJIyZ9&8D^#N2}N*#tE&6KhF!P%(8(7AbGk_x8_iq|JF7<9S~wb?lA~j4(roSYxNVK*G+StV zIa+th%AJ`f-QUZA52rPg^*7BJ#-NVs#Dz;i>umRgXqbC4@f(Yo76 z*N(B&5J4=OZh}M>HnG9`_}vuwp&`F}8z&?%<8Q5D`j(;79YuFPRBBpwqj98Zx}1V* z!jBz}sUeHZb^?40fsuyB*B}Fo(JmIjGq~R_JN}Hpuk3Ye4O{7N>||TEkU>0B!_M$| z1Y;nI(=`1bLAFgFrvCu-k+#z>p%+@YBN4?Q1guOwNWfg4#}%h^A4l|(-fAC+dY+|u zs>uxEXfCw?@kos77Bsnpf=1sf2?jw2K9m+tlA;V`dOAmg55!P z$>e}Y9Ov&qT~S%8!tx1dDo?NUl)5+Z7Tz5yTaK(~@2vFcBZE#-0lWa@E63+CD~o26Q;4A>Rf!f@E}UeDXC1N>fs@azFWzhL-)j%oT8~NCHkGA7x?FLj zi{Z7=LJ~l5H=Kgl#xaV|G=8bpx@!ELI_wyyVkfnfZi3|xJ7hz~c|7+XhN<~ZxS4DC zmA#F%kM@l4>ap1Bje6F)#*cNWZA*&=SGkKUxDKk{^$?6?XL{p;ds6M^;oZF2EzQ?Y z>rq}`*`{tS2?5C&$x-Y;$o@wLnmT67sQRO&wHr+jRkgZ`7iV6dxRtznKs?JN40-Rs z!Q+h8eMWwxbg{ZNR+_8cNVXH+Dezg}7%|I^VwFigZ(p3(yVl^m8m1}^i1#u0QKh(8 zz#E^t0gQbA04_+Tiv*j-pQkjvZUocgZ>pN;{^&a@@>Kp~gNzSa((gJF+Q+Bm({yMX zPu3@dK_c8HS%!0s_`)*`u6rDN8btkte{-YF40=Q%G-t)(!4Gi9K4Qnj^qmU29>Ofm?680MQ;&922;ZVG6?(dYc1vR_&>-! z7_&Bk>__8#T$tGBZ?2pD(_Ss9^kBm#z?Nz zAuZhY%pq_pZ{E5xB|Eb_dC!Od%LYER zFn=l1By+h*hR?}>a4V`x`-+3WuCDDHVUFbuji=bx*jIdq(=}+Ilho|B5%DDp*n!{P zi^Qt%@tpC=q0zyI$sl5`BV+QMCz)JidK}d?oCPXR9sX*2`2#}0pEfu&6waX;PB&te+BmemM^faM zTW&X#jB|`sHx~hwpBVM`s=hFu-*_HuWaglj;3PZ}IP7S0$Jf-fNaVRtcJBi@#VzWW zL}W1}1B}(%+mzfHJqLekQ`D~+ordh=y;M6o65wThLgcW@_VgaYvmUsfXO}~asH73<3NR?Z`fk`1-1G9nYoO4{e zOZ_>m@2>2UJ9|=Xl^e)klh4UL^FXehUr?Ir^2Lqxb^w1a2%zUC?XlX zv}udHvl*P>qm1KxDo?kn@&0rIL@~_h>w>ujbI77rnuHd1@eA(~OTEQc{7??uliYk7 zg8l^Dp+@3HU6Yh!?xv)@bYR2rI+5AjFaZu(NyppmMDWlNBAkJO2=+7*86Fl91;{xA zwH2|Mqzw>a(YH80hP=zTS~i3y9L(vv1Cz~K4gkp*_BrfD3WdQk1!4;GfPtJaTc6{{?uZW%kflkxoMM7LwaD-j@ipHIC*E4=q9 zwT=b}1B3cd?@@1Xq_Pz8i$>z!6)oS6<38rCTR^CT>SO)qbqCi!H5Icg5SbA{0B4WP ze)Vo$TH50*k|Qn#2mlrP&`-u%YD5lk%^WiNXnG{6$jVmmo=K|R@UpNHvOiz zgLHr@M!fAj0q;RHT}7@MY1n0%iiXD|d{lb&ry`}q3Z<3C)z6?5C#Pp2UEBo#@$4y$ zRG)~s_bo^Kc4IBtDNupgQE&k6-!<0S%-NxmW-XQM$0rr?)>W2osR$%yKkxcgtAiRO zq|1`y8wk!Spv*rLJ@b7)wrVH4xSgBGNI1?;Ki0e1ECxwpPQmfGoH40v?4yD<@Zu%0 z-@fes0BY?cs(DpY#3W?r6?ZN~fh5+0ExME7+ldcu6o3BN^{Wz`s={0pUoi*1C@E6cMS59}+wlA^?oa?Aqcoc{oe)~v3b4agUj*4jy~L1@Tl^I^Ea^rQBvzV16^ zg8Eb_%38`G@+bqAP{antLED^~2=|1_*DnO}qdLTk8t!6G0Y}e%^j)=I+4t+AX&qmE zXBE}Ozr}RdG|1(* zv(;|wbPJs-c+67WMy3_Mf^4voh=5Yy*iefy}aK|e+t8h0qz}u z!HK!=+2p7x3EN$K&pf=W~bWB^x_sQQsZ;#dbg-F#}foE$SU3Qcu}Z zkhe{nb^4VrD)$9gU_a^4#YxkBTOO0tS2lfOE~RMm6Wy$j9n62iK+g^KH2Cs#{nmzB z=F0jev6X~Sx=1aqfH*%fNJcBKRCLEj>X#PxhFwZqi;Q@d?HPNkau*@6MkP)FCpr19 zjs3yRd=KF|TDMDGXm^uXNvKO}Z6^3{Exbbo!5)$*%S8U0hZz;x?&igB#B*x;{k!TG z-WAKsZdycKU@L$zGGq9MHI~_4^=Cxt?{%WP1bIpcRx%@%bILNe9Qz(=+o8IG_o^(l z4G?O!*0(dZQr7KAjT<>03+E`n_5!)D)V92jrh_EujT=(m9iFjgYkv_jMz;k0HNo^L zCOm|X;cRnC;?<#?+R1K>cOluZ9(&*sk3xM#ZFg3eo&cO1D~pXewrave%QPf^??gC} zM}6z&70pXen^(|ZOMMp3X#*C}+Sch-Qk)aAQ~v-_LH-}iGx1R=7~^L(XJqV5hgdD9 z!a8+GFAE2|b#2}xnBjBSh3)sva;1}^I)*(y?ti6b`Zi{|wH|5WBm8OHd*pFks`SIu zeNII@ey3M|sG&ap0 z<-}4n?|B>Tc!L}TX7yk@<;ws%%PSuT&H!6L?T_ku}DV86wOKb5ja!Tz-c z_W0Fq?Q9~KPlFq*<%OemZo|quw`?BO1<#8nmmQ1hcJFBhBYUOuNhl*Fw)>Os+#LP> zCcfzL>Ux#({_q27;QsIv>Y+#(PBl%Rx9*lqlb|iN9T|sZH$t|UyidqpA79gjI zY`xi!IKj>_+~bdGn*QCjZ5L3}nQgpxi*3^(DY4joQvRob$EJ8S-ss!KcA>Q^biTN6 zr;_dAfo7{$9nTkp<1* ziATU(NZO?^iZ&S%NQNE zIx{KZUyQKN&NEo7mU>t1HcdfqptcI426B98iR5K}iz6J4*siH}HIAsadTzCG5=O+C zqf$sdo7dE1IX~r3y)|{FYqz6U>Zs?2*2zd_(;*nTYz>Nxc#n5E9k31urAuTEr&UKH z7*2G*Pf63(*8N}Aoj)e2rCi-K7FH5UBa2X!ASgEeVgbhQe%Yq&Crn*4S=6+9{SQ;Q z>r45D$YPC)m7U>Oa}KH{q@0uC;eObLv{v^wSA#(D@0G`;*^r9lua2mWgrFCi?fM zw7$HXP3cvOea+>>3*zdM#tsz}097(U2*;nzjL?M9wHvKJsk$FTxU-VOOql9A_O%<8 z-L*0k#b8SyaKS+Q&6Ym(cT%x!cSO*-%T?){o}K6$Hj3KT3nLl0xsAW-Io*bLcHptV z$8ObWJiChmiWlQ8vHqj|M7aX%y+zQm^&e2`b}Q38J+|7y&Oza=)QZ8jsww4)@XgLM z_cV4N#2&bVtn78^t)XePeUaE`3fqzx8)%F7L-LWqQh7X_cBM^kR@1I}!bx=wl$%eM z^3fMV(4q3Jx{y(2l~m=}sL10j#&{g|7uH=VqT5_(^6C%QVc6VAyQBS@6OL4mI}w5K zKb3J@sr*c?%0;R9s5|x7?s{Fdm@hQxbd4`rHrkDGNaveQBhR*CczE-bYxB+8fZYmeNITBn%Ie_;X%&>8qIRKM*aW>F%<7J4B34tZP?{ zz8ubn#*q~W%YaE$Qb}$};duktts?uy(FLuRjX9RnPqkm)WM$GzV3=Ud=G=oI z=e;tgBtJ*o#d!}B*yoZBkM#8&pw;E@7hb)RIV^6YSS+D^@dsu&@aIWBagql$TuEW1iGH6}5Hw7qQoFo$ouV7VeJq6IAekF$f0Yr+CgHhq@+~UEPljV} zHKvQDNxdQqAZVs62$3*R>+=FeW+RqKNHmtXLkAkEekV%#?$aE|Uvij%TQpNLV*BT7E#<8Qk znoJEFS=g)#IJ5|Sv%#==q9BH4IpkyBj5Jz9T2H3i-(6{uY4Z!0xI)MxV%x&yh8`k! z3=TWyx=#+H`(9mc3FKypaSoh?c18i>Xz`89wB)B|?NK9gN_9Np)EzJQuh4&r7jSe< z-|ZXSaelr{XX%1CjY)Ti$owMqXT~wW&MRsBFzPA46gp<#s9x3dsI2Z@JMAeGDR*$V zf2e{{gS&9#4?;&dqIX&y%$8Dg*|&;V^@${tSB)+hC9+5eX|2m(ft)k1I6ho@)*sbf z5!FA3Jv(`*TlKxor%7nnQD5}>vt_RCq$A6IV$vX3wwj&o3J-7}|kZ%pbvGjV?wR*}wZ4~cczhY~_>G9=+^yJs_HjF zZ9aJIv>P)TTzIOD;wvsVQ~>0HId4uVMUIiwkm?YmI<}uKvDOxkCFIkuHqkNh8QICi zY{&^9bBugftnV!PZ(Yz&*1Q)QedfUg5;zvpf^vm_!rAp0Ca`|L{5!VMbauDtjXDiQ zlI^c`gXQ|GIItOEDmX;jyUor{GfQv8;rTDAx$$0nWonyxWBs~<^!~5v4G*WSx`xi@ zPP6Il1=h|Rb$3tNvXSR!Om22%A&z(gwXGMb(^=P3NS{)g9-+Lqih1;wn+H#brdh4! z350E>SfM?*?^pv(qOPI)dOnlCT^-Enm~DVIR|fk6meQIPkjx9b~`O@ z?=B@W+(44DqM_nOhj%LYD&-GuaZHxQv`js?w_vy@spp=)(xU16y+2sftaQuHpVOlH zD<($)X1Qe{+C|1$!!F_*&@a6!-s$&UInoQ!SA8_!`kz;wZ(8BdNietB|WdQ{kC>*lnU=f}u3$aM;W{<}Ck!GvAt$oagsCu^BPQB3wLx$4k((TZFLmiV( zbKXZjm<&pR{t@$vZRpR${dWHVs;x9@drbjtwP!Kvu+0wJJK1|HJWKxoNzdgh1~NuR z6^BmcCRwkbmwrffY>b}S1ol6A&^jZ>=&MEiLASQGn6&M0V-4FM5XrX&O@q-17|*F5 z)mm6$&YcCrkP(n>$$Tql-_nw_|Y_n7olWTnLCG_ppUKRG!;tX1%0K zd8XXOHIz?2q|X}0w>wglyCCJ+9=kho^fm7-SJkjZ5 z*s~jxg?25UzwRfR{{R&_FIefl9t}50x|3Jwy*5WT8)6%+?%6?gnOE|XyEc=?GmKU{ zA~}SXKqq!1ljZ}t-JavHuT}L1oY3`?^(K$_i5;z(w^(JF%FVEb!lmLb=S-3doRP<+ zWZJLcwx@fq>Ng3f=}oOGJn-q3j-or52*`UzCk``_v$*-Cm(}@gX6wXfYOuB+_nBN5 z7g}bi1lBW4Z*gw^G;>7QXxoopQCer=rIZ@{y1!9sx|FgpxC?P>a;lcPj^!m^p! zz&P#)YR#v!x`IPzGWc?{;nQi#6UXR#=k3~_ZY|&|bJI}uQ9U)IB$|X+M9sy<)l=c) z8?wY>J%A>uL!;ay$tv1~7ovXu0JPI(vD6+yC)8Q>8N87^u!BCE1DtqsMW5bATmiUe zXgT$&-Akper>9BMu9I8A97x9IFEcWZ#Yo~*2P?Nbha6(4baz??(Czx4t>m+c>8EQw zH&ls7)Sbg@o+1t!CCI6|zWU!vg5N{D(k?FAYlLfrz>?_{V`^KH$hB9DuC6XP#8^n$-UQ2fCH+^q1-Tmklk7 zg9CQo7(9>DB!4PSy#0^hYFZoJ-K26{t;xHWcuTC3Ld+Nw44@LbmxIn~y`1__PiuDF zOVWC*(p$kG7Z#TbiK0`+8`4Ge+&yu{FU+7_Q9~TItgnlEo}$z4agfIcARl9zFKuNTAiow~gk-z=($ zwd5xtk?GBRibHX4lPM^NEIR{2Z?zb%^5eK%9CoN}?!qn|{H1ZQd(bvEn?uwWjA&b! zu0MDIP^1M>*!}87xI4mz<-5=*@4$*LAi!J@D$-67g~kZuDn05Ux9UfXJuK)IN;o8U z%|b4W$&zq6??L9i5;7`nUNBTtyU0MNJF&?L)4ELUMa#jEzf_N>m|>NGLn3? zN)k+a$<7HMYWODdkUd3Dk=Ca*E}6F-x$>Sf@n0HzrWY9W`Kn@dZK%X&w+5nXj7S1@ zHSO$9Y85k|452vUx`}e5oRVl`&PII1uXBp$kGBAv9Ml+{&j?t~HW@4^9Zu7^%LW<812sgH@rQAPk&2b1{p%|d z5A~`NN)g{A<2*6qid50u_qp|$%C6@*4V(d2pkycj7$9bb3AUji^XpSXa2V|bWOl_c zqzU37SY}p3?hQ<{u1+XybEId?qjzp=pHdP)MnE)N=NMjDlVColxvIApXR$f-szT_p zur2)RoyFKs%s{9!^*R%|*HO3yatPzK0l1aRZeLz2wf*pH>^{AyVqRia4BTxenpJn? z()C$!?uYOmI|_n(gWzsr03#zlqJ+(KLmV24Y2+~|-Id1x`p|$DI+E6;H*)Vn1NX`M zQoYQHCZXY$z{MG!c7iu@K->!a(!}xuaPn^|LG+^Or&84$oo?hUa?slk%)w9->zoYH z3GMXhwDD&Std{n6hh@y}4=tP&lo86ebt8e^mHL6Dhewmb<${SOZNYX$kPm-T*biEV zMe560Z=kf)?WD8OkpALVQcHj^RmkD9{XHvR;<5fTp*kE_4Ak>~KMYoD9*$yUhGr5nbK8KDduTk{!=?@H0 z5j;-q;$6nulymub>_Ft^fJ`jbd80|D7KlqkJNS$^1o{v3t5-%yfPG1fYQ;+up@uGi}+7mB+8!(z`mg@s3F2ikBbU>YYM@Px-R)NI_wT zZ|(N0w(i;5$F&Ji(ps|0#Ta>aV>tWO`&k!a#ULu^2PE)CRLd_$(S()5f}r*p?^6jG z!3Bu-6b3;860xy-&>x zidII+Rtm=%9jm-b7G`p*fOyCEs-Ce5R{cXIM3VwQP&~sY88lYLXy!u{fT$pqB=)7^ zJXsL4k|XR0;MK*rL?$&XTRgTXD{I))AU{!(DD7g3Asd~<`IU`G(@6I#ZU|VE;Xv*B z(3mETZHuwXdS}z#yCmc4f}jNB65l~Uu1iF;>w=j^#frmfqZ4+?dZO zr?+pvG;}zIHB1nIagSe$2Vhwd+1dQvhxygUnL}n$Tn=y#db!ZEYDC#A2v%u?@-EoN zKP1=7%aLnqz0ukgAr8@;li73IHS!CH783UtaoeXW(0oWmeEm&=@? z0OKPDf<+F!GQ-obYMNcI-azuaM0r|B(*jlF9wK>%tx}gr@uj)5lS9nnn@M7DP; zBFb};HslH82a$pt1M63H4NFTp9+!V=H48cPnT@LHv9ysomOq|1##HbQ(~kAoSQ_Yi zgP>~*88rP$!S%SF_#0{MRzo3(0opd?NHPBaw!`^VFwt9E+*#V|mtxw^WtJl(ZjiJ0 z!Sdz@`Rq*{xwq3G)vjS)uhl#~MSOdS9^5;^eB!!Y-jF3vk0>*#Y`*^xY3)MJ$EH}k`;uC=8l zuul%+2^O~Fl%@rn24lq_>GTa>rwA ztQ!*(f?R>ei*8%jw&muk^%jw(U-$*I{c=mY$^2Q73kf!r$Cg4iN}vpFY#*A=8>M=d z!>Vr=qU5@1k;BFvewO4f{ise(I~-=Z2$4|h`D?%6V%oaEjVnybB5|0I06^NEhi?7( zu2(C+VtHlzyErUw?6mk)nD6C|JBDMIU_mDb)AX)bym0k;bktU`CY&IW=tY8X>Ofve z>@s-mT&`5dxfb;(eQeQd?7?DXj6a7PMhYP#B!TWtMR9Q?V^A^SS=JZaJFe`VqvP7S zT&Njpe^g4=H7mU{@Vf6((T}kD<#OF9Ck}@g{U#4`u7w}@sS<}VDT9y8*JW}2Xm`Jgrk+E<<0FL}* z``0U#Fb1F>Bm9JH`x1R$q_pijU+5l^)2?+3O+Q-G;kmvMTpiOs@J4fxK+XWgKqb_5 zO-HD@a{E}kn@#C>*lBP!&9Mc^85?=+k9=`lu2dN7dWKS=)D|0ox?8C=D^9So>#5o; zLt1N=%=fF}0!ok@0~~-bJ%vcUOQ^%q8jajS6~EW-S}WW96FH2ja~d%|RVTg%NaHoi z<#w`l{{VOnS}3&WexqkrXu4wS9Uah?_N#5AIkuWn5h6)tox;3~=OnOI0D1sV6=P1* zH2J^c{vMpPw2w^FwAtPmBCsYSh+-_HwsKgJ$T*H5KwzttrpsnJ`83f6I zGQ$H0j8`j^-1-v&Kdi#%Pqw+&F6ERtT{tb2QEomP!qEa%*Ryg5J?KB}o9itu{{T}* zSuSI}TQzwGe{@Qnzoz4lYUOgcBu}VL>w9XjX$dTmL%Zsg<6<2cFgOJ9wEC$S=B%uC z_Zov;J*+D=oH9#p=rCi!BWV8swBTfRu2(Cv26eEp%WjVD>M1osw-U&bWujpaVk6FW zsUT!?nir~0B>ZF1x-R0{*5g3BwUy-4=7m}?@q+5>#zDyEo@CjD*qRKLjF)#%qV{QYUc;Hu~G;3>%j+D^4VqIHOF{YPkd~d#> z{ZqNaVV|=vn2ZtHxm>Di`<6ek81##|XOv3oAA+qdx6*7L3EL{+_WCzIgb#}CePD<# z5KR6n-3F52q8TMYD*oxoUpje@3=iJ9T%r%DN}V@TAN+69?X*6z(Dj`sb*z?Fo;9Qi zj|SMqAPNx(zy~=a)bm+2{->#Q*G}7AX?N2t$5X|#RGF||P$eyZzyi5F@!T5aa*8}Y}eb=@1RbQ>KjR=KlPnP!4mh!R_ZHW<;dkc0u{ zIp(=srp+*T;BuHpQ|q_gRrrSm{-z*Vu97J33=xRL+2eB#+rEA&{?nwiiGSh)ROw^& zE2nAk&LUNmhCUQUfn(}P0H5-%S1E2t{HEW;vwS|}qQz721|GB*H-EM@4MDB$C-Ixl z9^4iA2iG~xS=Ke(TcNs|%F9c=lJ8G#KHhn3H6Qtld5q{9K*)F?o_z@Su2(9BKahvm zp^>&fb4%3vOQ-b?oz(1P(*bq{iTTnYrfJ`_Eaixmc#ECw5kJQkdn<+`-l(TRbjGjv zrJ~x;r}#G7wv{E@!EWX?wwJ>Vz8ro`5y0efc&=9{mk}O2Hx}>r7c9DeOtt(Y*Z%+z zQWuk6vbwv|(&ASx95F=kSRV3)cEb#J&NE9kS~iz=rG6giGg(Gp)UTzI?S~IGClLT! z*eL8h&2qU^F!e62*p~0^3zJ9F^3Rhgt(w-}Z%K>%Dg4rLAu-{*L-tZoZP^ z>R?wF5$y$ck5ayjFnK(hJ$0k$>#pBukwCFSVm_+UWB^M6+8OomhQbx z3GJY=)qaZFB}gQ*Sy=$U-a*R%I2p!B995ky*-^R926?VmD<9=R`Al7Bs9Mwamg77I z?~1hO7Ay?l20zNVT&(4S2xZ%NmQ66bXFG>#p5vASupWZBT&S<954ln~U9R#^sG^WN zJf32FtC9DvS1XD4Ak(r+ii= zMLikQI-|6RLlgeZM()CM&VK&@YUOgG(}GPqFpQ9UVxw84eZ;ZKfsB3YmCES;sp0BZ zN#!#FTP2POs@GFFi02=h+PPe#$EoG_DjA&ID9FJa*LWq7XABtUb}N<2BBR)o62Y{;@7d zmDCXpORg<6+1bQ0#JkEi3k}DQY!9^y)l9bf`sklgEVepyg#TB_a45vqEOzv`enAOBr$zO?aD(Y z0Rc0RT?TxufID&VT&`8dExY>65vW5Au8ORX#>VRN>E|rD@f4CjL&tH0Nt(@_wZB}Z znvoBsfMH`kzFpj(T$<%_yQl!M!f<#M29f)r0Ps6RDmlZNE*f3sc z^#rGB$l&pc<#MZs*FG$!CVVQeC{ETH8TYP4NssPpmCB{zYGDgT9%U%3Gr%LYb&Z)d zM_^wwfwDx3v<>iVya=sdj;EbA%-QIiVGCN^L03EB9%7@vV6SU~9ayMk-woht} znTr%8;8!b^Vtq(Fx3DUJ3Fo;rPyn|`z;f) z)W3)qS`MM7S|ya0qV5%i3bmx35M$vnB&w7ACnMsyT&FsfuU&{orZmke_oTG_YJD!y z+}>R_opH4`tf_)S;C@*KIAz64ZPB_!U1QWb3~zd?1)EN{qTz+ZZXBaGW<%^ju2(D2 za8D!t&=Jz09Tlg`4aM9MwbWs)T4D7t%H9>yj7=K<0E2ktli{=4jc9tS zUUe>;70r#5mfEyq>g`NeiQjfNg$K&qXCoZfE0yN=C}E`Q`^H12Y0@636Inwl=@XBq zMg%K@F^Loq8;?`Z%?Z2d-6|fx()8%yb+^=QM6Ntm-4k~G+h;5G$*xx_Y#@qHa*M3C zJvp!GkX>AO7PE_RtowwKllfd84{qQC^G=XhEIL++eFe?LPZgPX(O4B+jFHGBu6f!? z9~H{wL_!GsKi(zWYFfOV39a9aV(|;y7+w`C;T1jbrF^I5aZ(iFm PT&`CtYwA&G8x#N8EMl03 literal 0 HcmV?d00001 diff --git a/app/assets/images/baklava.jpeg b/app/assets/images/baklava.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..508b2e68e42aaefde6f2b086946438c846a76db3 GIT binary patch literal 70355 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

    Ct_5*>Id0MD!TY!Cl8403;lqE7>D`YBs%n zYU>E9BMrtuNc_5*(eM~ty>fXk>-}Ne|+-9Jg zQpv{9KDEqfkv@-N@m}iJI)b}p8t8!NPf?tlgXvbMya4BHfFAr2UR2t9O6Oc@wYssZ zCD<#Fp#C*fTo#ZF5mX_$f_5s*0rWgm{K3{T7!J52ifS#6$!N_MeDVW+bPt$d4B&rz ztx*gda-@D#ftf%lf=5i&sy;+A^p3$ofWL|6sx+>y6pVf~PU>0MWV$Inz*cR=!^X-t zo&Ek=a*e_$=oGW(7+iYyr%GHX$vE_^2(BIeL%7H}C+z{g&$TL)_X>mR5 zXv=ufKzEIxyV>N57G{ftsIW%T_i&v?TyA z5&_eO>r%sg@-bz8eQ%4lBH{@LhyEHn7cU~SJev+l?X>m-kF9aq z{{VzFtrF#0${}}WB9}+txW`eqx%zeVrS)lY^DTlE>B-xu%UN7!WR3wD$NvDXuf=@v zy0n{Hw<59!hdgN>(ln3~Pn*nVRV(!Yt12CF_xWz2m~eSLefkkn=*bT8p2wrw>hZ*x zknTp|kQ{FR0B7mzR6Ij_aXg-W#UT(BjxmKrJ@Nicb8-3llELVFGYqpw`k1V!1Cm6-u8TwT5+(~yW-I}?M254Bg0f5d( zKf-g4YX?nByE`V0W9D4t$R)Y!&ws64yuFIgPrr7Rpo7aK5}-4jbjP{kxZ~nm+p9;m zxs4)Li!U@zK~e4ezZ!9aW#4-j~2T3XLS z6Gpa|b7^w_0A-)#$N(3|$a;QWm5Zyi!fABz7TF<`t8

    - - + + <% end %> <% end %> diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb index b7895e6e59..73a999784e 100644 --- a/app/views/orders/show.html.erb +++ b/app/views/orders/show.html.erb @@ -1,29 +1,44 @@

    <%= "Order # #{@order.id}" %>

    -

    Order status: <%= "#{@order.status.capitalize}" %>

    -

    Order Details:

    -

    User: <%= @order.merchant_id %>

    - +

    Order Details

    + +

    Status: <%= "#{@order.status.capitalize}" %>

    +

    Created on: <%= "#{@order.created_at}" %>

    + +

    Client: <%= Merchant.find_by(id: @order.merchant_id).username %>

    Contact: <%= @order.email %>

    -

    Shipped to: <%= @order.address %> - <%= @order.zip_code %>

    + +

    Charged to card: <%= " ************#{@order.cc_number[13]}#{@order.cc_number[14]}#{@order.cc_number[15]}" %> | Expiration date: <%= @order.cc_expiration %>

    +

    Shipping information: <%= @order.address %> - <%= @order.zip_code %>

    -

    Charged to card: <%= " ************#{@order.cc_number[13]}#{@order.cc_number[14]}#{@order.cc_number[15]}" %> | Expiration date: <%= @order.cc_expiration %>

    +
    Item - <%= product.quantity %> + <%= op.quantity %> <%= format_price(product.price) %> - <%= format_price(product.quantity * product.price) %> + <%= format_price(op.quantity * product.price) %> <%= link_to "Edit", edit_orderproduct_path(op.id) %> From ff4bf500cde86e7dc989d7ca9142f9fe13b9d612 Mon Sep 17 00:00:00 2001 From: Aruna Date: Wed, 25 Apr 2018 20:11:28 -0700 Subject: [PATCH 163/252] quantity updated in cart --- app/controllers/orderproducts_controller.rb | 24 +++++++++++++++++++++ app/controllers/orders_controller.rb | 17 +++------------ 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 6fdcc61764..0a796df290 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -30,12 +30,16 @@ def create else orderproduct = Orderproduct.create_orderproduct(params['quantity'], params['product_id'], @order.id) end + end if orderproduct.save + status = :success flash[:result_text] = "#{orderproduct.quantity} #{orderproduct.product.name} added to your cart!" + reduce_inventory(orderproduct) redirect_to orderproducts_path + else status = :bad_request flash[:result_text] = "Error - products not added to your cart" @@ -48,8 +52,10 @@ def edit def update if @orderproduct.update(orderproduct_params) + #add_inventory(orderproduct) flash[:status] = :success flash[:result_text] = "Cart updated!" + reduce_inventory(orderproduct) redirect_to orderproducts_path else flash.now[:status] = :failure @@ -69,6 +75,7 @@ def destroy def clear_cart Orderproduct.where(order_id: @order.first.id).delete_all + add_inventory(orderproduct) redirect_to orderproducts_path end @@ -82,4 +89,21 @@ def find_orderproduct @orderproduct = Orderproduct.find_by(id: params[:id]) render_404 unless @orderproduct end + + def reduce_inventory(orderproduct) + @product = Product.find_by(id: orderproduct.product_id) + @product.quantity -= orderproduct.quantity + + @product.save + + end + def add_inventory(orderproduct) + #order.orderproducts.each do |orderproduct| + @product = Product.find_by(id: orderproduct.product_id) + @product.quantity += orderproduct.quantity + @product.save + + end + + end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index af24b51e61..ebbc3532d0 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -26,6 +26,7 @@ def create @order = Order.new(order_params) @order.update(status: "open") if @order.save + redirect_to order_path(@order.id) else flash[:failure] = :failure @@ -66,19 +67,7 @@ def find_order render_404 unless @order end - def reduce_inventory(order) - order.orderproducts.each do |orderproduct| - product = Product.find_by(id: orderproduct.product_id) - product.quantity -= orderproduct.quantity - product.save - end - end - def add_inventory(order) - order.orderproducts.each do |orderproduct| - product = Product.find_by(id: orderproduct.product_id) - product.quantity += orderproduct.quantity - product.save - end - end + + end From 6824e1522012fd074ea26e2642ddfcad9ab3f6a9 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 25 Apr 2018 21:45:51 -0700 Subject: [PATCH 164/252] styling --- app/assets/stylesheets/application.css | 16 +++++++++++++--- app/controllers/categories_controller.rb | 10 +++++++--- app/views/layouts/application.html.erb | 2 +- app/views/merchants/index.html.erb | 2 +- app/views/products/index.html.erb | 4 +++- app/views/products/new.html.erb | 17 ++++++++++++----- app/views/sessions/show.html.erb | 2 +- 7 files changed, 38 insertions(+), 15 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 52b1f0f17d..447eda3eb7 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -31,7 +31,15 @@ .nav-drop p { margin: 0; - padding-left: .25em; + padding-left: .2em; +} + +.submit { + background-color: #ffaa80; + border: solid thin; + width: 10em; + height: 3em; + font-weight: bold; } #login { @@ -65,6 +73,7 @@ justify-content: center; padding-top: 20px; } + .item-box { display: flex; flex-direction: row; @@ -72,7 +81,7 @@ justify-content: space-around; align-content: center; } - + .merch-container { display: grid; grid-template: @@ -99,7 +108,8 @@ } .product-container { - padding: 2em; + padding: 1.5em; + /* border: solid thin grey; */ } .product-container h4 { diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 6dd96b219b..13eecd8bce 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -1,7 +1,7 @@ class CategoriesController < ApplicationController before_action :find_category, only: [:show, :edit, :update, :destroy] before_action :find_user - + def index @categories = Category.all end @@ -17,8 +17,12 @@ def create @category = Category.new(category_params) if @category.save flash[:status] = :success - flash[:result_text] = "Successfully created #{@category.name}" - redirect_to categories_path(@category.id) + flash[:result_text] = "Successfully added #{@category.name}" + + redirect_to + new_product_path + + # categories_path(@category.id) else flash[:status] = :failure flash[:result_text] = "Could not create this category" diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 5bde9f7ec8..91c9c3752c 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -84,7 +84,7 @@ <%= link_to "View profile", user_profile_path(@user.id), class: "button" %>
  • - <%= link_to "View orders", user_products_path(@user.id) %> + <%= link_to "View orders", user_products_path(@user.id), class: "button" %>
  • diff --git a/app/views/merchants/index.html.erb b/app/views/merchants/index.html.erb index af848d4742..e086d73d20 100644 --- a/app/views/merchants/index.html.erb +++ b/app/views/merchants/index.html.erb @@ -3,7 +3,7 @@
    <% @merchants.each do |merchant| %>
    - merchant pic + merchant pic

    Username:<%= link_to merchant.username, merchant_path(merchant.id) %> diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 695541c3b1..1c8fb16a77 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,10 +1,12 @@ +

    All products

    +
    <% @products.each do |product| %>

    <%= product.name %>

    product pic + https://loremflickr.com/280/200/dessert" alt="product pic">

    Price: <%= format_price(product.price) %> diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index c8e49e1d30..506e63b88e 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -1,21 +1,28 @@ +

    Add a product

    + <%= form_for @product do |f| %> <%= f.hidden_field :product_id, value: @product.id %> - <%= f.label :name %> + <%= f.label :name, "Name: "%> <%= f.text_field :name %> - <%= f.label "price" %> + <%= f.label :price, "Price: " %> <%= f.text_field :price %> - <%= f.label :quantity %> + <%= f.label :quantity, "Quantity: " %> <%= f.text_field :quantity %> - <%= f.label :description %> + <%= f.label :description, "Description: " %> <%= f.text_area :description %> + Assign categories:
    <%= f.collection_check_boxes :category_ids, Category.all, :id, :name do |b| %> <%= b.check_box %> <%= b.label %> <% end %> - <%= f.submit %> +
    + <%= link_to "Add category", new_category_path, class: "button" %> +
    + <%= f.submit class: "submit" %> + <% end %>
    diff --git a/app/views/sessions/show.html.erb b/app/views/sessions/show.html.erb index df2e1b3613..5ff31c9840 100644 --- a/app/views/sessions/show.html.erb +++ b/app/views/sessions/show.html.erb @@ -17,7 +17,7 @@
    <%= product.name %>
    <%= product.quantity %><%= product.price %><%= format_price(product.price) %> <%= link_to "Edit Item", edit_product_path(product.id) %> <%= link_to "Delete", product_path(product.id), method: :delete %>
    #>!sWmrZ6n?}VbdD#1hD}2lz8x?DrNSug8unyVRe)G! zidbHT%+igAe!ho6{Do4gJJL}!p6zfv^I9in2O*vNmh7}OKE-yChyIhj&r^$lJ743= zH(G+>?YTyW`zK<{H(syu6`GY{C(uk(e0f+}10E5H*CvAECa*IcU-a}>WNPWE?`72A zaU^LQ%5u7X$|+xun1&8x2j3cg4^2k!7)->L$@FGWA+$$~T&pVYdM((WWMs-2KUa_d zms0{OU7n-O^*+;K-j}voQhb(=&GQRKFg}c~Ht-iV<_r^n~VY zHK>UvRTyG?+17~M?QNZXI@=Cxv_;H<`hwG%_hKD+7E=ffUpgvS$kHyWpJ{LO&){14=ZAKLuRqy;eYu)S{0WTDaxFO(hFP`V*LYK^VnonR1QSV@^@Cm&uo#m~=eUnvkqy)6vp4%UjN8#EIX@Xnfz zZ>^I#^bQ!Bo9+qXjPsY{<6cQNu{pW>c=8{Wx|(Lng1NcRc8o_);{48AH~mUfKxtwl zOO?P^!;M0+%zjM`@US3P0FY?7*YgP$lY)pc36`5_a&id1CnN(ndk0?DPvC!PvN|TA zc-E*pU-#HwW@Tjb`0U-ViuowKDnYcrw(5m=r9NP!kyi!2^*~koY*_ z9%meb9niyViAA7-kxtWSA?CC;X+g9JHzM(v-}0|J1UcYp_>W3c18vmVskLO3=ICRr zp1;<$b`eO5sXqVX)iCf=s=tEW!>8Q;0tUi@i8Y_W2e77GgN0Y3DFu(PfkYGJywmzc zNj|5NC%$1H66Dr_j+p@X%61S;dJN2sL+3_bb|UIF+BX~59z}U9!reNeHhTBcc-;GQ z$R^&RyV;5_5oTlZBmU2sx<>sCp;_5u@l|b!0SESX>tWA=%In&NX@4#6{oXCm{gfO9 zfxa6~@4c7TPgLEnZh-flYW6$zo1B*H&hNFHrlm`uU~eGw=7V?MI) zdgtpZo`S!lE$DotDWdWD^c#{TWf9zX=m0jZB@S>qEbnS=yGFDf?ZuuO1E*X+A$=%5 zv^GrINA={reoH{@p5N3}vqW>1nvo6@{$>;Q?f%_4C%BMs^G>{i3|A$^Fz27rJGj+gkq0> z^ocr++Lh1=JNcimk-{oWHZyF7mTP4ui2VZtdxX0}ND(^u%e&e^<^oYEXzc8v zoEv@Nu1y!z!H&8%<#Q%kKXtY|IVP2T{p9=iW~um}`Sj*x`^+1}HO||@K!5Y9DM4C? z8jt3Sr|S9-yMH!4F#9UFR~?I}Cc0g1O}zFt)OE#3O+IsA!&L`wTTAE09#yW&Voidc z#QB#D0b1?YOM&%tI44N!pN81Q!AxdJ+-G3Bz+L8vN0qVWs|$yp&{B_THl_z1GRL~K z1z)eD`N}btMrejUbid@h`rv)kX%2bqfiJ>>7tAdH-`hIpAOp+VWGLiEEhof|^j~8o6Q=MP0E-`(k3whu>Gyc01_6BDN+68|}CltIF+cn`p@_tx;;Qm4%$`!v&QAYz`NsR}|3 zZ0;0LhG)(;p1k_W*sdd~p6BeXV{6RB#vjuX57C^x>@FTX-)q14^*mtXyldV@_Ke6q z#Al6&2nUeJs&iA1q$Ys^{|5Kah=8>+)@yc+@ecVtaTV ziF54CTEN

    RbkNVGDL;0d=quez2e^9QO7uHOa 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 osZUzdEV*LLwh=Wv`xtld2g^C_tVs|>;W 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 WO(7uDk#k9id}4}{Fes&PKmXZRyazu3 literal 0 HcmV?d00001 diff --git a/db/seeds/products.csv b/db/seeds/products.csv index e69de29bb2..d31011b69b 100644 --- a/db/seeds/products.csv +++ b/db/seeds/products.csv @@ -0,0 +1,11 @@ +name,price,quantity,description,status,photo +Pineapple cake,10.50,12,Moist and fresh,active,pineapple_cake.jpg +Flan,5.95,20,Homemade and floppy,active, +Pistachio ice cream,5.99,12,A pint of awesome,active, +Baklava,3.50,40,Traditional pastry,active, +Lemon ice cream cake,9.95,15,Refreshing,active, +Chocolate chip cookies,6.50,100,Better than girl scout,active +Cheesecake,7.50,15,Creamy goodness,active, +Apple pie,6.60,20,Homemade freshness,active, +German chocolate cake,9.99,5,Delicious,active +Fruit bouquet,15,4,Great for sharing,active From 6ee7bfe56beeb5ce3f5ba5a6fb67aca3b9f87636 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 26 Apr 2018 15:06:39 -0700 Subject: [PATCH 173/252] images added --- db/seeds/products.csv | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/db/seeds/products.csv b/db/seeds/products.csv index d31011b69b..b95149e85d 100644 --- a/db/seeds/products.csv +++ b/db/seeds/products.csv @@ -1,11 +1,11 @@ name,price,quantity,description,status,photo Pineapple cake,10.50,12,Moist and fresh,active,pineapple_cake.jpg -Flan,5.95,20,Homemade and floppy,active, -Pistachio ice cream,5.99,12,A pint of awesome,active, -Baklava,3.50,40,Traditional pastry,active, -Lemon ice cream cake,9.95,15,Refreshing,active, -Chocolate chip cookies,6.50,100,Better than girl scout,active -Cheesecake,7.50,15,Creamy goodness,active, -Apple pie,6.60,20,Homemade freshness,active, -German chocolate cake,9.99,5,Delicious,active -Fruit bouquet,15,4,Great for sharing,active +Flan,5.95,20,Homemade and floppy,active,flan.jpg +Pistachio ice cream,5.99,12,A pint of awesome,active,pistachio_ice_cream.jpg +Baklava,3.50,40,Traditional pastry,active,baklava.jpg +Lemon ice cream cake,9.95,15,Refreshing,active,lemon_ice_cream.jpg +Chocolate chip cookies,6.50,100,Better than girl scout,active,choco_cookies.jpg +Cheesecake,7.50,15,Creamy goodness,active,cheesecake.jpg +Apple pie,6.60,20,Homemade freshness,active,apple_pie.jpg +German chocolate cake,9.99,5,Delicious,active,german_choco_cake.jpg +Fruit bouquet,15,4,Great for sharing,active,fruit_bouquet.jpg From 3196e31cb3b3571b1d071d78f322fedc03f3b152 Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 26 Apr 2018 15:38:06 -0700 Subject: [PATCH 174/252] added link to merchants add acart --- app/views/merchants/show.html.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index d268d61220..56f26fc069 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -13,8 +13,8 @@ Stock: <%= product.quantity %>

    -

    - Add to cart +

    + <%=link_to "Add a cart",orderproducts_path, class: 'button' %>

    From eb554448f568588a5381bd4c4e85601e17fbeef1 Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 26 Apr 2018 15:38:27 -0700 Subject: [PATCH 175/252] added seeds file --- app/controllers/orderproducts_controller.rb | 20 ++++---- db/seeds.rb | 55 ++++++++++++--------- db/seeds/categories.csv | 6 +++ db/seeds/merchants.csv | 5 ++ db/seeds/products.csv | 1 + 5 files changed, 55 insertions(+), 32 deletions(-) create mode 100644 db/seeds/categories.csv diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 6daac3b174..4039e7627e 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -67,6 +67,7 @@ def update def destroy if @orderproduct.destroy + add_inventory(@orderproduct) flash[:status] = :success flash[:result_text] = "Item successfully removed from your cart!" redirect_to orderproducts_path @@ -74,8 +75,9 @@ def destroy end def clear_cart + add_inventory(@orderproduct) Orderproduct.where(order_id: @order.first.id).delete_all - #add_inventory(@order) + redirect_to orderproducts_path end @@ -97,14 +99,14 @@ def reduce_inventory(orderproduct) @product.save end - # def add_inventory(order) - # # @orders.each do |orderproduct| - # @product = Product.find_by(id: orderproduct.product_id) - # @product.quantity += orderproduct.quantity - # @product.save - # end - # - # end + def add_inventory(orderproduct) + @orders.orderproducts.each do |orderproduct| + @product = Product.find_by(id: orderproduct.product_id) + @product.quantity += orderproduct.quantity + @product.save + end + + end end diff --git a/db/seeds.rb b/db/seeds.rb index d9651f57df..6780c2becc 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -10,35 +10,44 @@ require 'faker' # Categories: -puts "\n" -10.times do |t| - category = Category.create(name: Faker::Dessert.topping) - until category.name do - category = Category.create!(name: Faker::Dessert.topping) - end - puts "#{category.name} created!" -end -p "**Created #{Category.count} categories**" +CATEGORIES_FILE = Rails.root.join('db', 'seeds', 'categories.csv') + +CSV.foreach(CATEGORIES_FILE, :headers => true) do |row| +categories = Category.create(name: row['name']) +puts "Category #{categories.id} created " +end # Mercahnts -puts "\n" -10.times do |t| - merchant = Merchant.create(username: "#{Faker::Name.first_name}#{t}", email: Faker::Internet.email ) - until merchant.username do - merchant = Merchant.create!(username: "#{Faker::Name.name}#{t}", email: Faker::Internet.email ) - end - puts "#{merchant.username} created!" +MERCHANT_FILE = Rails.root.join('db', 'seeds', 'merchants.csv') +puts "Loading raw Merchant data from #{MERCHANT_FILE}" + + +CSV.foreach(MERCHANT_FILE, :headers => true) do |row| + merchant = Merchant.create(username:row['username'],email:row['email']) +puts "Merchant #{merchant.id} created " +puts "#{merchant.username} created in the category" end -p "**Created #{Merchant.count} merchants**" -# Products -puts "\n" -10.times do |t| - product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.order("RANDOM()").first] , quantity: 2, status: "active",merchant_id: Merchant.order("RANDOM()").first.id ) - puts "#{product.name} created in the category: #{product.categories.first.name}" + +# Merchants +PRODUCT_FILE = Rails.root.join('db', 'seeds', 'products.csv') +puts "Loading raw Product data from #{PRODUCT_FILE}" + + +CSV.foreach(PRODUCT_FILE, :headers => true) do |row| + product = Product.create(name:row['name'],price:row['price'],quantity:row['quantity'],description:row['description'],photo:row['photo'],status:row['status']) +puts "Product #{product.id} created " +puts "#{product.name} created in the category: #{product.categories.first.name}" end -p "**Created #{Product.count} desserts**" + + +# puts "\n" +# 10.times do |t| +# product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.order("RANDOM()").first] , quantity: 2, status: "active",merchant_id: Merchant.order("RANDOM()").first.id ) +# puts "#{product.name} created in the category: #{product.categories.first.name}" +# +# p "**Created #{Product.count} desserts**" # Reviews diff --git a/db/seeds/categories.csv b/db/seeds/categories.csv new file mode 100644 index 0000000000..bb932e7720 --- /dev/null +++ b/db/seeds/categories.csv @@ -0,0 +1,6 @@ +name +Pasteries +Pies +Cookies +Puddings +Tarts diff --git a/db/seeds/merchants.csv b/db/seeds/merchants.csv index e69de29bb2..d69caa9394 100644 --- a/db/seeds/merchants.csv +++ b/db/seeds/merchants.csv @@ -0,0 +1,5 @@ +username,email +Nick,nick@live.com +Devin,devin@hotmail.com +Atul,atul76@gmail.com +Lucy,lucy@gmail.com diff --git a/db/seeds/products.csv b/db/seeds/products.csv index e69de29bb2..c6cb2b5b8c 100644 --- a/db/seeds/products.csv +++ b/db/seeds/products.csv @@ -0,0 +1 @@ +name,price,quantity,description,status,photo From 6261f07516eb63045b8433aa23b372a05e0b92cf Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 26 Apr 2018 16:11:02 -0700 Subject: [PATCH 176/252] Fixed reviews display method, added revenue page, 'my products' showing now on profile page and profile page, also nav-bar on logged-in user --- app/assets/stylesheets/application.css | 19 +++++++ app/controllers/orders_controller.rb | 14 ++--- app/views/layouts/application.html.erb | 9 ++-- app/views/orders/index.html.erb | 4 +- app/views/orders/show.html.erb | 39 +++++++++----- app/views/products/show.html.erb | 33 ++++++++---- app/views/reviews/new.html.erb | 8 +-- app/views/sessions/index.html.erb | 71 ++++++++++++++------------ app/views/sessions/show.html.erb | 10 ++-- 9 files changed, 132 insertions(+), 75 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 595c78db07..df130962b8 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -170,9 +170,28 @@ th { table { width: 80%; + margin: 80px; + margin-left: 10%; } +/* tr:hover { + background-color: #f5f5f5; +} */ + .home-title { padding-top: 2em; padding-bottom: 2em; } + +.user-profile, .user-products-view { + text-align: center; +} + +#review { + flex-direction: row; +} + +#review li { + list-style: none; + padding: 8px; +} diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index ebbc3532d0..5874754e9c 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -26,7 +26,6 @@ def create @order = Order.new(order_params) @order.update(status: "open") if @order.save - redirect_to order_path(@order.id) else flash[:failure] = :failure @@ -39,16 +38,19 @@ def update # TODO: check conditions of when will update it to to cancel or when will be updating it to checkout # If canceling an order: unless @order.status == "open" - flash[:message] = "Order #{@order} was canceled." if @order.update(status: "canceled") + status = :success + flash[:result_text] = "Order #{@order} was canceled." if @order.update(status: "canceled") redirect_to order_path(@order.id) else # _checkout_form comes here if @order.update(order_params) # @order.update(status: "paid") - flash[:message] = "Checkout successful" + status = :success + flash[:result_text] = "Checkout for order ##{@order.id} was successful." redirect_to orders_path else - flash[:message] = "Something went wrong." - render :edit + status = :bad_request + flash[:result_text] = "Error - Cart could not be checked out." + render :edit, status: status end end end @@ -68,6 +70,6 @@ def find_order end - + end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 91c9c3752c..652b231721 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -78,13 +78,16 @@ <%= link_to "Logged in as #{@user.username}", user_profile_path(@user), class: "button" %> diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb index 7ed1ac07db..7b8e476678 100644 --- a/app/views/orders/index.html.erb +++ b/app/views/orders/index.html.erb @@ -13,8 +13,8 @@ <% @orders.each do |order| %> <% unless order.status == "open" %>
    <%= link_to "Order ##{order.id}", order_path(order.id) %>
    <%= order.status %>put order.total<%= %><%= order.status.capitalize %><%= format_price(order.total) %>
    + + + + + + + <% @order.orderproducts.each do |op| %> + <% p = Product.find_by(id: op.product_id) %> + + + + + <% end %> +
    ItemQuantityPrice
    <%= link_to p.name, product_path(p.id) %><%= op.quantity %><%= format_price(p.price) %>
    + -

    Order Items:

    -
      - <% @order.products do |product| %> -
    • <%= product.name %>
    • -
    -<% end %>
    + <% unless @order.status == "canceled"%> <%= link_to "Cancel this order", order_path(@order.id), method: :patch, :class => "button"%> + <% end %>
    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 00187efc2b..440ae2198a 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -9,7 +9,11 @@
    + <% if @product.quantity == 0 %> +

    Product out of Stock

    + <% else %>

    Stock: <%= @product.quantity %>

    + <% end %>

    Price: <%= format_price(@product.price) %>

    Description: @@ -20,6 +24,7 @@ <% end %>

    + <% if @product.quantity > 0%>
    <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> <%= f.label :quantity %> @@ -28,7 +33,7 @@ <%= f.submit "Add to cart", class: "button" %> <% end %>
    - + <% end %>

    Ratings Summary

    @@ -37,23 +42,33 @@

    <%=link_to "Add review", new_product_review_path(@product.id), class: 'button' %>

    + + <% if @product.reviews.empty? %>

    Be the first to review!

    + <%else %> +
    + +
    +
      - <% @product.reviews.each do |review| %> -
    • - <%review.rating.times do %> - <%= "🍦" %> - <% end %> -

    • - <%= review.comment %> + <% @product.reviews.length.times do |i| %> +
    • Review <%= "#{i+1}: " %><%="🍦" * @product.reviews[i].rating %>
    • + + <% if @product.reviews[i].comment && @product.reviews[i].comment.length > 0%> +
    • Comment: "<%= @product.reviews[i].comment %>"
    • + <%else %> +
    • No comments
    • + <%end %> <%end %>
    <% end %> -
    + + + diff --git a/app/views/reviews/new.html.erb b/app/views/reviews/new.html.erb index 10cc5cc3bb..37be7425d4 100644 --- a/app/views/reviews/new.html.erb +++ b/app/views/reviews/new.html.erb @@ -4,15 +4,15 @@ <%= f.hidden_field :product_id, value: @product.id %> <%= f.label :rating %>
    - <%= f.radio_button(:rating, 5) %> + <%= f.radio_button(:rating, 1) %> - <%= f.radio_button(:rating, 4) %> + <%= f.radio_button(:rating, 2) %> <%= f.radio_button(:rating, 3) %> - <%= f.radio_button(:rating, 2) %> + <%= f.radio_button(:rating, 4) %> - <%= f.radio_button(:rating, 1) %> + <%= f.radio_button(:rating, 5) %>
    diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index 3f9acb8ff5..121a39ace6 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -1,39 +1,45 @@ -

    Sessions#index

    + @@ -43,5 +49,6 @@ + diff --git a/app/views/sessions/show.html.erb b/app/views/sessions/show.html.erb index 5ff31c9840..edae6b624d 100644 --- a/app/views/sessions/show.html.erb +++ b/app/views/sessions/show.html.erb @@ -1,12 +1,8 @@ -

    Sessions#show

    -

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

    - -

    <%= @user.username%> products

    <% unless @user_products.first.nil? %> - +
    @@ -19,12 +15,12 @@ - + <% end %>
    Item Quantity<%= product.quantity %> <%= format_price(product.price) %> <%= link_to "Edit Item", edit_product_path(product.id) %><%= link_to "Delete", product_path(product.id), method: :delete %><%= link_to "Retire Item", product_path(product.id), method: :delete %>
    <% else %> -

    You have no products for sale.

    +

    You have no products for sale.

    <% end %>

    <%= link_to("Add a Product", new_product_path, :class => "button") %>

    From 18d5f65aa00713342488bcabc192f0ba72f71da6 Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 26 Apr 2018 16:16:59 -0700 Subject: [PATCH 177/252] working on seed file --- app/views/products/show.html.erb | 3 ++- db/seeds.rb | 13 ++----------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index bd0aeb1352..995ac82c3e 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -4,6 +4,7 @@
    @@ -24,7 +25,7 @@
    <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> <%= f.label :quantity %> - <%= f.select :quantity, options_for_select(1..@product.quantity)%> + <%= f.select :quantity, options_for_select(1..@product.quantity),:style => "width:250px"%> <%= f.hidden_field :product_id, value: @product.id %> <%= f.submit "Add to cart", class: "button" %> <% end %> diff --git a/db/seeds.rb b/db/seeds.rb index 6780c2becc..82089db7b8 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -36,20 +36,11 @@ CSV.foreach(PRODUCT_FILE, :headers => true) do |row| - product = Product.create(name:row['name'],price:row['price'],quantity:row['quantity'],description:row['description'],photo:row['photo'],status:row['status']) + product = Product.create(name:row['name'],price:row['price'],quantity:row['quantity'],description:row['description'],status:row['status'],photo:row['photo']) puts "Product #{product.id} created " -puts "#{product.name} created in the category: #{product.categories.first.name}" +#puts "#{product.name} created in the category: #{product.categories.first.name}" end - -# puts "\n" -# 10.times do |t| -# product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.order("RANDOM()").first] , quantity: 2, status: "active",merchant_id: Merchant.order("RANDOM()").first.id ) -# puts "#{product.name} created in the category: #{product.categories.first.name}" -# -# p "**Created #{Product.count} desserts**" - - # Reviews REVIEW_FILE = Rails.root.join('db','seeds', 'reviews.csv') CSV.foreach(REVIEW_FILE, :headers => true) do |row| From 020839fdd088adef2776e63e4f816e30700969cb Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 26 Apr 2018 16:18:07 -0700 Subject: [PATCH 178/252] blah --- Gemfile.lock | 8 +- app/controllers/products_controller.rb | 2 +- app/helpers/application_helper.rb | 6 +- app/views/products/show.html.erb | 3 +- bin/bundle | 106 ++++++++++++++++++++++++- bin/byebug | 29 +++++++ bin/coderay | 29 +++++++ bin/dotenv | 29 +++++++ bin/listen | 29 +++++++ bin/nokogiri | 29 +++++++ bin/pry | 29 +++++++ bin/puma | 29 +++++++ bin/pumactl | 29 +++++++ bin/rackup | 29 +++++++ bin/rails | 34 ++++++-- bin/rake | 34 ++++++-- bin/sass | 29 +++++++ bin/sass-convert | 29 +++++++ bin/scss | 29 +++++++ bin/spring | 34 +++++--- bin/sprockets | 29 +++++++ bin/thor | 29 +++++++ bin/tilt | 29 +++++++ db/seeds.rb | 24 +++--- 24 files changed, 636 insertions(+), 50 deletions(-) create mode 100755 bin/byebug create mode 100755 bin/coderay create mode 100755 bin/dotenv create mode 100755 bin/listen create mode 100755 bin/nokogiri create mode 100755 bin/pry create mode 100755 bin/puma create mode 100755 bin/pumactl create mode 100755 bin/rackup create mode 100755 bin/sass create mode 100755 bin/sass-convert create mode 100755 bin/scss create mode 100755 bin/sprockets create mode 100755 bin/thor create mode 100755 bin/tilt diff --git a/Gemfile.lock b/Gemfile.lock index ceebc22432..6fd58a4337 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -76,9 +76,9 @@ GEM concurrent-ruby (1.0.5) crass (1.0.4) debug_inspector (0.0.3) - dotenv (2.3.0) - dotenv-rails (2.3.0) - dotenv (= 2.3.0) + dotenv (2.4.0) + dotenv-rails (2.4.0) + dotenv (= 2.4.0) railties (>= 3.2, < 6.0) erubi (1.7.1) execjs (2.7.0) @@ -156,7 +156,7 @@ GEM pry (>= 0.10.4) public_suffix (3.0.2) puma (3.11.4) - rack (2.0.4) + rack (2.0.5) rack-test (1.0.0) rack (>= 1.0, < 3) rails (5.1.6) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index f81d2a8730..13bb438244 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -7,7 +7,6 @@ def root end def index - @products = find_active_products # If using this path for displaying the logged in user's products: if @user.id == params[:merchant_id].to_i @@ -16,6 +15,7 @@ def index end def show + raise end def new diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 4cb004d112..d707fe0f68 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,7 +1,11 @@ module ApplicationHelper def format_price(price) - ("" + number_to_currency(price) + "").html_safe + ("" + number_to_currency(price) + "").html_safe + end + + def add_photo(photo) + ("").html_safe end end diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index bd0aeb1352..be7e15ed7b 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -4,8 +4,7 @@
    - product pic + "/>
    diff --git a/bin/bundle b/bin/bundle index 66e9889e8b..524dfd3f2a 100755 --- a/bin/bundle +++ b/bin/bundle @@ -1,3 +1,105 @@ #!/usr/bin/env ruby -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) -load Gem.bin_path('bundler', 'bundle') +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'bundle' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "rubygems" + +m = Module.new do + module_function + + def invoked_as_script? + File.expand_path($0) == File.expand_path(__FILE__) + end + + def env_var_version + ENV["BUNDLER_VERSION"] + end + + def cli_arg_version + return unless invoked_as_script? # don't want to hijack other binstubs + return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` + bundler_version = nil + update_index = nil + ARGV.each_with_index do |a, i| + if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN + bundler_version = a + end + next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ + bundler_version = $1 || ">= 0.a" + update_index = i + end + bundler_version + end + + def gemfile + gemfile = ENV["BUNDLE_GEMFILE"] + return gemfile if gemfile && !gemfile.empty? + + File.expand_path("../../Gemfile", __FILE__) + end + + def lockfile + lockfile = + case File.basename(gemfile) + when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) + else "#{gemfile}.lock" + end + File.expand_path(lockfile) + end + + def lockfile_version + return unless File.file?(lockfile) + lockfile_contents = File.read(lockfile) + return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ + Regexp.last_match(1) + end + + def bundler_version + @bundler_version ||= begin + env_var_version || cli_arg_version || + lockfile_version || "#{Gem::Requirement.default}.a" + end + end + + def load_bundler! + ENV["BUNDLE_GEMFILE"] ||= gemfile + + # must dup string for RG < 1.8 compatibility + activate_bundler(bundler_version.dup) + end + + def activate_bundler(bundler_version) + if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0") + bundler_version = "< 2" + end + gem_error = activation_error_handling do + gem "bundler", bundler_version + end + return if gem_error.nil? + require_error = activation_error_handling do + require "bundler/version" + end + return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION)) + warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`" + exit 42 + end + + def activation_error_handling + yield + nil + rescue StandardError, LoadError => e + e + end +end + +m.load_bundler! + +if m.invoked_as_script? + load Gem.bin_path("bundler", "bundle") +end diff --git a/bin/byebug b/bin/byebug new file mode 100755 index 0000000000..5fbc94f312 --- /dev/null +++ b/bin/byebug @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'byebug' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("byebug", "byebug") diff --git a/bin/coderay b/bin/coderay new file mode 100755 index 0000000000..f37ff7395a --- /dev/null +++ b/bin/coderay @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'coderay' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("coderay", "coderay") diff --git a/bin/dotenv b/bin/dotenv new file mode 100755 index 0000000000..d37a5ed716 --- /dev/null +++ b/bin/dotenv @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'dotenv' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("dotenv", "dotenv") diff --git a/bin/listen b/bin/listen new file mode 100755 index 0000000000..c3f9d35065 --- /dev/null +++ b/bin/listen @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'listen' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("listen", "listen") diff --git a/bin/nokogiri b/bin/nokogiri new file mode 100755 index 0000000000..cc5fb98dde --- /dev/null +++ b/bin/nokogiri @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'nokogiri' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("nokogiri", "nokogiri") diff --git a/bin/pry b/bin/pry new file mode 100755 index 0000000000..f1beb54b4e --- /dev/null +++ b/bin/pry @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'pry' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("pry", "pry") diff --git a/bin/puma b/bin/puma new file mode 100755 index 0000000000..7835c24f19 --- /dev/null +++ b/bin/puma @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'puma' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("puma", "puma") diff --git a/bin/pumactl b/bin/pumactl new file mode 100755 index 0000000000..42afaec234 --- /dev/null +++ b/bin/pumactl @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'pumactl' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("puma", "pumactl") diff --git a/bin/rackup b/bin/rackup new file mode 100755 index 0000000000..0f4c5cea6b --- /dev/null +++ b/bin/rackup @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rackup' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rack", "rackup") diff --git a/bin/rails b/bin/rails index 5badb2fde0..6065ef071e 100755 --- a/bin/rails +++ b/bin/rails @@ -1,9 +1,29 @@ #!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError => e - raise unless e.message.include?('spring') +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rails' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end end -APP_PATH = File.expand_path('../config/application', __dir__) -require_relative '../config/boot' -require 'rails/commands' + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("railties", "rails") diff --git a/bin/rake b/bin/rake index d87d5f5781..ea0e2936bf 100755 --- a/bin/rake +++ b/bin/rake @@ -1,9 +1,29 @@ #!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError => e - raise unless e.message.include?('spring') +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rake' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end end -require_relative '../config/boot' -require 'rake' -Rake.application.run + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rake", "rake") diff --git a/bin/sass b/bin/sass new file mode 100755 index 0000000000..2802b47c37 --- /dev/null +++ b/bin/sass @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'sass' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("sass", "sass") diff --git a/bin/sass-convert b/bin/sass-convert new file mode 100755 index 0000000000..c8a84ec387 --- /dev/null +++ b/bin/sass-convert @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'sass-convert' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("sass", "sass-convert") diff --git a/bin/scss b/bin/scss new file mode 100755 index 0000000000..adbfa6f0af --- /dev/null +++ b/bin/scss @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'scss' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("sass", "scss") diff --git a/bin/spring b/bin/spring index fb2ec2ebb4..0791b502d9 100755 --- a/bin/spring +++ b/bin/spring @@ -1,17 +1,29 @@ #!/usr/bin/env ruby +# frozen_string_literal: true -# This file loads spring without using Bundler, in order to be fast. -# It gets overwritten when you run the `spring binstub` command. +# +# This file was generated by Bundler. +# +# The application 'spring' is installed as part of a gem, and +# this file is here to facilitate running it. +# -unless defined?(Spring) - require 'rubygems' - require 'bundler' +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) - 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' +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") end end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("spring", "spring") diff --git a/bin/sprockets b/bin/sprockets new file mode 100755 index 0000000000..510e030040 --- /dev/null +++ b/bin/sprockets @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'sprockets' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("sprockets", "sprockets") diff --git a/bin/thor b/bin/thor new file mode 100755 index 0000000000..22fe98f0fc --- /dev/null +++ b/bin/thor @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'thor' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("thor", "thor") diff --git a/bin/tilt b/bin/tilt new file mode 100755 index 0000000000..dd94b340cc --- /dev/null +++ b/bin/tilt @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'tilt' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("tilt", "tilt") diff --git a/db/seeds.rb b/db/seeds.rb index 6780c2becc..cc60404076 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -12,35 +12,37 @@ # Categories: CATEGORIES_FILE = Rails.root.join('db', 'seeds', 'categories.csv') - CSV.foreach(CATEGORIES_FILE, :headers => true) do |row| categories = Category.create(name: row['name']) puts "Category #{categories.id} created " end + # Mercahnts MERCHANT_FILE = Rails.root.join('db', 'seeds', 'merchants.csv') puts "Loading raw Merchant data from #{MERCHANT_FILE}" - CSV.foreach(MERCHANT_FILE, :headers => true) do |row| merchant = Merchant.create(username:row['username'],email:row['email']) puts "Merchant #{merchant.id} created " puts "#{merchant.username} created in the category" end - - -# Merchants +# Products PRODUCT_FILE = Rails.root.join('db', 'seeds', 'products.csv') puts "Loading raw Product data from #{PRODUCT_FILE}" - CSV.foreach(PRODUCT_FILE, :headers => true) do |row| - product = Product.create(name:row['name'],price:row['price'],quantity:row['quantity'],description:row['description'],photo:row['photo'],status:row['status']) + product = Product.create(name:row['name'],price:row['price'],quantity:row['quantity'],description:row['description'],status:row['status'],photo:row['photo']) puts "Product #{product.id} created " puts "#{product.name} created in the category: #{product.categories.first.name}" end +# Reviews +REVIEW_FILE = Rails.root.join('db','seeds', 'reviews.csv') +CSV.foreach(REVIEW_FILE, :headers => true) do |row| + review = Review.create(rating: row['rating'], product_id: row['product_id']) + puts "Review #{review.id} created with rating #{review.rating}" +end # puts "\n" # 10.times do |t| @@ -48,11 +50,3 @@ # puts "#{product.name} created in the category: #{product.categories.first.name}" # # p "**Created #{Product.count} desserts**" - - -# Reviews -REVIEW_FILE = Rails.root.join('db','seeds', 'reviews.csv') -CSV.foreach(REVIEW_FILE, :headers => true) do |row| - review = Review.create(rating: row['rating'], product_id: row['product_id'] ) - puts "Review #{review.id} created with rating #{review.rating}" -end From d414f1b9cf1181b0dda87c9937fa05b49b8f1598 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 26 Apr 2018 16:28:19 -0700 Subject: [PATCH 179/252] Fixed how the seed.rb was reding the csv file, creating a random category for products now . --- app/views/products/show.html.erb | 6 ++++-- db/seeds.rb | 20 +++++--------------- db/seeds/reviews.csv | 10 +++++----- 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 1cf729d138..83c4cbb6eb 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -60,10 +60,12 @@ <% if @product.reviews[i].comment && @product.reviews[i].comment.length > 0%>
  • Comment: "<%= @product.reviews[i].comment %>"
  • - <%else %> -
  • No comments
  • + <%else %> +
  • No comments
  • <%end %> <%end %> <% end %>
    + +
    diff --git a/db/seeds.rb b/db/seeds.rb index 6780c2becc..62b1e6793a 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -12,16 +12,16 @@ # Categories: CATEGORIES_FILE = Rails.root.join('db', 'seeds', 'categories.csv') - CSV.foreach(CATEGORIES_FILE, :headers => true) do |row| categories = Category.create(name: row['name']) puts "Category #{categories.id} created " end + + # Mercahnts MERCHANT_FILE = Rails.root.join('db', 'seeds', 'merchants.csv') puts "Loading raw Merchant data from #{MERCHANT_FILE}" - CSV.foreach(MERCHANT_FILE, :headers => true) do |row| merchant = Merchant.create(username:row['username'],email:row['email']) puts "Merchant #{merchant.id} created " @@ -29,27 +29,17 @@ end - -# Merchants +# Products PRODUCT_FILE = Rails.root.join('db', 'seeds', 'products.csv') puts "Loading raw Product data from #{PRODUCT_FILE}" - CSV.foreach(PRODUCT_FILE, :headers => true) do |row| - product = Product.create(name:row['name'],price:row['price'],quantity:row['quantity'],description:row['description'],photo:row['photo'],status:row['status']) + product = Product.create!(name:row['name'],price:row['price'],quantity:row['quantity'],description:row['description'],photo:row['photo'],status:row['status'], categories: [Category.all.sample]) puts "Product #{product.id} created " -puts "#{product.name} created in the category: #{product.categories.first.name}" +# puts "#{product.name} created in the category: #{product.categories.first.name}" end -# puts "\n" -# 10.times do |t| -# product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.order("RANDOM()").first] , quantity: 2, status: "active",merchant_id: Merchant.order("RANDOM()").first.id ) -# puts "#{product.name} created in the category: #{product.categories.first.name}" -# -# p "**Created #{Product.count} desserts**" - - # Reviews REVIEW_FILE = Rails.root.join('db','seeds', 'reviews.csv') CSV.foreach(REVIEW_FILE, :headers => true) do |row| diff --git a/db/seeds/reviews.csv b/db/seeds/reviews.csv index a2686a16af..823f7b5fb8 100644 --- a/db/seeds/reviews.csv +++ b/db/seeds/reviews.csv @@ -4,8 +4,8 @@ rating,product_id,comment 3,5,bad 4,6,tasty 5,1 -6,2 -7,7 -8,8 -9,9 -10,10 +3,2 +4,7 +5,8 +2,9 +1,10 From 2cfb6b3a60126769f26a9944632aed96311b7d66 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 26 Apr 2018 16:29:26 -0700 Subject: [PATCH 180/252] seeds --- app/models/product.rb | 4 +--- app/views/products/show.html.erb | 2 +- db/seeds.rb | 9 +-------- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/app/models/product.rb b/app/models/product.rb index bf03ae1cd5..b96c3430ac 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -3,7 +3,6 @@ class Product < ApplicationRecord has_and_belongs_to_many :categories, join_table: "category_product" has_many :reviews - validates :name, presence: true, length: { minimum: 1 } validate :has_atleast_one_category validates_numericality_of :quantity, presence: true, greater_than_or_equal_to: 0 @@ -11,7 +10,6 @@ class Product < ApplicationRecord def average_rating - return "No reviews yet" if reviews.count == 0 sum = 0.0 self.reviews.each do |review| @@ -27,8 +25,8 @@ def change_status end private + def has_atleast_one_category - if categories.empty? errors.add(:categories, "must have atleat one category") end diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 69297ac998..9b66a4707b 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -7,7 +7,7 @@ "/>
    -
    +
    <% if @product.quantity == 0 %>

    Product out of Stock

    <% else %> diff --git a/db/seeds.rb b/db/seeds.rb index cc60404076..3a83772f13 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -32,7 +32,7 @@ puts "Loading raw Product data from #{PRODUCT_FILE}" CSV.foreach(PRODUCT_FILE, :headers => true) do |row| - product = Product.create(name:row['name'],price:row['price'],quantity:row['quantity'],description:row['description'],status:row['status'],photo:row['photo']) + product = Product.create!(name:row['name'],price:row['price'],quantity:row['quantity'],description:row['description'],status:row['status'],photo:row['photo']) puts "Product #{product.id} created " puts "#{product.name} created in the category: #{product.categories.first.name}" end @@ -43,10 +43,3 @@ review = Review.create(rating: row['rating'], product_id: row['product_id']) puts "Review #{review.id} created with rating #{review.rating}" end - -# puts "\n" -# 10.times do |t| -# product = Product.create!(name: Faker::Dessert.variety, price: 1, categories: [Category.order("RANDOM()").first] , quantity: 2, status: "active",merchant_id: Merchant.order("RANDOM()").first.id ) -# puts "#{product.name} created in the category: #{product.categories.first.name}" -# -# p "**Created #{Product.count} desserts**" From 9e78f490174b3c333eb0e9c06e26bceeca344512 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 26 Apr 2018 16:36:41 -0700 Subject: [PATCH 181/252] Linked each product to a merchant on seeds file. --- app/controllers/products_controller.rb | 2 +- db/seeds.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index f81d2a8730..94cfb5064d 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -10,7 +10,7 @@ def index @products = find_active_products # If using this path for displaying the logged in user's products: - if @user.id == params[:merchant_id].to_i + if @user && @user.id == params[:merchant_id].to_i @user_products = Product.where(merchant_id: @user.id).order(id: :desc) end end diff --git a/db/seeds.rb b/db/seeds.rb index 62b1e6793a..82e15ee60c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -34,7 +34,7 @@ puts "Loading raw Product data from #{PRODUCT_FILE}" CSV.foreach(PRODUCT_FILE, :headers => true) do |row| - product = Product.create!(name:row['name'],price:row['price'],quantity:row['quantity'],description:row['description'],photo:row['photo'],status:row['status'], categories: [Category.all.sample]) + product = Product.create!(name:row['name'],price:row['price'],quantity:row['quantity'],description:row['description'],photo:row['photo'],status:row['status'], categories: [Category.all.sample], merchant_id: Merchant.all.sample.id) puts "Product #{product.id} created " # puts "#{product.name} created in the category: #{product.categories.first.name}" end From 9bce9d798dd5a58f984ce81e06f7072fec7669ed Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 26 Apr 2018 16:47:47 -0700 Subject: [PATCH 182/252] Removed option of retiring a product from the user_products view, it is on the edit_product form only now. --- app/views/sessions/show.html.erb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/views/sessions/show.html.erb b/app/views/sessions/show.html.erb index edae6b624d..aa02c33736 100644 --- a/app/views/sessions/show.html.erb +++ b/app/views/sessions/show.html.erb @@ -7,7 +7,7 @@ Item Quantity Price - Options + Options <% @user_products.each do |product| %> @@ -15,7 +15,6 @@ <%= product.quantity %> <%= format_price(product.price) %> <%= link_to "Edit Item", edit_product_path(product.id) %> - <%= link_to "Retire Item", product_path(product.id), method: :delete %> <% end %> From b040671949e0a9f0b4042b60f647a352d186a1aa Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 26 Apr 2018 16:48:07 -0700 Subject: [PATCH 183/252] checking for updated stock after the user edits the quantity --- app/controllers/orderproducts_controller.rb | 2 +- app/views/layouts/application.html.erb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 417a66f36b..38dcdcb3f0 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -58,7 +58,7 @@ def edit def update if @orderproduct.update(orderproduct_params) - #reduce_inventory(orderproduct) + reduce_inventory(orderproduct) flash[:status] = :success flash[:result_text] = "Cart updated!" reduce_inventory(orderproduct) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 652b231721..f0119b683a 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -89,6 +89,7 @@
  • <%= link_to "Add a new Product", new_product_path, class: "button" %>
  • + From 8a02525cb1aa48d3439b54bc3e836bb56b4a7267 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 26 Apr 2018 16:57:03 -0700 Subject: [PATCH 184/252] Fixed orderproducts_controller#add_inventory method enable the clearcart button to work --- app/controllers/orderproducts_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index 417a66f36b..a2b32b4da0 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -106,7 +106,7 @@ def reduce_inventory(orderproduct) end def add_inventory(orderproduct) - @orders.orderproducts.each do |orderproduct| + @order.first.orderproducts.each do |orderproduct| @product = Product.find_by(id: orderproduct.product_id) @product.quantity += orderproduct.quantity @product.save From c1727088add40ec335aab7d36c28062459525b3d Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 26 Apr 2018 16:58:38 -0700 Subject: [PATCH 185/252] Changed a variable name in orderproducts --- app/controllers/orderproducts_controller.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/orderproducts_controller.rb b/app/controllers/orderproducts_controller.rb index a2b32b4da0..945607c175 100644 --- a/app/controllers/orderproducts_controller.rb +++ b/app/controllers/orderproducts_controller.rb @@ -106,9 +106,9 @@ def reduce_inventory(orderproduct) end def add_inventory(orderproduct) - @order.first.orderproducts.each do |orderproduct| - @product = Product.find_by(id: orderproduct.product_id) - @product.quantity += orderproduct.quantity + @order.first.orderproducts.each do |op| + @product = Product.find_by(id: op.product_id) + @product.quantity += op.quantity @product.save end From 58f5225e9959745815f8213e723284ae90bb8987 Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 26 Apr 2018 17:18:05 -0700 Subject: [PATCH 186/252] Added Order model conditional validation for the checkout form. --- app/controllers/orders_controller.rb | 3 +-- app/models/order.rb | 30 +++++++++++----------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 5874754e9c..1120a443ee 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -35,7 +35,6 @@ def create end def update - # TODO: check conditions of when will update it to to cancel or when will be updating it to checkout # If canceling an order: unless @order.status == "open" status = :success @@ -49,7 +48,7 @@ def update redirect_to orders_path else status = :bad_request - flash[:result_text] = "Error - Cart could not be checked out." + flash[:result_text] = "Error: Cart could not be checked out. Please complete all fields." render :edit, status: status end end diff --git a/app/models/order.rb b/app/models/order.rb index 646e30ec3b..9a025a829c 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -4,18 +4,20 @@ class Order < ApplicationRecord has_many :orderproducts has_many :products, through: :orderproducts - validates :address, presence: true, length: { in: 1..35 }, if: :checking_out? - validates :card_name, presence: true, length: { minimum: 1 }, if: :checking_out? - validates :cc_number, presence: true, length: { is: 16 }, if: :checking_out? - validates :cc_expiration, presence: true, if: :checking_out? - validates :cvv, presence: true, length: { is: 3 }, if: :checking_out? - validates :zip_code, presence: true, length: { is: 5 }, if: :checking_out? - validates :email, presence: true, - format: { with: VALID_EMAIL }, - uniqueness: { case_sensitive: false }, if: :checking_out? + with_options if: :checking_out? do |order| + validates :address, presence: true, length: { in: 1..35 } + validates :card_name, presence: true, length: { minimum: 1 } + validates :cc_number, presence: true, length: { is: 16 } + validates :cc_expiration, presence: true + validates :cvv, presence: true, length: { is: 3 } + validates :zip_code, presence: true, length: { is: 5 } + validates :email, presence: true, + format: { with: VALID_EMAIL }, + uniqueness: { case_sensitive: false } + end def checking_out? - :status == "paid" + :status == "open" end def total @@ -23,15 +25,7 @@ def total self.orderproducts.each do |op| total += op.sub_total end - return total end end - -# lass User < ApplicationRecord -# with_options if: :is_admin? do |admin| -# admin.validates :password, length: { minimum: 10 } -# admin.validates :email, presence: true -# end -# end From 9e4c4ea0974709663f98f7b5fde74678bd2984ad Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 26 Apr 2018 17:22:48 -0700 Subject: [PATCH 187/252] working on categories show and index --- app/views/categories/index.html.erb | 13 ++++++------- app/views/categories/show.html.erb | 23 ++++++++++++++++++----- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index b7354eb043..d8748f743c 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -1,12 +1,11 @@

    Categories

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

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

      +
      <% end %> -
    +
    diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index a5e810f54b..4aa21f93b4 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -1,7 +1,20 @@ <%= @category.name %> - -
      +
      <% @category.products.each do |product| %> -
    • <%= link_to product.name, product_path(product.id) %>
    • -<% end %> -
    +
    +

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

    + product pic +
    +

    + Price: <%= format_price(product.price) %> +

    + Stock: <%= product.quantity %> +

    +

    +

    + <%= link_to "Add to cart", url_for(:controller => 'orderproducts', :action => 'create', :product_id => product.id, :quantity => product.quantity), method: :post %> +

    +
    + <% end %> +
    From 1c20ea900913ad7b1dca00b00b1e382c2a332d4d Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 26 Apr 2018 17:33:48 -0700 Subject: [PATCH 188/252] Changed 'create category' button from add product to category index and started working on flash style --- app/assets/stylesheets/application.css | 3 +++ app/models/order.rb | 1 + app/views/categories/index.html.erb | 1 + app/views/layouts/application.html.erb | 3 +++ app/views/products/new.html.erb | 3 --- 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 1c03eb5c7f..252af4210c 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -213,5 +213,8 @@ background-color: #f5f5f5; .product-show-form { grid-area: text2; +} +.falsh { + } diff --git a/app/models/order.rb b/app/models/order.rb index 9a025a829c..6bdc0511d4 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -9,6 +9,7 @@ class Order < ApplicationRecord validates :card_name, presence: true, length: { minimum: 1 } validates :cc_number, presence: true, length: { is: 16 } validates :cc_expiration, presence: true + # TODO: the date should be grater than today validates :cvv, presence: true, length: { is: 3 } validates :zip_code, presence: true, length: { is: 5 } validates :email, presence: true, diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index b7354eb043..632f6d65dd 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -9,4 +9,5 @@ <% end %> + <%= link_to "Add category", new_category_path, class: "button" %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 652b231721..518f323b83 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -108,6 +108,8 @@ +
    + <% if flash[:result_text] or flash[:messages] %>
    @@ -123,6 +125,7 @@ <% end %>
    <% end %> +
    <%= yield %> diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index 506e63b88e..91f6bfd964 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -19,9 +19,6 @@ <%= b.check_box %> <%= b.label %> <% end %> -
    - <%= link_to "Add category", new_category_path, class: "button" %> -
    <%= f.submit class: "submit" %> <% end %> From 11fbd93036003be20fe89a22bc9e300a27210a14 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 26 Apr 2018 17:49:06 -0700 Subject: [PATCH 189/252] products fixing --- app/assets/stylesheets/application.css | 44 +++++++++++--------------- app/controllers/products_controller.rb | 1 - app/helpers/application_helper.rb | 4 --- app/views/categories/index.html.erb | 3 -- app/views/merchants/show.html.erb | 27 ++++++++-------- app/views/products/index.html.erb | 27 ++++++++-------- app/views/products/root.html.erb | 5 +-- app/views/products/show.html.erb | 6 ++-- 8 files changed, 53 insertions(+), 64 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 1c03eb5c7f..4c7e7f18c9 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -29,6 +29,21 @@ body { border: 0; } +#show-pic { + width: 250px; + height: 200px; +} + +#pic { + width: 150px; + height: 150px; + margin-left: auto; + margin-right: auto; + border: 0; + display: flex; + justify-content: center; +} + .nav-drop p { margin: 0; padding-left: .2em; @@ -52,7 +67,6 @@ body { margin: 0; } .top-bar { - /* background-color: #3366cc; */ background-color: #009999; border-bottom: dotted; border-bottom-color: skyblue; @@ -62,7 +76,6 @@ body { .button { background-color: white; - /* background-color: #f2f2f2; */ color: black; border: black solid thin; } @@ -126,9 +139,10 @@ strong { .product-container { padding: 1.5em; border: solid thin grey; - margin-bottom: 2em; - margin-left: .5em; - margin-right: .5em; + margin-bottom: 4em; + margin-left: 2em; + margin-right: 2em; + background-color: rgba(255, 255, 255, 0.5); } .product-container h4 { @@ -183,7 +197,6 @@ background-color: #f5f5f5; padding-bottom: 2em; } - .user-profile, .user-products-view { text-align: center; } @@ -196,22 +209,3 @@ background-color: #f5f5f5; list-style: none; padding: 8px; } -.product-show-container { - display: grid; - grid-template: - "text1" "image" - "text2" "image"; -} - -#pic { - grid-area: image; -} - -.product-show-info { - grid-area: text1; -} - -.product-show-form { - grid-area: text2; - -} diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 13bb438244..90d43f1b66 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -15,7 +15,6 @@ def index end def show - raise end def new diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index d707fe0f68..42202f45a5 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -4,8 +4,4 @@ def format_price(price) ("" + number_to_currency(price) + "").html_safe end - def add_photo(photo) - ("").html_safe - end - end diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index b7354eb043..cbd394c3b9 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -1,12 +1,9 @@ -

    Categories

      <% @categories.each do |category|%> -
    • <%= link_to category.name, category_path(category.id) %>
    • - <% end %>
    diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index 56f26fc069..580b7deb32 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -4,19 +4,20 @@ <% Product.where(merchant_id: @merchant.id).each do |product| %>

    <%= product.name %>

    - product pic -
    + + <%= image_tag(product.photo) %> + +
    +

    + Price: <%= format_price(product.price) %>

    - Price: <%= format_price(product.price) %> -

    - Stock: <%= product.quantity %> -

    + Stock: <%= product.quantity %>

    -

    - <%=link_to "Add a cart",orderproducts_path, class: 'button' %> -

    -
    +

    +

    + <%=link_to "Add a cart",orderproducts_path, class: 'button' %> +

    - <% end %> - +
    + <% end %> + diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 3305da927f..c17a4c42ec 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -5,20 +5,21 @@ <% @products.each do |product| %>

    <%= product.name %>

    - product pic -
    +
    + <%= image_tag(product.photo) %> +
    +
    +

    + Price: <%= format_price(product.price) %>

    - Price: <%= format_price(product.price) %> -

    - Stock: <%= product.quantity %> -

    -

    -

    - <%= link_to "Add to cart", url_for(:controller => 'orderproducts', :action => 'create', :product_id => product.id, :quantity => product.quantity), method: :post %> + Stock: <%= product.quantity %>

    -
    +

    +

    + <%= link_to "Add to cart", url_for(:controller => 'orderproducts', :action => 'create', :product_id => product.id, :quantity => product.quantity), method: :post %> +

    - <% end %> - +
    + <% end %> + diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index f67190c386..e817e9ad5b 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -4,8 +4,9 @@
    <% @products.each do |product| %>
    - product pic +
    + <%= image_tag(product.photo) %> +
    <%= link_to product.name, product_path(product.id) %>
    Price: <%= format_price(product.price) %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index be8837a216..e074c0da2b 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -3,9 +3,9 @@

    <%= @product.name %> details

    -
    - "/> -
    +
    + <%= image_tag(@product.photo) %> +
    <% if @product.quantity == 0 %> From afb45627b9fd0f659bf942a9a8d46542e9a5c13a Mon Sep 17 00:00:00 2001 From: LetiTran Date: Thu, 26 Apr 2018 20:09:39 -0700 Subject: [PATCH 190/252] Updated some of the test's fixtures --- app/models/product.rb | 2 +- app/views/categories/show.html.erb | 2 ++ test/fixtures/merchants.yml | 8 ++++---- test/fixtures/orderproducts.yml | 4 ++++ test/fixtures/orders.yml | 21 +++++++++++++++---- test/fixtures/products.yml | 33 ++++++++++++++++++++++++------ test/models/order_test.rb | 12 +++++------ test/models/product_test.rb | 10 +++++++++ 8 files changed, 71 insertions(+), 21 deletions(-) diff --git a/app/models/product.rb b/app/models/product.rb index b96c3430ac..cf01e8e314 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -25,7 +25,7 @@ def change_status end private - + def has_atleast_one_category if categories.empty? errors.add(:categories, "must have atleat one category") diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 4aa21f93b4..fd54e45e08 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -1,4 +1,6 @@ <%= @category.name %> + +
    <% @category.products.each do |product| %>
    diff --git a/test/fixtures/merchants.yml b/test/fixtures/merchants.yml index 058f8271fb..9fafd624f7 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: merchant-one +atul: + username: Atul email: hello@hello.com provider: github uid: 1222 -two: - username: merchant-two +lucy: + username: Lucy email: goodbye@goodbye.com provider: github uid: 22222 diff --git a/test/fixtures/orderproducts.yml b/test/fixtures/orderproducts.yml index 6609c00aa6..ea2005e57f 100644 --- a/test/fixtures/orderproducts.yml +++ b/test/fixtures/orderproducts.yml @@ -2,6 +2,10 @@ one: quantity: 1 + product_id: products(:candy).id + order_id: orders(:paid).id two: quantity: 1 + product_id: products(:cake).id + order_id: orders(:paid).id diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index 0e82ca0b50..e536298cf6 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 -one: - status: Paid +paid: + status: paid email: some_person@testing.com address: 123 Fake addres, Faketown card_name: Fake Buyer @@ -9,9 +9,10 @@ one: cc_expiration: 2018-04-19 cvv: 1234 zip_code: 98010 + merchant_id: merchants(:lucy).id -two: - status: Open +open: + status: open email: random_person@testing.com address: 456 Fake addres, Faketown card_name: Second Fake Buyer @@ -19,3 +20,15 @@ two: cc_expiration: 2018-04-19 cvv: 4567 zip_code: 98000 + merchant_id: merchants(:atul).id + +canceled: + status: canceled + email: random_person@testing.com + address: 456 Fake addres, Faketown + card_name: Second Fake Buyer + cc_number: MyString + cc_expiration: 2018-04-19 + cvv: 4567 + zip_code: 98000 + merchant_id: merchants(:atul).id diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index 9af4a54fa9..f289a1a16e 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -2,10 +2,31 @@ candy: name: Candy - price: 10 - quantity: 1 + price: 9.99 + quantity: 7 + description: Great for sharing + merchant_id: mercahts(:atul).id + # orderproduct_id: + status: active + photo: fruit_bouquet.jpg -two: - name: MyString - price: 1 - quantity: 1 + +cake: + name: Cake + price: 5.95 + quantity: 20 + description: Delicious + merchant_id: mercahts(:lucy).id + # orderproduct_id: + status: active + photo: german_choco_cake.jpg + +flan: + name: Flan + price: 13 + quantity: 9 + description: Homemade and floppy + merchant_id: mercahts(:lucy).id + # orderproduct_id: + status: retired + photo: flan.jpg diff --git a/test/models/order_test.rb b/test/models/order_test.rb index 8999dfc53d..d3e484d0cd 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -1,8 +1,7 @@ require "test_helper" describe Order do - let(:order) { Order.new address: "123, Fake address", card_name: "A name", cc_number: "1234567891234567", cc_expiration: Date.new(2001,2) , cvv: "123", zip_code: "98005", email: "email@test.com" } - + let(:order) { Order.new address: "123, Fake address", card_name: "A name", cc_number: "1234567891234567", cc_expiration: Date.new(2001,2) , cvv: "123", zip_code: "98005", email: "email@test.com", merchant_id: merchants(:lucy).id } describe 'validations' do it "must be valid" do @@ -191,11 +190,12 @@ end describe "relations" do - it "has a list of products" do - order.must_respond_to :products + it "has a list of orderproducts" do + + order.must_respond_to :orderproducts - order.products.each do |product| - product.must_be_kind_of Product + order.orderproducts.each do |orderproduct| + orderproduct.must_be_kind_of Orderproduct end end end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index 4b3ba36e96..d0b86484d1 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -86,3 +86,13 @@ end end + + + +# TODO +# Name must be present +# Name must be unique +# Price must be present +# Price must be a number +# Price must be greater than 0 +# Product must belong to a User From 333b6d22881cef833f2161c944f14b3683dc89b0 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 26 Apr 2018 20:19:46 -0700 Subject: [PATCH 191/252] h1 and products styling --- app/assets/stylesheets/application.css | 17 ++-- app/views/layouts/application.html.erb | 29 ++++--- app/views/products/root.html.erb | 2 +- app/views/products/show.html.erb | 109 +++++++++++++------------ db/seeds/products.csv | 2 +- 5 files changed, 83 insertions(+), 76 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index bbfd5c770a..4c09afcd06 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -32,16 +32,23 @@ body { #show-pic { width: 250px; height: 200px; + margin-left: auto; + margin-right: auto; + border: 0; + display: flex; + justify-content: center; + border: thin solid grey; } #pic { - width: 150px; + width: 200px; height: 150px; margin-left: auto; margin-right: auto; border: 0; display: flex; justify-content: center; + border: thin solid grey; } .nav-drop p { @@ -81,10 +88,10 @@ body { } h1 { font-family: 'Pacifico', cursive; - padding-bottom: 20px; + padding-bottom: 40px; display: flex; justify-content: center; - padding-top: 20px; + padding-top: 40px; } .item-box { @@ -192,7 +199,7 @@ table { background-color: #f5f5f5; } */ -.home-title { +#home-title { padding-top: 2em; padding-bottom: 2em; } @@ -228,6 +235,6 @@ background-color: #f5f5f5; grid-area: text2; } -.falsh { +.flash { } diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 278875e46f..b3902190d0 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -75,7 +75,7 @@
    <%= yield %> diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index e817e9ad5b..077a2bfdcd 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -1,4 +1,4 @@ -

    Sweetsy!

    +

    Sweetsy!

    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index e074c0da2b..e90fe06e4c 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -7,64 +7,65 @@ <%= image_tag(@product.photo) %>
    -
    - <% if @product.quantity == 0 %> -

    Product out of Stock

    - <% else %> -

    Stock: <%= @product.quantity %>

    +
    + <% if @product.quantity == 0 %> +

    Product out of Stock

    + <% else %> +

    Stock: <%= @product.quantity %>

    + <% end %> +

    Price: <%= format_price(@product.price) %> +

    + Description: + <% if @product.description %> + <%= @product.description %> + <% else %> + <%= "None" %> + <% end %> +

    + + <% if @product.quantity > 0%> +
    + <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> + <%= f.label :quantity %> + <%= f.select :quantity, options_for_select(1..@product.quantity)%> + <%= f.hidden_field :product_id, value: @product.id %> + <%= f.submit "Add to cart", class: "button" %> + <% end %> +
    <% end %> -

    Price: <%= format_price(@product.price) %> +

    +

    Ratings Summary

    - Description: - <% if @product.description %> - <%= @product.description %> - <% else %> - <%= "None" %> - <% end %> + <%="Average rating: #{@product.average_rating}" %> +

    +

    + <%=link_to "Add review", new_product_review_path(@product.id), class: 'button' %>

    - <% if @product.quantity > 0%> -
    - <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> - <%= f.label :quantity %> - <%= f.select :quantity, options_for_select(1..@product.quantity)%> - <%= f.hidden_field :product_id, value: @product.id %> - <%= f.submit "Add to cart", class: "button" %> - <% end %> -
    - <% end %> -
    -

    Ratings Summary

    -

    - <%="Average rating: #{@product.average_rating}" %> -

    -

    - <%=link_to "Add review", new_product_review_path(@product.id), class: 'button' %> -

    - - - <% if @product.reviews.empty? %> -

    - Be the first to review! -

    + + <% if @product.reviews.empty? %> +

    + Be the first to review! +

    - <%else %> -
    + <%else %> +
    -
    - -
      - <% @product.reviews.length.times do |i| %> -
    • Review <%= "#{i+1}: " %><%="🍦" * @product.reviews[i].rating %>
    • +
      + +
        + <% @product.reviews.length.times do |i| %> +
      • Review <%= "#{i+1}: " %><%="🍦" * @product.reviews[i].rating %>
      • - <% if @product.reviews[i].comment && @product.reviews[i].comment.length > 0%> -
      • Comment: "<%= @product.reviews[i].comment %>"
      • - <%else %> -
      • No comments
      • - <%end %> - <%end %> -
      - <% end %> -
      -
    -
    + <% if @product.reviews[i].comment && @product.reviews[i].comment.length > 0%> +
  • Comment: "<%= @product.reviews[i].comment %>"
  • + <%else %> +
  • No comments
  • + <%end %> + <%end %> + + <% end %> + + + + diff --git a/db/seeds/products.csv b/db/seeds/products.csv index b95149e85d..be98a97dae 100644 --- a/db/seeds/products.csv +++ b/db/seeds/products.csv @@ -3,7 +3,7 @@ Pineapple cake,10.50,12,Moist and fresh,active,pineapple_cake.jpg Flan,5.95,20,Homemade and floppy,active,flan.jpg Pistachio ice cream,5.99,12,A pint of awesome,active,pistachio_ice_cream.jpg Baklava,3.50,40,Traditional pastry,active,baklava.jpg -Lemon ice cream cake,9.95,15,Refreshing,active,lemon_ice_cream.jpg +Lemon ice cream,9.95,15,Refreshing,active,lemon_ice_cream.jpg Chocolate chip cookies,6.50,100,Better than girl scout,active,choco_cookies.jpg Cheesecake,7.50,15,Creamy goodness,active,cheesecake.jpg Apple pie,6.60,20,Homemade freshness,active,apple_pie.jpg From b48df67442960ea5136999796554b13c07a1bbd5 Mon Sep 17 00:00:00 2001 From: Aruna Date: Thu, 26 Apr 2018 20:39:08 -0700 Subject: [PATCH 192/252] tried some styling on categories --- app/views/categories/show.html.erb | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 4aa21f93b4..c2c3261fac 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -1,10 +1,12 @@ <%= @category.name %> +
    +
    <% @category.products.each do |product| %> -

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

    - product pic +
    + <%= image_tag(product.photo) %> +

    Price: <%= format_price(product.price) %> @@ -16,5 +18,9 @@ <%= link_to "Add to cart", url_for(:controller => 'orderproducts', :action => 'create', :product_id => product.id, :quantity => product.quantity), method: :post %>

    - <% end %>
    + +
    + <% end %> +
    +
    From 41065f077c86fd00dbbe4915683800ccca5f904f Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 26 Apr 2018 21:29:06 -0700 Subject: [PATCH 193/252] show page pic and details --- app/assets/stylesheets/application.css | 39 ++++++--- app/views/products/index.html.erb | 2 +- app/views/products/show.html.erb | 110 +++++++++++++------------ 3 files changed, 87 insertions(+), 64 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 4c09afcd06..bcf3050880 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -73,6 +73,7 @@ body { #login a { margin: 0; } + .top-bar { background-color: #009999; border-bottom: dotted; @@ -86,6 +87,7 @@ body { color: black; border: black solid thin; } + h1 { font-family: 'Pacifico', cursive; padding-bottom: 40px; @@ -133,6 +135,10 @@ h1 { justify-content: center; } +.rating-container { + padding-top: 3em; +} + .rating-container ul { display: flex; justify-content: center; @@ -216,25 +222,36 @@ background-color: #f5f5f5; list-style: none; padding: 8px; } -.product-show-container { + +.flash { + +} + +.merch-container { display: grid; grid-template: - "text1" "image" - "text2" "image"; + "image" + "text"; + padding: 2em; } -#pic { - grid-area: image; +.product-show-details { + display: flex; + justify-content: center; } -.product-show-info { - grid-area: text1; +.product-show-details #show-pic { + margin: 0; } -.product-show-form { - grid-area: text2; +.product-form { + display: flex; + justify-content: center; } -.flash { - +.product-show-details p { + display: flex; + flex-direction: column; + padding: 1em; + margin: 0; } diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index c17a4c42ec..7a56f1490b 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -4,7 +4,7 @@
    <% @products.each do |product| %>
    -

    <%= product.name %>

    +

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

    <%= image_tag(product.photo) %>
    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index e90fe06e4c..533ba73b3b 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -3,17 +3,23 @@

    <%= @product.name %> details

    -
    - <%= image_tag(@product.photo) %> -
    -
    - <% if @product.quantity == 0 %> -

    Product out of Stock

    - <% else %> -

    Stock: <%= @product.quantity %>

    - <% end %> -

    Price: <%= format_price(@product.price) %> +

    +
    + <%= image_tag(@product.photo) %> +
    +
    +

    + Price: <%= format_price(@product.price) %> + + <% if @product.quantity == 0 %> +

    Product out of Stock

    + <% else %> +

    +

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

    + <% end %>

    Description: <% if @product.description %> @@ -22,50 +28,50 @@ <%= "None" %> <% end %>

    +
    +
    + <% if @product.quantity > 0 %> +

    + <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> + <%= f.label :quantity %> + <%= f.select :quantity, options_for_select(1..@product.quantity), class: "select-width" %> + <%= f.hidden_field :product_id, value: @product.id %> + <%= f.submit "Add to cart", class: "button" %> + <% end %> +

    + <% end %> +
    - <% if @product.quantity > 0%> -
    - <%= form_for (Orderproduct.new), :url => orderproducts_path do |f| %> - <%= f.label :quantity %> - <%= f.select :quantity, options_for_select(1..@product.quantity)%> - <%= f.hidden_field :product_id, value: @product.id %> - <%= f.submit "Add to cart", class: "button" %> - <% end %> -
    - <% end %> -
    -

    Ratings Summary

    -

    - <%="Average rating: #{@product.average_rating}" %> -

    -

    - <%=link_to "Add review", new_product_review_path(@product.id), class: 'button' %> -

    - - - <% if @product.reviews.empty? %> -

    - Be the first to review! -

    +
    +

    Ratings Summary

    +

    + <%="Average rating: #{@product.average_rating}" %> +

    +

    + <%=link_to "Add review", new_product_review_path(@product.id), class: 'button' %> +

    + + <% if @product.reviews.empty? %> +

    + Be the first to review! +

    + <%else %> +
    - <%else %> -
    +
    + +
      + <% @product.reviews.length.times do |i| %> +
    • Review <%= "#{i+1}: " %><%="🍦" * @product.reviews[i].rating %>
    • -
      - -
        - <% @product.reviews.length.times do |i| %> -
      • Review <%= "#{i+1}: " %><%="🍦" * @product.reviews[i].rating %>
      • + <% if @product.reviews[i].comment && @product.reviews[i].comment.length > 0%> +
      • Comment: "<%= @product.reviews[i].comment %>"
      • + <%else %> +
      • No comments
      • + <%end %> + <%end %> +
      + <% end %> +
      - <% if @product.reviews[i].comment && @product.reviews[i].comment.length > 0%> -
    • Comment: "<%= @product.reviews[i].comment %>"
    • - <%else %> -
    • No comments
    • - <%end %> - <%end %> -
    - <% end %> -
    - -
    From 4b7575bcb08c9076fcee99076db4311ff4065af1 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Thu, 26 Apr 2018 22:43:34 -0700 Subject: [PATCH 194/252] product show --- app/assets/stylesheets/application.css | 24 ++++++++++++++++ app/views/products/new.html.erb | 2 +- app/views/products/show.html.erb | 38 +++++++++++++------------- app/views/sessions/index.html.erb | 1 - 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index bcf3050880..f51849dee3 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -215,7 +215,15 @@ background-color: #f5f5f5; } #review { + display: flex; flex-direction: row; + justify-content: center; +} + +#review ul { + display: flex; + flex-direction: column; + justify-content: center; } #review li { @@ -244,6 +252,14 @@ background-color: #f5f5f5; margin: 0; } +.product-show-container { + border: solid thin grey; + padding-top: 1.5em; + width: 450px; + margin: auto; + background-color: rgba(255, 255, 255, 0.5); +} + .product-form { display: flex; justify-content: center; @@ -255,3 +271,11 @@ background-color: #f5f5f5; padding: 1em; margin: 0; } + +.new_orderproduct { + display: flex; + flex-direction: column; + width: 250px; + align-items: center; + margin: auto; +} diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index 91f6bfd964..18597f0e80 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -19,7 +19,7 @@ <%= b.check_box %> <%= b.label %> <% end %> - <%= f.submit class: "submit" %> + <%= f.submit "Add item", class: "button" %> <% end %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 533ba73b3b..7e7bcd4aff 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -2,7 +2,7 @@

    <%= @product.name %> details

    -
    +
    @@ -10,11 +10,11 @@

    - Price: <%= format_price(@product.price) %> - - <% if @product.quantity == 0 %> -

    Product out of Stock

    - <% else %> + Price: <%= format_price(@product.price) %> + + <% if @product.quantity == 0 %> +

    Product out of Stock

    + <% else %>

    Stock: <%= @product.quantity %> @@ -36,14 +36,16 @@ <%= f.label :quantity %> <%= f.select :quantity, options_for_select(1..@product.quantity), class: "select-width" %> <%= f.hidden_field :product_id, value: @product.id %> - <%= f.submit "Add to cart", class: "button" %> - <% end %>

    + <%= f.submit "Add to cart", class: "button" %> + <% end %> + <% end %>
    +
    -

    Ratings Summary

    +

    Ratings & Reviews

    <%="Average rating: #{@product.average_rating}" %>

    @@ -62,16 +64,14 @@
      <% @product.reviews.length.times do |i| %> -
    • Review <%= "#{i+1}: " %><%="🍦" * @product.reviews[i].rating %>
    • - - <% if @product.reviews[i].comment && @product.reviews[i].comment.length > 0%> -
    • Comment: "<%= @product.reviews[i].comment %>"
    • - <%else %> -
    • No comments
    • - <%end %> - <%end %> +
    • Rating <%= "#{i+1}: " %><%="🍦" * @product.reviews[i].rating %> + <% if @product.reviews[i].comment && @product.reviews[i].comment.length > 0%> + Comment: "<%= @product.reviews[i].comment %>" + <%else %> + Comment: None + <%end %> + <%end %> +
    <% end %> - -
    diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index 121a39ace6..58e0790b78 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -1,6 +1,5 @@ diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index dec9f204f6..641b68fb6c 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -14,8 +14,10 @@ Stock: <%= product.quantity %>

    + <% unless product.quantity == 0 %>

    - <%= link_to "Add to cart", url_for(:controller => 'orderproducts', :action => 'create', :product_id => product.id, :quantity => product.quantity), method: :post %> + <%= link_to "Add to cart", url_for(:controller => 'orderproducts', :action => 'create', :product_id => product.id, :quantity => 1), method: :post %> + <% end %>

    From 58bad0e6aa8860cec198b55601d57e10dec1b01e Mon Sep 17 00:00:00 2001 From: LetiTran Date: Fri, 27 Apr 2018 11:31:19 -0700 Subject: [PATCH 220/252] Removed cart button if not logged in. --- app/views/layouts/application.html.erb | 25 +- coverage/.last_run.json | 2 +- coverage/.resultset.json | 712 ++-- coverage/index.html | 4846 ++++++++++++++++-------- test/test_helper.rb | 12 +- 5 files changed, 3796 insertions(+), 1801 deletions(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index c308da2261..7393429be2 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -92,19 +92,18 @@ -

    - <%= link_to "Log Out", logout_path, method: :delete, class: "button" %> - <% else %> -

    -

    - <%= link_to "Log In", github_login_path, class: "button" %> - <% end %> -

    -

    - <%= link_to "View cart", cart_path, class: "button" %> -

    - -
    +

    <%= link_to "Log Out", logout_path, method: :delete, class: "button" %>

    + +

    <%= link_to "View cart", cart_path, class: "button" %>

    + + <% else %> +

    +

    + <%= link_to "Log In", github_login_path, class: "button" %> + <% end %> +

    + + diff --git a/coverage/.last_run.json b/coverage/.last_run.json index bf9546f97b..efaea9235b 100644 --- a/coverage/.last_run.json +++ b/coverage/.last_run.json @@ -1,5 +1,5 @@ { "result": { - "covered_percent": 43.77 + "covered_percent": 12.43 } } diff --git a/coverage/.resultset.json b/coverage/.resultset.json index 74930db2b5..fc5a6150b5 100644 --- a/coverage/.resultset.json +++ b/coverage/.resultset.json @@ -1,137 +1,187 @@ { "Unit Tests": { "coverage": { - "/Users/alex/Ada/rails/betsy/app/models/category.rb": [ + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/helpers/application_helper.rb": [ 1, + null, 1, + 0, null, + null, + null + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/helpers/categories_helper.rb": [ 1, null ], - "/Users/alex/Ada/rails/betsy/app/models/application_record.rb": [ + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/helpers/merchants_helper.rb": [ 1, + null + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/helpers/orderproducts_helper.rb": [ 1, null ], - "/Users/alex/Ada/rails/betsy/test/models/merchant_test.rb": [ + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/helpers/orders_helper.rb": [ + 1, + null + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/helpers/products_helper.rb": [ 1, null, + null + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/helpers/reviews_helper.rb": [ 1, + null + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/helpers/sessions_helper.rb": [ 1, - null, + null + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/models/order.rb": [ 1, 1, - 0, - null, null, 1, - 0, - null, - 0, - 0, - null, - null, 1, - 0, - null, - 0, - 0, null, + 1, + 1, + 1, + 1, + 1, null, 1, - 0, + 1, + 1, null, - 0, null, - 0, - 0, null, null, 1, - 0, - null, - 0, - 0, + 308, null, null, 1, - 0, + 4, + 4, + 4, null, - 0, - 0, + 4, null, null, 1, - 0, + 2, + 2, null, - 0, null, + 1, 0, - 0, - null, - null, null, + null + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/models/application_record.rb": [ + 1, + 1, + null + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/models/review.rb": [ 1, 1, - 0, - null, - 0, - 0, - null, null, + 1, + 1, null, null ], - "/Users/alex/Ada/rails/betsy/app/models/merchant.rb": [ + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/models/product.rb": [ + 1, 1, 1, 1, null, - null, + 1, + 1, + 1, 1, null, null, 1, + 0, + 0, + 0, + 0, null, + 0, null, null, 1, 0, + 0, null, null, + 1, null, - null, + 1, + 0, + 0, null, null, null, null ], - "/Users/alex/Ada/rails/betsy/test/models/order_test.rb": [ + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/models/category.rb": [ + 1, 1, null, 1, + null + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/models/orderproduct.rb": [ + 1, + 1, 1, null, 1, + null, 1, 0, null, + 0, null, + 0, null, + 0, + 0, + 0, + 0, null, null, + 1, + 4, null, null, null, null, null, + null + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/models/merchant.rb": [ + 1, + 1, + 1, null, null, + 1, null, null, + 1, null, null, null, + 1, + 0, null, null, null, @@ -139,112 +189,417 @@ null, null, null, + null + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/mailers/application_mailer.rb": [ + 0, + 0, + 0, + 0 + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/jobs/application_job.rb": [ + 0, + 0 + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/controllers/application_controller.rb": [ + 0, + 0, null, + 0, null, + 0, + 0, null, + 0, null, + 0, + 0, + 0, null, + 0, + 0, + 0, null, null, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0 + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/controllers/categories_controller.rb": [ + 0, + 0, + 0, null, + 0, + 0, + 0, null, + 0, + 0, null, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, null, + 0, null, null, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0, + 0, null, + 0, null, + 0, + 0, + 0, null, + 0, null, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0 + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/controllers/orderproducts_controller.rb": [ + 0, + 0, + 0, + 0, null, + 0, + 0, + 0, null, + 0, + 0, null, + 0, + 0, + 0, null, + 0, null, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, null, null, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, null, + 0, null, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0 + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/controllers/merchants_controller.rb": [ + 0, + 0, + 0, null, + 0, + 0, + 0, null, + 0, null, null, null, null, null, + 0, null, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0, null, + 0, + 0, + 0, + null, + 0, + 0, + 0, + 0, + 0 + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/controllers/orders_controller.rb": [ + 0, + 0, + 0, + null, + 0, null, null, null, null, null, null, + 0, null, + 0, null, + 0, null, null, + 0, null, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0, null, + 0, + 0, + 0, + 0, null, null, + 0, + 0, null, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, null, + 0, + 0, null, + 0, null, + 0, + 0, + 0, null, + 0, + 0, + 0, + 0, null, null, null, null, + 0 + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/controllers/products_controller.rb": [ + 0, + 0, + 0, null, + 0, + 0, + 0, null, - 1, - 1, + 0, + 0, null, 0, + 0, + 0, + 0, null, 0, 0, null, - null, - null, - null, - null, - 1, - 1, 0, 0, 0, null, 0, 0, + 0, null, - 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0, 0, 0, @@ -252,101 +607,46 @@ 0, 0, null, + 0, null, + 0, null, - 1, - 1, 0, null, 0, 0, - null, 0, 0, - null, - null, - 1, 0, 0, 0, - null, 0, 0, - null, - null, - null, - null - ], - "/Users/alex/Ada/rails/betsy/app/models/order.rb": [ - 1, - 1, - null, - 1, - 1, - null, - 1, - 1, - 1, - 1, - 1, - null, - 1, - 1, - 1, - null, - null, - null, - null, - 1, 0, null, + 0, null, - 1, 0, 0, 0, null, 0, - null, - null, - 1, 0, 0, null, - null, - 1, 0, - null, - null - ], - "/Users/alex/Ada/rails/betsy/test/models/orderproduct_test.rb": [ - 1, - null, - 1, - 1, - null, - 1, - 1, 0, - null, - null, - 1, + 0, 0, null, 0, 0, - null, - null, - null + 0, + 0 ], - "/Users/alex/Ada/rails/betsy/app/models/orderproduct.rb": [ - 1, - 1, - 1, - null, - 1, - null, - 1, + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/controllers/sessions_controller.rb": [ + 0, + 0, 0, null, 0, @@ -357,45 +657,15 @@ 0, 0, 0, - null, - null, - 1, 0, - null, - null, - null, - null, - null, - null - ], - "/Users/alex/Ada/rails/betsy/test/models/product_test.rb": [ - 1, - null, - 1, - 1, - null, - 1, - 1, 0, - null, - null, - null, - 1, 0, - null, 0, 0, null, - null, - null, - 1, 0, - null, 0, 0, - null, - null, - 1, 0, null, 0, @@ -403,224 +673,126 @@ 0, 0, null, - null, - 1, 0, null, 0, 0, - null, - null, - null, - 1, 0, null, 0, 0, null, - null, - 1, 0, - null, 0, 0, null, - null, - null, - 1, 0, - null, 0, 0, - null, - null, - 1, 0, - null, 0, 0, - null, - null, - 1, 0, - null, 0, 0, - null, - null, - null, - 1, - null, - 1, 0, - null, - null, - 1, 0, - null, 0, 0, - null, - null, - null, - 1, 0, - null, 0, 0, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - 1, - 1, + 0, 0, 0, null, 0, 0, - null, - null, - 1, 0, - null, 0, 0, null, 0, 0, 0, - null, - null, - null, - 1, - 1, 0, - null, 0, 0, null, - null, - 1, 0, 0, 0, - null, + 0, + 0, + 0 + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/controllers/reviews_controller.rb": [ + 0, 0, 0, null, + 0, + 0, + 0, null, + 0, null, - 1, - 1, 0, null, 0, 0, + 0, + 0, null, 0, + null, 0, null, null, - null - ], - "/Users/alex/Ada/rails/betsy/app/models/product.rb": [ - 1, - 1, - 1, - 1, null, - 1, - 1, - 1, - 1, null, null, - 1, + 0, + 0, + null, 0, 0, 0, 0, - null, 0, - null, - null, - 1, 0, 0, - null, - null, - 1, - null, - 1, 0, 0, - null, - null, - null, - null - ], - "/Users/alex/Ada/rails/betsy/test/models/review_test.rb": [ - 1, - null, - 1, - 1, - null, - 1, - 1, 0, - null, 0, null, null, - 1, 0, null, 0, 0, - null, - null, - 1, 0, null, 0, 0, - null, - null, - null, - 1, - 1, 0, 0, - null, + 0 + ], + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/channels/application_cable/connection.rb": [ 0, 0, - null, - null, - null, - null + 0, + 0 ], - "/Users/alex/Ada/rails/betsy/app/models/review.rb": [ - 1, - 1, - null, - 1, - 1, - null, - null + "/Users/leticiaogawa/Desktop/ada/c9_Ampers/projects/rails/betsy/app/channels/application_cable/channel.rb": [ + 0, + 0, + 0, + 0 ] }, - "timestamp": 1524851598 + "timestamp": 1524852571 } } diff --git a/coverage/index.html b/coverage/index.html index ddeb39801d..6607c97fd0 100644 --- a/coverage/index.html +++ b/coverage/index.html @@ -14,27 +14,27 @@ loading