From dc88ee3b1a76139a5b0ce3fecb49b87ab77feb8c Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Tue, 17 Oct 2017 14:16:42 -0700 Subject: [PATCH 001/223] Initial Rails setup --- .gitignore | 19 + Gemfile | 68 ++ Gemfile.lock | 232 +++++++ Rakefile | 6 + app/assets/config/manifest.js | 3 + app/assets/images/.keep | 0 app/assets/javascripts/application.js | 17 + app/assets/javascripts/cable.js | 13 + app/assets/javascripts/channels/.keep | 0 app/assets/stylesheets/_settings.scss | 620 ++++++++++++++++++ app/assets/stylesheets/application.css | 17 + .../stylesheets/foundation_and_overrides.scss | 53 ++ 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/models/user.rb | 2 + 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/migrate/20171017211617_create_users.rb | 8 + 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/fixtures/users.yml | 11 + test/helpers/.keep | 0 test/integration/.keep | 0 test/mailers/.keep | 0 test/models/.keep | 0 test/models/user_test.rb | 9 + test/system/.keep | 0 test/test_helper.rb | 26 + tmp/.keep | 0 vendor/.keep | 0 81 files changed, 2015 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/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/models/user.rb 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/migrate/20171017211617_create_users.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/fixtures/users.yml 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/models/user_test.rb 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..b105f8ecb6 --- /dev/null +++ b/Gemfile @@ -0,0 +1,68 @@ +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.4' +# Use postgresql as the database for Active Record +gem 'pg', '~> 0.18' +# Use Puma as the app server +gem 'puma', '~> 3.7' +# Use SCSS for stylesheets +gem 'sass-rails', '~> 5.0' +# Use Uglifier as compressor for JavaScript assets +gem 'uglifier', '>= 1.3.0' +# See https://github.com/rails/execjs#readme for more supported runtimes +# gem 'therubyracer', platforms: :ruby + +# Use CoffeeScript for .coffee assets and views +# gem 'coffee-rails', '~> 4.2' +# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks +gem 'turbolinks', '~> 5' +# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder +gem 'jbuilder', '~> 2.5' +# Use Redis adapter to run Action Cable in production +# gem 'redis', '~> 3.0' +# Use ActiveModel has_secure_password +# gem 'bcrypt', '~> 3.1.7' + +# Use Capistrano for deployment +# gem 'capistrano-rails', group: :development + +gem 'foundation-rails', '~> 6.3.1' + +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' +group :development do + gem 'better_errors' + gem 'pry-rails' + 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..511ae2017e --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,232 @@ +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.1.4) + actionpack (= 5.1.4) + nio4r (~> 2.0) + websocket-driver (~> 0.6.1) + actionmailer (5.1.4) + actionpack (= 5.1.4) + actionview (= 5.1.4) + activejob (= 5.1.4) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.1.4) + actionview (= 5.1.4) + activesupport (= 5.1.4) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.1.4) + activesupport (= 5.1.4) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.1.4) + activesupport (= 5.1.4) + globalid (>= 0.3.6) + activemodel (5.1.4) + activesupport (= 5.1.4) + activerecord (5.1.4) + activemodel (= 5.1.4) + activesupport (= 5.1.4) + arel (~> 8.0) + activesupport (5.1.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (~> 0.7) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + ansi (1.5.0) + arel (8.0.0) + babel-source (5.8.35) + babel-transpiler (0.7.0) + babel-source (>= 4.0, < 6) + execjs (~> 2.0) + better_errors (2.4.0) + coderay (>= 1.0.0) + erubi (>= 1.0.0) + rack (>= 0.9.0) + bindex (0.5.0) + binding_of_caller (0.7.2) + debug_inspector (>= 0.0.1) + builder (3.2.3) + byebug (9.1.0) + capybara (2.15.4) + addressable + mini_mime (>= 0.1.3) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) + childprocess (0.8.0) + ffi (~> 1.0, >= 1.0.11) + coderay (1.1.2) + concurrent-ruby (1.0.5) + crass (1.0.2) + debug_inspector (0.0.3) + erubi (1.7.0) + execjs (2.7.0) + ffi (1.9.18) + foundation-rails (6.3.1.0) + railties (>= 3.1.0) + sass (>= 3.3.0, < 3.5) + sprockets-es6 (>= 0.9.0) + globalid (0.4.0) + activesupport (>= 4.2.0) + i18n (0.9.0) + concurrent-ruby (~> 1.0) + jbuilder (2.7.0) + activesupport (>= 4.2.0) + multi_json (>= 1.2) + 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.1.1) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.6.6) + mime-types (>= 1.16, < 4) + method_source (0.9.0) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mini_mime (0.1.4) + mini_portile2 (2.3.0) + minitest (5.10.3) + minitest-rails (3.0.0) + minitest (~> 5.8) + railties (~> 5.0) + minitest-reporters (1.1.18) + ansi + builder + minitest (>= 5.0) + ruby-progressbar + multi_json (1.12.2) + nio4r (2.1.0) + nokogiri (1.8.1) + mini_portile2 (~> 2.3.0) + pg (0.21.0) + pry (0.11.1) + coderay (~> 1.1.0) + method_source (~> 0.9.0) + pry-rails (0.3.6) + pry (>= 0.10.4) + public_suffix (3.0.0) + puma (3.10.0) + rack (2.0.3) + rack-test (0.7.0) + rack (>= 1.0, < 3) + rails (5.1.4) + actioncable (= 5.1.4) + actionmailer (= 5.1.4) + actionpack (= 5.1.4) + actionview (= 5.1.4) + activejob (= 5.1.4) + activemodel (= 5.1.4) + activerecord (= 5.1.4) + activesupport (= 5.1.4) + bundler (>= 1.3.0) + railties (= 5.1.4) + sprockets-rails (>= 2.0.0) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.0.3) + loofah (~> 2.0) + railties (5.1.4) + actionpack (= 5.1.4) + activesupport (= 5.1.4) + method_source + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rake (12.1.0) + rb-fsevent (0.10.2) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) + ruby-progressbar (1.9.0) + ruby_dep (1.5.0) + rubyzip (1.2.1) + sass (3.4.25) + sass-rails (5.0.6) + railties (>= 4.0.0, < 6) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + selenium-webdriver (3.6.0) + childprocess (~> 0.5) + rubyzip (~> 1.0) + spring (2.0.2) + activesupport (>= 4.2) + spring-watcher-listen (2.0.1) + listen (>= 2.7, < 4.0) + spring (>= 1.2, < 3.0) + sprockets (3.7.1) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-es6 (0.9.2) + babel-source (>= 5.8.11) + babel-transpiler + sprockets (>= 3.0.0) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + thor (0.20.0) + thread_safe (0.3.6) + tilt (2.0.8) + turbolinks (5.0.1) + turbolinks-source (~> 5) + turbolinks-source (5.0.3) + tzinfo (1.2.3) + thread_safe (~> 0.1) + uglifier (3.2.0) + execjs (>= 0.3.0, < 3) + web-console (3.5.1) + actionview (>= 5.0) + activemodel (>= 5.0) + bindex (>= 0.4.0) + railties (>= 5.0) + websocket-driver (0.6.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.2) + xpath (2.1.0) + nokogiri (~> 1.3) + +PLATFORMS + ruby + +DEPENDENCIES + better_errors + binding_of_caller + byebug + capybara (~> 2.13) + foundation-rails (~> 6.3.1) + jbuilder (~> 2.5) + jquery-turbolinks + listen (>= 3.0.5, < 3.2) + minitest-rails + minitest-reporters + pg (~> 0.18) + pry-rails + puma (~> 3.7) + rails (~> 5.1.4) + 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.15.4 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..8460d2bdab --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,17 @@ +// 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 rails-ujs +//= 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..af784b6d68 --- /dev/null +++ b/app/assets/stylesheets/_settings.scss @@ -0,0 +1,620 @@ +// 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. Forms +// 20. Label +// 21. Media Object +// 22. Menu +// 23. Meter +// 24. Off-canvas +// 25. Orbit +// 26. Pagination +// 27. Progress Bar +// 28. Responsive Embed +// 29. Reveal +// 30. Slider +// 31. Switch +// 32. Table +// 33. Tabs +// 34. Thumbnail +// 35. Title Bar +// 36. Tooltip +// 37. Top Bar + +@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-weight-normal: normal; +$global-weight-bold: bold; +$global-radius: 0; +$global-text-direction: ltr; +$global-flexbox: false; +$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; +$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-arrows: true; +$accordionmenu-arrow-color: $primary-color; +$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-slash: true; + +// 11. Button +// ---------- + +$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-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: $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-arrow-color: $primary-color; +$drilldown-arrow-size: 6px; +$drilldown-background: $white; + +// 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-min-width: 200px; +$dropdownmenu-background: $white; +$dropdownmenu-border: 1px solid $medium-gray; + +// 19. 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-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-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; + +// 20. 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; + +// 21. Media Object +// ---------------- + +$mediaobject-margin-bottom: $global-margin; +$mediaobject-section-padding: $global-padding; +$mediaobject-image-width-stacked: 100%; + +// 22. Menu +// -------- + +$menu-margin: 0; +$menu-margin-nested: 1rem; +$menu-item-padding: 0.7rem 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-border: $light-gray; + +// 23. 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; + +// 24. Off-canvas +// -------------- + +$offcanvas-size: 250px; +$offcanvas-vertical-size: 250px; +$offcanvas-background: $light-gray; +$offcanvas-shadow: 0 0 10px rgba($black, 0.7); +$offcanvas-push-zindex: 1; +$offcanvas-overlap-zindex: 10; +$offcanvas-reveal-zindex: 1; +$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'; + +// 25. 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; + +// 26. 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; + +// 27. Progress Bar +// ---------------- + +$progress-height: 1rem; +$progress-background: $medium-gray; +$progress-margin-bottom: $global-margin; +$progress-meter-background: $primary-color; +$progress-radius: $global-radius; + +// 28. Responsive Embed +// -------------------- + +$responsive-embed-margin-bottom: rem-calc(16); +$responsive-embed-ratios: ( + default: 4 by 3, + widescreen: 16 by 9, +); + +// 29. 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); + +// 30. 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; + +// 31. 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; + +// 32. 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; + +// 33. 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; + +// 34. 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; + +// 35. 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; + +// 36. Tooltip +// ----------- + +$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-font-size: $small-font-size; +$tooltip-pip-width: 0.75rem; +$tooltip-pip-height: $tooltip-pip-width * 0.866; +$tooltip-radius: $global-radius; + +// 37. 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; diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css new file mode 100644 index 0000000000..a152282fce --- /dev/null +++ b/app/assets/stylesheets/application.css @@ -0,0 +1,17 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's + * vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + * + *= require_tree . + *= require_self + *= require foundation_and_overrides + + */ diff --git a/app/assets/stylesheets/foundation_and_overrides.scss b/app/assets/stylesheets/foundation_and_overrides.scss new file mode 100644 index 0000000000..2066155081 --- /dev/null +++ b/app/assets/stylesheets/foundation_and_overrides.scss @@ -0,0 +1,53 @@ +@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-grid; +@include foundation-typography; +@include foundation-button; +@include foundation-forms; +@include foundation-visibility-classes; +@include foundation-float-classes; +@include foundation-accordion; +@include foundation-accordion-menu; +@include foundation-badge; +@include foundation-breadcrumbs; +@include foundation-button-group; +@include foundation-callout; +@include foundation-card; +@include foundation-close-button; +@include foundation-drilldown-menu; +@include foundation-dropdown; +@include foundation-dropdown-menu; +@include foundation-responsive-embed; +@include foundation-label; +@include foundation-media-object; +@include foundation-menu; +@include foundation-menu-icon; +@include foundation-off-canvas; +@include foundation-orbit; +@include foundation-pagination; +@include foundation-progress-bar; +@include foundation-slider; +@include foundation-sticky; +@include foundation-reveal; +@include foundation-switch; +@include foundation-table; +@include foundation-tabs; +@include foundation-thumbnail; +@include foundation-title-bar; +@include foundation-tooltip; +@include foundation-top-bar; + +// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package. +// +// @include motion-ui-transitions; +// @include motion-ui-animations; 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/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000000..379658a509 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,2 @@ +class User < ApplicationRecord +end 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..28845a5772 --- /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: 6ad4cb09f1f6310238665bbedf21d3df757d2f4131527195e7c378acd15ece9e0f1ddb2b7a8856621109d116ef1854cf34d293c897dcdcc2929c8311389fd4d8 + +test: + secret_key_base: 0f85486780575c561a663d649687d640df12955e544d74a258158c05c6b7ba8a808323a7e7f04e93d54253d37a1e0a572f33482e33443adf6b27bf08f1609190 + +# 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/migrate/20171017211617_create_users.rb b/db/migrate/20171017211617_create_users.rb new file mode 100644 index 0000000000..a588bf5a68 --- /dev/null +++ b/db/migrate/20171017211617_create_users.rb @@ -0,0 +1,8 @@ +class CreateUsers < ActiveRecord::Migration[5.1] + def change + create_table :users do |t| + + t.timestamps + end + end +end 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/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 0000000000..dc3ee79b5d --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the "{}" from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/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/models/user_test.rb b/test/models/user_test.rb new file mode 100644 index 0000000000..cc862ac2d9 --- /dev/null +++ b/test/models/user_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe User do + let(:user) { User.new } + + it "must be valid" do + value(user).must_be :valid? + end +end 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 1856ee0c16049e0631cd4414e63f5131aa8feef7 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Tue, 17 Oct 2017 16:07:11 -0700 Subject: [PATCH 002/223] Add model and controller for merchant --- app/assets/javascripts/merchants.js | 2 ++ app/assets/stylesheets/merchants.scss | 3 +++ app/controllers/merchants_controller.rb | 2 ++ app/helpers/merchants_helper.rb | 2 ++ app/models/merchant.rb | 2 ++ db/migrate/20171017230130_create_merchants.rb | 10 ++++++++ db/schema.rb | 25 +++++++++++++++++++ test/controllers/merchants_controller_test.rb | 7 ++++++ test/fixtures/merchants.yml | 11 ++++++++ test/models/merchant_test.rb | 9 +++++++ 10 files changed, 73 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/models/merchant.rb create mode 100644 db/migrate/20171017230130_create_merchants.rb create mode 100644 db/schema.rb create mode 100644 test/controllers/merchants_controller_test.rb create mode 100644 test/fixtures/merchants.yml create mode 100644 test/models/merchant_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..ae95f7677b --- /dev/null +++ b/app/controllers/merchants_controller.rb @@ -0,0 +1,2 @@ +class MerchantsController < ApplicationController +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/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/db/migrate/20171017230130_create_merchants.rb b/db/migrate/20171017230130_create_merchants.rb new file mode 100644 index 0000000000..64a57c904c --- /dev/null +++ b/db/migrate/20171017230130_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/schema.rb b/db/schema.rb new file mode 100644 index 0000000000..f2f77b0a21 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,25 @@ +# 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: 20171017230130) do + + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + 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 + +end diff --git a/test/controllers/merchants_controller_test.rb b/test/controllers/merchants_controller_test.rb new file mode 100644 index 0000000000..6eb57f7baa --- /dev/null +++ b/test/controllers/merchants_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +describe MerchantsController do + # it "must be a real test" do + # flunk "Need real tests" + # end +end diff --git a/test/fixtures/merchants.yml b/test/fixtures/merchants.yml new file mode 100644 index 0000000000..dc3ee79b5d --- /dev/null +++ b/test/fixtures/merchants.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the "{}" from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/models/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 From 9b7a496eefe0edbf2bf6632bbd2b9267c349b738 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Tue, 17 Oct 2017 16:10:28 -0700 Subject: [PATCH 003/223] Add model and controller for merchant --- app/models/user.rb | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 app/models/user.rb diff --git a/app/models/user.rb b/app/models/user.rb deleted file mode 100644 index 379658a509..0000000000 --- a/app/models/user.rb +++ /dev/null @@ -1,2 +0,0 @@ -class User < ApplicationRecord -end From 874d1799d635bb0f15c6530c6c95842a1b1e81ba Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Tue, 17 Oct 2017 16:11:46 -0700 Subject: [PATCH 004/223] Add model and controller for merchant --- db/migrate/20171017211617_create_users.rb | 8 -------- test/fixtures/users.yml | 11 ----------- test/models/user_test.rb | 9 --------- 3 files changed, 28 deletions(-) delete mode 100644 db/migrate/20171017211617_create_users.rb delete mode 100644 test/fixtures/users.yml delete mode 100644 test/models/user_test.rb diff --git a/db/migrate/20171017211617_create_users.rb b/db/migrate/20171017211617_create_users.rb deleted file mode 100644 index a588bf5a68..0000000000 --- a/db/migrate/20171017211617_create_users.rb +++ /dev/null @@ -1,8 +0,0 @@ -class CreateUsers < ActiveRecord::Migration[5.1] - def change - create_table :users do |t| - - t.timestamps - end - end -end diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml deleted file mode 100644 index dc3ee79b5d..0000000000 --- a/test/fixtures/users.yml +++ /dev/null @@ -1,11 +0,0 @@ -# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html - -# This model initially had no columns defined. If you add columns to the -# model remove the "{}" from the fixture names and add the columns immediately -# below each fixture, per the syntax in the comments below -# -one: {} -# column: value -# -two: {} -# column: value diff --git a/test/models/user_test.rb b/test/models/user_test.rb deleted file mode 100644 index cc862ac2d9..0000000000 --- a/test/models/user_test.rb +++ /dev/null @@ -1,9 +0,0 @@ -require "test_helper" - -describe User do - let(:user) { User.new } - - it "must be valid" do - value(user).must_be :valid? - end -end From 36196ca76d067d9b50641576c5d35e31a8cf86e7 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Tue, 17 Oct 2017 16:26:44 -0700 Subject: [PATCH 005/223] Add model and controller product --- app/assets/javascripts/products.js | 2 ++ app/assets/stylesheets/products.scss | 3 +++ app/controllers/products_controller.rb | 2 ++ app/helpers/products_helper.rb | 2 ++ app/models/product.rb | 2 ++ db/migrate/20171017231310_create_products.rb | 15 +++++++++++++++ db/schema.rb | 14 +++++++++++++- test/controllers/products_controller_test.rb | 7 +++++++ test/fixtures/products.yml | 11 +++++++++++ test/models/product_test.rb | 9 +++++++++ 10 files changed, 66 insertions(+), 1 deletion(-) 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/models/product.rb create mode 100644 db/migrate/20171017231310_create_products.rb create mode 100644 test/controllers/products_controller_test.rb create mode 100644 test/fixtures/products.yml create mode 100644 test/models/product_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..f1ad12ddea --- /dev/null +++ b/app/controllers/products_controller.rb @@ -0,0 +1,2 @@ +class ProductsController < ApplicationController +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/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/db/migrate/20171017231310_create_products.rb b/db/migrate/20171017231310_create_products.rb new file mode 100644 index 0000000000..e28175d8ae --- /dev/null +++ b/db/migrate/20171017231310_create_products.rb @@ -0,0 +1,15 @@ +class CreateProducts < ActiveRecord::Migration[5.1] + def change + create_table :products do |t| + t.string :name + t.float :price + t.integer :stock + t.boolean :retired + t.text :description + t.string :image_url + t.integer :merchant_id + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index f2f77b0a21..8426080fd7 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: 20171017230130) do +ActiveRecord::Schema.define(version: 20171017231310) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -22,4 +22,16 @@ t.datetime "updated_at", null: false end + create_table "products", force: :cascade do |t| + t.string "name" + t.float "price" + t.integer "stock" + t.boolean "retired" + t.text "description" + t.string "image_url" + t.integer "merchant_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + end diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb new file mode 100644 index 0000000000..392a20e292 --- /dev/null +++ b/test/controllers/products_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +describe ProductsController do + # it "must be a real test" do + # flunk "Need real tests" + # end +end diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml new file mode 100644 index 0000000000..dc3ee79b5d --- /dev/null +++ b/test/fixtures/products.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the "{}" from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/models/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 From 58898ae8d7f73f7017b46c5b21a97cb41d86928a Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Tue, 17 Oct 2017 16:33:50 -0700 Subject: [PATCH 006/223] Add model and controller order_items --- app/assets/javascripts/order_items.js | 2 ++ app/assets/stylesheets/order_items.scss | 3 +++ app/controllers/order_items_controller.rb | 2 ++ app/helpers/order_items_helper.rb | 2 ++ app/models/order_item.rb | 2 ++ db/migrate/20171017232857_create_order_items.rb | 11 +++++++++++ db/schema.rb | 10 +++++++++- test/controllers/order_items_controller_test.rb | 7 +++++++ test/fixtures/order_items.yml | 11 +++++++++++ test/models/order_item_test.rb | 9 +++++++++ 10 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/order_items.js create mode 100644 app/assets/stylesheets/order_items.scss create mode 100644 app/controllers/order_items_controller.rb create mode 100644 app/helpers/order_items_helper.rb create mode 100644 app/models/order_item.rb create mode 100644 db/migrate/20171017232857_create_order_items.rb create mode 100644 test/controllers/order_items_controller_test.rb create mode 100644 test/fixtures/order_items.yml create mode 100644 test/models/order_item_test.rb diff --git a/app/assets/javascripts/order_items.js b/app/assets/javascripts/order_items.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/order_items.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/stylesheets/order_items.scss b/app/assets/stylesheets/order_items.scss new file mode 100644 index 0000000000..584862de9b --- /dev/null +++ b/app/assets/stylesheets/order_items.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the OrderItems 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/order_items_controller.rb b/app/controllers/order_items_controller.rb new file mode 100644 index 0000000000..357e7f5c80 --- /dev/null +++ b/app/controllers/order_items_controller.rb @@ -0,0 +1,2 @@ +class OrderItemsController < ApplicationController +end diff --git a/app/helpers/order_items_helper.rb b/app/helpers/order_items_helper.rb new file mode 100644 index 0000000000..e197528ae1 --- /dev/null +++ b/app/helpers/order_items_helper.rb @@ -0,0 +1,2 @@ +module OrderItemsHelper +end diff --git a/app/models/order_item.rb b/app/models/order_item.rb new file mode 100644 index 0000000000..acc6099fd0 --- /dev/null +++ b/app/models/order_item.rb @@ -0,0 +1,2 @@ +class OrderItem < ApplicationRecord +end diff --git a/db/migrate/20171017232857_create_order_items.rb b/db/migrate/20171017232857_create_order_items.rb new file mode 100644 index 0000000000..1b14bf865b --- /dev/null +++ b/db/migrate/20171017232857_create_order_items.rb @@ -0,0 +1,11 @@ +class CreateOrderItems < ActiveRecord::Migration[5.1] + def change + create_table :order_items do |t| + t.integer :quantity + t.integer :product_id + t.integer :order_id + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 8426080fd7..11c9eeeb3d 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: 20171017231310) do +ActiveRecord::Schema.define(version: 20171017232857) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -22,6 +22,14 @@ t.datetime "updated_at", null: false end + create_table "order_items", force: :cascade do |t| + t.integer "quantity" + t.integer "product_id" + t.integer "order_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "products", force: :cascade do |t| t.string "name" t.float "price" diff --git a/test/controllers/order_items_controller_test.rb b/test/controllers/order_items_controller_test.rb new file mode 100644 index 0000000000..96e3063c9c --- /dev/null +++ b/test/controllers/order_items_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +describe OrderItemsController do + # it "must be a real test" do + # flunk "Need real tests" + # end +end diff --git a/test/fixtures/order_items.yml b/test/fixtures/order_items.yml new file mode 100644 index 0000000000..dc3ee79b5d --- /dev/null +++ b/test/fixtures/order_items.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the "{}" from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/models/order_item_test.rb b/test/models/order_item_test.rb new file mode 100644 index 0000000000..19a9bf8f58 --- /dev/null +++ b/test/models/order_item_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe OrderItem do + let(:order_item) { OrderItem.new } + + it "must be valid" do + value(order_item).must_be :valid? + end +end From fd229380edc227f209c1875bb55ac49813622e11 Mon Sep 17 00:00:00 2001 From: Rebecca Bergena Date: Tue, 17 Oct 2017 16:39:27 -0700 Subject: [PATCH 007/223] add order model --- app/models/order.rb | 2 ++ db/migrate/20171017233246_create_orders.rb | 14 ++++++++++++++ db/schema.rb | 13 ++++++++++++- test/fixtures/orders.yml | 11 +++++++++++ test/models/order_test.rb | 9 +++++++++ 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 app/models/order.rb create mode 100644 db/migrate/20171017233246_create_orders.rb create mode 100644 test/fixtures/orders.yml create mode 100644 test/models/order_test.rb 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/db/migrate/20171017233246_create_orders.rb b/db/migrate/20171017233246_create_orders.rb new file mode 100644 index 0000000000..81d89915b6 --- /dev/null +++ b/db/migrate/20171017233246_create_orders.rb @@ -0,0 +1,14 @@ +class CreateOrders < ActiveRecord::Migration[5.1] + def change + create_table :orders do |t| + t.string :status + t.string :customer_name + t.string :customer_email + t.integer :cc_number + t.date :cc_exipration + t.integer :cc_ccv + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 8426080fd7..1d71d06631 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: 20171017231310) do +ActiveRecord::Schema.define(version: 20171017233246) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -22,6 +22,17 @@ t.datetime "updated_at", null: false end + create_table "orders", force: :cascade do |t| + t.string "status" + t.string "customer_name" + t.string "customer_email" + t.integer "cc_number" + t.date "cc_exipration" + t.integer "cc_ccv" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "products", force: :cascade do |t| t.string "name" t.float "price" diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml new file mode 100644 index 0000000000..dc3ee79b5d --- /dev/null +++ b/test/fixtures/orders.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the "{}" from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/models/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 From e181817dd52249fe5da1feeadad4674d89e4e0ce Mon Sep 17 00:00:00 2001 From: Rebecca Bergena Date: Tue, 17 Oct 2017 16:57:42 -0700 Subject: [PATCH 008/223] revert --- app/models/order.rb | 2 -- db/migrate/20171017233246_create_orders.rb | 14 -------------- db/schema.rb | 11 +---------- test/fixtures/orders.yml | 11 ----------- test/models/order_test.rb | 9 --------- 5 files changed, 1 insertion(+), 46 deletions(-) delete mode 100644 app/models/order.rb delete mode 100644 db/migrate/20171017233246_create_orders.rb delete mode 100644 test/fixtures/orders.yml delete mode 100644 test/models/order_test.rb diff --git a/app/models/order.rb b/app/models/order.rb deleted file mode 100644 index 10281b3450..0000000000 --- a/app/models/order.rb +++ /dev/null @@ -1,2 +0,0 @@ -class Order < ApplicationRecord -end diff --git a/db/migrate/20171017233246_create_orders.rb b/db/migrate/20171017233246_create_orders.rb deleted file mode 100644 index 81d89915b6..0000000000 --- a/db/migrate/20171017233246_create_orders.rb +++ /dev/null @@ -1,14 +0,0 @@ -class CreateOrders < ActiveRecord::Migration[5.1] - def change - create_table :orders do |t| - t.string :status - t.string :customer_name - t.string :customer_email - t.integer :cc_number - t.date :cc_exipration - t.integer :cc_ccv - - t.timestamps - end - end -end diff --git a/db/schema.rb b/db/schema.rb index df3c52c19b..11c9eeeb3d 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: 20171017232857) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -22,15 +22,6 @@ t.datetime "updated_at", null: false end - - create_table "orders", force: :cascade do |t| - t.string "status" - t.string "customer_name" - t.string "customer_email" - t.integer "cc_number" - t.date "cc_exipration" - t.integer "cc_ccv" - create_table "order_items", force: :cascade do |t| t.integer "quantity" t.integer "product_id" diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml deleted file mode 100644 index dc3ee79b5d..0000000000 --- a/test/fixtures/orders.yml +++ /dev/null @@ -1,11 +0,0 @@ -# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html - -# This model initially had no columns defined. If you add columns to the -# model remove the "{}" from the fixture names and add the columns immediately -# below each fixture, per the syntax in the comments below -# -one: {} -# column: value -# -two: {} -# column: value diff --git a/test/models/order_test.rb b/test/models/order_test.rb deleted file mode 100644 index df80f10fb6..0000000000 --- a/test/models/order_test.rb +++ /dev/null @@ -1,9 +0,0 @@ -require "test_helper" - -describe Order do - let(:order) { Order.new } - - it "must be valid" do - value(order).must_be :valid? - end -end From 568244517e23357be188b76b516305464d47a0dd Mon Sep 17 00:00:00 2001 From: Rebecca Bergena Date: Tue, 17 Oct 2017 17:16:48 -0700 Subject: [PATCH 009/223] add order model --- app/models/order.rb | 2 ++ db/migrate/20171018001235_create_orders.rb | 15 +++++++++++++++ db/schema.rb | 14 +++++++++++++- test/fixtures/orders.yml | 11 +++++++++++ test/models/order_test.rb | 9 +++++++++ 5 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 app/models/order.rb create mode 100644 db/migrate/20171018001235_create_orders.rb create mode 100644 test/fixtures/orders.yml create mode 100644 test/models/order_test.rb 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/db/migrate/20171018001235_create_orders.rb b/db/migrate/20171018001235_create_orders.rb new file mode 100644 index 0000000000..93ffcec7ea --- /dev/null +++ b/db/migrate/20171018001235_create_orders.rb @@ -0,0 +1,15 @@ +class CreateOrders < ActiveRecord::Migration[5.1] + def change + create_table :orders do |t| + t.string :status + t.string :customer_name + t.string :customer_email + t.string :customer_address + t.string :cc_number + t.date :cc_exipration + t.string :cc_ccv + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 11c9eeeb3d..f4afde3118 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: 20171017232857) do +ActiveRecord::Schema.define(version: 20171018001235) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -30,6 +30,18 @@ t.datetime "updated_at", null: false end + create_table "orders", force: :cascade do |t| + t.string "status" + t.string "customer_name" + t.string "customer_email" + t.string "customer_address" + t.string "cc_number" + t.date "cc_exipration" + t.string "cc_ccv" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "products", force: :cascade do |t| t.string "name" t.float "price" diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml new file mode 100644 index 0000000000..dc3ee79b5d --- /dev/null +++ b/test/fixtures/orders.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the "{}" from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/models/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 From 2066faa17f48c5fce7dd710e9b6c69d4cc1a7c11 Mon Sep 17 00:00:00 2001 From: Eva Sawyer Date: Tue, 17 Oct 2017 20:58:57 -0700 Subject: [PATCH 010/223] testing product relationships and validations --- app/models/product.rb | 10 ++++++ test/models/product_test.rb | 65 +++++++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/app/models/product.rb b/app/models/product.rb index 35a85acab3..b57a467bbb 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,2 +1,12 @@ class Product < ApplicationRecord + + belongs_to :merchant + has_many :order_item + + + validates :name, presence: true, uniqueness: true + validates :price, presence: true #must be a number too + validates_numericality_of :price, greater_than: 0 + + end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index a618b0a156..700aed0528 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -1,9 +1,68 @@ require "test_helper" describe Product do - let(:product) { Product.new } + describe "relations" do - it "must be valid" do - value(product).must_be :valid? + it "has a merchant" do + onceler = Merchant.create + # want_to_buy = Order_items.create + thneed = Product.new(name: "blue_thneed", price: 10, merchant: onceler) + + thneed.must_respond_to :merchant + thneed.merchant.must_be_kind_of Merchant + end + + #This is failing b/c I can't make Order_items. + #I don't know why I can't make Order_items. + it "has a list of order_items" do + onceler = Merchant.create + want_to_buy = Order_item.create + thneed = Product.new(name: "blue_thneed", price: 10, merchant: onceler, order_item: want_to_buy) + + thneed.must_respond_to :item_order + end + end + + describe "validations" do + + it "allows a product to be created with a unique name and price" do + onceler = Merchant.create + thneed = Product.new(name: "blue_thneed", price: 10, merchant: onceler) + + thneed.valid?.must_equal true + end + + it "requires a name to be created" do + onceler = Merchant.create + thneed = Product.new(price: 10, merchant: onceler) + + thneed.valid?.must_equal false + end + + it "requires a price to be created" do + onceler = Merchant.create + thneed = Product.new(name: "blue_thneed", merchant: onceler) + + thneed.valid?.must_equal false + end + + it "requires the price be greater than 0" do + onceler = Merchant.create + thneed_0 = Product.new(name: "blue_thneed", price: 0, merchant: onceler) + thneed_less_than_0 = Product.new(name: "blue_thneed", price: -10, merchant: onceler) + thneed_ten = Product.new(name: "blue_thneed", price: "ten", merchant: onceler) + + thneed_0.valid?.must_equal false + thneed_less_than_0.valid?.must_equal false + thneed_ten.valid?.must_equal false + end + + it "requires a unique name to be created" do + onceler = Merchant.create + thneed_1 = Product.create(name: "blue_thneed", price: 10, merchant: onceler) + thneed_2 = Product.new(name: "blue_thneed", price: 10, merchant: onceler) + + thneed_2.valid?.must_equal false + end end end From 2ed7b0e46cf8ddf66c669dc370bc162f1b0945e4 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Tue, 17 Oct 2017 21:01:11 -0700 Subject: [PATCH 011/223] Add new controller main --- app/assets/javascripts/main.js | 2 ++ app/assets/stylesheets/main.scss | 3 +++ app/controllers/main_controller.rb | 5 +++++ app/controllers/merchants_controller.rb | 12 ++++++++++++ app/helpers/main_helper.rb | 2 ++ test/controllers/main_controller_test.rb | 7 +++++++ 6 files changed, 31 insertions(+) create mode 100644 app/assets/javascripts/main.js create mode 100644 app/assets/stylesheets/main.scss create mode 100644 app/controllers/main_controller.rb create mode 100644 app/helpers/main_helper.rb create mode 100644 test/controllers/main_controller_test.rb diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/main.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/main.scss b/app/assets/stylesheets/main.scss new file mode 100644 index 0000000000..a0d94c17c1 --- /dev/null +++ b/app/assets/stylesheets/main.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the main 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/main_controller.rb b/app/controllers/main_controller.rb new file mode 100644 index 0000000000..86dda5ef32 --- /dev/null +++ b/app/controllers/main_controller.rb @@ -0,0 +1,5 @@ +class MainController < ApplicationController + def index + + end +end diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index ae95f7677b..4ccb1c1a3f 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -1,2 +1,14 @@ class MerchantsController < ApplicationController + + def new + end + + def create + end + + def login + end + + def logout + end end diff --git a/app/helpers/main_helper.rb b/app/helpers/main_helper.rb new file mode 100644 index 0000000000..826effed96 --- /dev/null +++ b/app/helpers/main_helper.rb @@ -0,0 +1,2 @@ +module MainHelper +end diff --git a/test/controllers/main_controller_test.rb b/test/controllers/main_controller_test.rb new file mode 100644 index 0000000000..33c8140433 --- /dev/null +++ b/test/controllers/main_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +describe MainController do + # it "must be a real test" do + # flunk "Need real tests" + # end +end From 4ee38e5c7a90a92637baf9ce855d1e955bb8a1e0 Mon Sep 17 00:00:00 2001 From: Eva Sawyer Date: Tue, 17 Oct 2017 21:43:44 -0700 Subject: [PATCH 012/223] first pass at product controller crud functions and tests --- app/controllers/products_controller.rb | 50 ++++++ config/routes.rb | 3 + db/schema.rb | 14 +- test/controllers/products_controller_test.rb | 154 ++++++++++++++++++- test/models/product_test.rb | 6 + 5 files changed, 218 insertions(+), 9 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index f1ad12ddea..e4afc8dd02 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,2 +1,52 @@ class ProductsController < ApplicationController + + def new + @product = Product.new + end + + def create + @product = Product.new(product_params) + if @product.save + flash[:status] = :success + flash[:result_text] = "Successfully created #{@product.name}, ID number #{@product.id}" + redirect_to product_path(@product) + else + flash[:status] = :failure + flash[:result_text] = "Could not create #{@product.name}, ID number #{@product.id}" + flash[:messages] = @work.errors.messages + render :new, status: :bad_request + end + end + + def edit + end + + def show + @product = Product.find(params[:id]) + end + + def update + @product.update_attributes(product_params) + if @product.save + flash[:status] = :success + flash[:result_text] = "Successfully updated #{@product.name}, ID number #{@product.id}" + redirect_to product_path(@product) + else + flash[:status] = :failure + flash[:result_text] = "Could not updated #{@product.name}, ID number #{@product.id}" + flash[:messages] = @product.errors.messages + render :new, status: :bad_request + end + end + + + def index + @products = Product.all + end + + private + + def product_params + params.require(:name).permit(:price, :stock, :retired, :description, :image_url, :merchant_i) + end end diff --git a/config/routes.rb b/config/routes.rb index 787824f888..f6c1aa65a3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,6 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html + + + resources :products end diff --git a/db/schema.rb b/db/schema.rb index df3c52c19b..cd016962ae 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: 20171017233246) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -22,6 +22,13 @@ t.datetime "updated_at", null: false end + create_table "order_items", force: :cascade do |t| + t.integer "quantity" + t.integer "product_id" + t.integer "order_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end create_table "orders", force: :cascade do |t| t.string "status" @@ -30,11 +37,6 @@ t.integer "cc_number" t.date "cc_exipration" t.integer "cc_ccv" - - create_table "order_items", force: :cascade do |t| - t.integer "quantity" - t.integer "product_id" - t.integer "order_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false end diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index 392a20e292..67dd402057 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -1,7 +1,155 @@ require "test_helper" describe ProductsController do - # it "must be a real test" do - # flunk "Need real tests" - # end + + describe "new" do + it "works" do + get new_product_path + must_respond_with :success + end + end + + describe "show" do + it "succeeds for an valid product ID" do + #when we get seed data we can clean this up + onceler = Merchant.create + Product.new(name: "blue_thneed", price: 10, merchant: onceler) + + get product_path(Product.first) + must_respond_with :success + end + + it "renders 404 not_found for a bogus product ID" do + onceler = Merchant.create + Product.new(name: "blue_thneed", price: 10, merchant: onceler) + + bogus_product_id = Product.last.id + 1 + get product_path(bogus_product_id) + must_respond_with :not_found + end + end + + describe "edit" do + it "succeeds for an extant product ID" do + #when we get seed data we can clean this up + onceler = Merchant.create + Product.new(name: "blue_thneed", price: 10, merchant: onceler) + + get edit_product_path(Product.first) + must_respond_with :success + end + + it "renders 404 not_found for a bogus product ID" do + #when we get seed data we can clean this up + onceler = Merchant.create + Product.new(name: "blue_thneed", price: 10, merchant: onceler) + + bogus_product_id = Product.last.id + 1 + get edit_product_path(bogus_product_id) + must_respond_with :not_found + end + end + + describe "index" do + it "succeeds when there are products" do + #when we get seed data we can clean this up + onceler = Merchant.create + Product.new(name: "blue_thneed", price: 10, merchant: onceler) + + get products_path + must_respond_with :success + end + + it "succeeds when there are no products" do + Product.destroy_all + get products_path + must_respond_with :success + end + end + + describe "create" do + it "creates a product with valid data" do + onceler = Merchant.create + product_data = { + product: { + name: "thneed", + price: 10, + merchant: onceler + } + } + start_count = Product.count + + post products_path, params: product_data + + must_redirect_to product_path(Product.last) + Product.count.must_equal start_count + 1 + end + + it "renders bad_request and does not update the DB for bogus data" do + product_data = { + product: { + name: "" + } + } + start_count = Product.count + + post products_path, params: product_data + + must_redirect_to product_path(Product.last) + Product.count.must_equal start_count + end + end + + + describe "update" do + it "succeeds for valid data and an valid product ID" do + onceler = Merchant.create + Product.new(name: "blue_thneed", merchant: onceler) + + product = Product.first + product_data = { + product: { + name: "cup", + price: 20, + merchant: onceler + } + } + start_count = Product.count + + patch product_path(product), params: product_data + + must_redirect_to product_path(Product.last) + Product.count.must_equal start_count + 1 + end + + it "renders bad_request for bogus data" do + onceler = Merchant.create + Product.new(name: "blue_thneed", merchant: onceler) + + product = Product.first + product_data = { + product: { + name: "" + } + } + start_count = Product.count + + patch product_path(product), params: product_data + + must_redirect_to product_path(Product.last) + Product.count.must_equal start_count + end + + it "renders 404 not_found for a bogus product ID" do + onceler = Merchant.create + Product.new(name: "blue_thneed", merchant: onceler) + + bogus_product_id = Product.last.id + 1 + get product_path(bogus_product_id) + must_respond_with :not_found + end + end + + + end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index 700aed0528..bf2c236ece 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -1,5 +1,11 @@ require "test_helper" +###None of this is working yet. +#problems to solve: +#1. Where are the layouts +#2. There is something wrong with the strong params + + describe Product do describe "relations" do From 53563e2b2264f80c786f0c1a754608b96db77f32 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Tue, 17 Oct 2017 22:15:44 -0700 Subject: [PATCH 013/223] Add header and some styling --- .DS_Store | Bin 0 -> 12292 bytes app/.DS_Store | Bin 0 -> 12292 bytes app/assets/.DS_Store | Bin 0 -> 6148 bytes app/assets/images/.DS_Store | Bin 0 -> 6148 bytes app/assets/images/birds.png | Bin 0 -> 211697 bytes app/assets/images/birdsy.png | Bin 0 -> 17600 bytes app/assets/images/cart-icon.png | Bin 0 -> 10587 bytes app/assets/stylesheets/application.css | 23 +++++++++++++++++++++++ app/controllers/.DS_Store | Bin 0 -> 6148 bytes app/views/.DS_Store | Bin 0 -> 6148 bytes app/views/layouts/.DS_Store | Bin 0 -> 6148 bytes app/views/layouts/application.html.erb | 24 +++++++++++++++++++++++- app/views/main/.DS_Store | Bin 0 -> 6148 bytes app/views/main/index.html.erb | 3 +++ config/routes.rb | 3 +++ 15 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 .DS_Store create mode 100644 app/.DS_Store create mode 100644 app/assets/.DS_Store create mode 100644 app/assets/images/.DS_Store create mode 100644 app/assets/images/birds.png create mode 100644 app/assets/images/birdsy.png create mode 100644 app/assets/images/cart-icon.png create mode 100644 app/controllers/.DS_Store create mode 100644 app/views/.DS_Store create mode 100644 app/views/layouts/.DS_Store create mode 100644 app/views/main/.DS_Store create mode 100644 app/views/main/index.html.erb diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..22caacb66066d17b2dd6ca78961ef997f57bc84c GIT binary patch literal 12292 zcmeI1&u-H|5XNVlklIQGK_F3XzR^Qf1zNR7LTEtC1dEy_2$tIBqo0}=-+W~<#!q~JZdC?fVT_MgOY z_q6W^Ps8?Tr*idf93_4jwfj0aY_%cT-U_2uJgUdTs5RJb80S{lN;-N_>u?;`ad#@$ z4iA@C7ro_MD@Tjo;o4et(OX%q9vxNQy3X|*%eNl}@tb$=KYaZ3`Rg~mBvSU%gf5%w z)Al=hcEJaYe$a5u7tQD z*l;GzoEG_Jv<_`zjy;Ud&vSwcvsbTEnY++$&>dQ*N3c`4XCjJ}VDtecxlB0g^vDJ1 z_VaI5#rdXHB|5-p5uSZa{p^T3*I%hz@o1(Mez|+7Y-`qzjb#`6^)3u6`#%GbA_UG6 zfr80(p3naq(|`XzM=O$4g@6$FQv#~E-dL|AO7H4tMDs51p}s)n!n(1sIs{GTivX@q z|6z!}2PwzYtQ{K*4~qN{pfN}z1cZPP5CTF#2nYcoAOwVf5D)@FKnMr{As__)DuLf@ ChAP_t literal 0 HcmV?d00001 diff --git a/app/.DS_Store b/app/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7082784022d1fc398589c6bf4e32d5d2d56d037d GIT binary patch literal 12292 zcmeI1%Wl(95QgU@X<{o<2~s7>&O5ruA~aRHBnkxyu|WjU1x3YfEMjErD0Z4fh?E5j zuKT_Lf@k3YD)BJkKNlj`NmlKmsB^42|H<);FW)$J#vvln8TIZHZ4;3NlUl2yThZit zX-lnOW;US$@kA*lPr~@b3uAA|nNfC(^x>p%d{Y}u?e&wag?dnUjHZX^MD ze{f(@+eT+v)vW`aDgmG+Osj@5>Hrnv7;PJ!X;q=vrmh}@2^FTq5IP*|9qA5j8=Yy@ z;Usi83A1NmDiopijyOlTlW1$@o(V94WdgExFOy3N7C%?N%dgU7*bb~TpQF$DdgEkZ zYW+XnAPkbU(Kr`{VripXv243)S2u4}Uw8ZQxSP7^DCxMvSMt*{H|=|7{34FS#n|;; z2LAZCw)HTMQa6bFp$ZOqK3t9tgQypeJMk#$B}ZL7c^LH4zS^jnuq@lMk85`(lV+># zG5r#t;Td(`)FHt?=>Gh_2LhoK7aZ8?fZ|P>cmKxI}6>`pBMeF{Ar(d zhfx?uZ!s@pEIOe+5Jp&h3NO3@kqCdocIK*KL{x=;4BwQ7&=8A{QTD|NqQr9<1uGcv zYoh*x6ts4)Bn4{#9NV{w(8Hq4!8|usT&L!CCJz zykqLEx)@Yiv%VX2itYL|&L4x2$9e`UnhPM~d2^DUIq8du=I1{y4Q@=}5(J7mc3al} zkJi8czr-FmlnF3_>rOzF4!Q>&9Ob`X!1)7~wYCF$1Cveq&9tfzbgCSOs&X8<_`?um y2d*-vZFHs;GidxGKw;pH2`~XBzyz286JP>NfC(@GCcp%k025#WOn?boDS^MYN>J1Q literal 0 HcmV?d00001 diff --git a/app/assets/.DS_Store b/app/assets/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..75cb24583fe4d6cd1377a66257dda7e993108e93 GIT binary patch literal 6148 zcmeHK&u`N(6n^eXNfZf!#9`cWgF_FU#x`zLWkW(-5JBv~&`6fh28Fn4(p9LdlmiET z{vQbb75;!7_+QHRY%{HExgrF9((`9Of6qxiTXsxDqBl-9h(lA>ovn7Txv@2C2h*LMPCK~0-I>k&x2|*J=H}gpu{?SA{=>&lpTB%nUq%A! zUD-8*zu+4x3mP4Vqav3@A92p{=oQpEhL=!%1T}|LT~ty$2J^h?9@rJVp`2Bx0m^hm z*6D>TG_6?$tO8bnl?s?W%<)$C+MrdyD)2um!23f0XY3lRHL9%xg}MR&n+PjIoqq*6 zCotGGSZhQNOz2dgP8H^gA#^(8f#G!x)*5v>33K@n=E=g`P=tCq#t#&oL|3CNtpZko zMFrM$)93Sl@Avor#U$IZ3RngHDFsAxH{9*vlg!z=^l^OF2JjbfHs;kD&r(oPM=`j3 e6tBaTAs%oA*fm&dLY5Ph2uNDv{V7Q&TjA_ft(J3ckLp%(0Id9&mS_l}5Yc zFESu&*TfJLJYkHr^_z}{*>uQWZjEqBY*VYtB`vVG7V+}2=EOPu9p*X40Y+?hamc3* zF~bGz4HoBFA@duvwU<%8mH8S+=wpCKoE0Xs|0r&~W+_8tFSIEXmH+ xQgL$DCe&N1h>Xh>S0QY~qnKmmDBht)p+AuZF*VE;>7n=^fk=ZJXW&N}cn2`$Sfl^| literal 0 HcmV?d00001 diff --git a/app/assets/images/birds.png b/app/assets/images/birds.png new file mode 100644 index 0000000000000000000000000000000000000000..f109c788000d23abde858d04f59dba3097097249 GIT binary patch literal 211697 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 z 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 odK*Rn7+(r<*&H9Hf2T^P8H81_&9*&&Pmga7~l literal 0 HcmV?d00001 diff --git a/app/assets/images/birdsy.png b/app/assets/images/birdsy.png new file mode 100644 index 0000000000000000000000000000000000000000..d1fa50afa9470777c35f1639ada3e95fc8d7dcd5 GIT binary patch literal 17600 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 literal 0 HcmV?d00001 diff --git a/app/assets/images/cart-icon.png b/app/assets/images/cart-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a50c0218856b49cd4bafe6aadc90218e48036f3e GIT binary patch literal 10587 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 literal 0 HcmV?d00001 diff --git a/app/views/.DS_Store b/app/views/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..743c2e3769b5708c1976531d08e303c8ab728549 GIT binary patch literal 6148 zcmeHKy^hmB5T4B$&c+f12?^-jL6IU5lq=5)2NI$|7;y!Mf_;vNC7(C)4-pEHTu|`a z^9Bf>g$Fo^hY8>Q#M~uN&>%#1q?vC#JF~0(Wbb&1hz+Xv22q=cY^Xr%9Lz67j0;_p zmX0_;Cg-TAq~c!652JJ~+XM^)hJk;L0rBl_Q%WJdBu*#3UmjsZ91C}$*P*S&0(LDs znii8NmD%5;NtzU8w|mT5Th^Jg+qUDlj(h%s`!pEyX;6k`RSd%XiFkStmg7kKk2p^o zKa3tHqv^1H={C>GFv&)_EKcGPQV#Z$EauYzud=u}2vl%CiOaE^R0nL^v7KT2@@&@Y zcf4Nz=Dg$0c6PcQ?^eG%pSNE-_SI{>-TM)L_2%un_a8of{vx+V49A$1iyD{k70wDx zFM>QvdG;J5qROHpkeE=Wj=zS!Zx|EwF->2Sw>iW$TVA2e0c9h~>5#^tF8kR#mgKRA zg1m(kctkGV(VSvgH3ZouyrX5uX{wG_s%)B|ileT=T1|&q=F2zy(}`8&QX63O%Wk_H zuvfE1!+>Gn&lnKrg9jDpYpfN@qXR}>0e}|5Qs9f922tZ_^flHBF#=(#6sSs>zG5&{ zj<~1ue2uk2RZdJ_KA2va=^F}@t7CporW5lO8fzFZ44h_QOFgzl|G)G5`~T@8^JEw> z4E$FNFl#T^8(>Six2|nY^jZ)43@SwA)e2<^jBdx$5v}+NR0_sC;Q)P&wL(N7=0`x% LV2okluQKohiXPrh literal 0 HcmV?d00001 diff --git a/app/views/layouts/.DS_Store b/app/views/layouts/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..aa87d117f875bcc5701a8c90a82312d7f3648c53 GIT binary patch literal 6148 zcmeHKO-lnY5PhRP6g=322ah>=D)W=Y67BjundfJ6E&n4>lCUC}Q)qBqR)%=riB zmdh{EI)6$skPIXP$v`sj69#x^tBemEvrh(+fn?x=0X-iIn_>;@9qs5~XC(k}M6(HX zeHv>_39Ny=BS$FWp+parC^5vtX)obd1A9jgheYuqG4p%zA~rko7juVH$Ly1VWMG>C zt$isIz5mbn$qW|x=8|19kPQ4+24pn9n$NhqxLd#NQ}5cscFm@ue!VIb>RXQh{?T*f e*am&Ps7}8c*gI+#wOcqb9|A^5cFDjmFz^PCraj~U literal 0 HcmV?d00001 diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index cd60004891..4d6684a2a2 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -12,8 +12,30 @@ +
+ + + +
+ +
+ <%= yield %> +
+ +
+ +
- <%= yield %> diff --git a/app/views/main/.DS_Store b/app/views/main/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ee4fb87b1625f2e0400c308fc590b042a76c5d0c GIT binary patch literal 6148 zcmeH~F-yci5QX396$gS`X}P7`etSoL$t85kT)>< zb|*90MT|=4JzlZIJ)ZH1evzK9y+?P|?{2$(*D=o@@{)f37RH%O1VlgtL_h>Y;I{<4_tNGksTxH<1VrGIfPWtf z-L*CyQsdLXA&vml8N*?m$610}JV32Yhg3#rmZj7zwRXg?EN8s5yxMd~&2m`m%=@&R zt({OTc4xdqI;^H@6af(!6FAQ0!u$V*{=@lyT%?r;?(-fIi} shW=s9jdTvtimB0xx$ste_9d_QoY!m9AvMYwk8-Mh1e}XZ1pb1+J1-6#H~;_u literal 0 HcmV?d00001 diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb new file mode 100644 index 0000000000..34095fb80c --- /dev/null +++ b/app/views/main/index.html.erb @@ -0,0 +1,3 @@ +
+ <%= image_tag "birds.png" %> +
diff --git a/config/routes.rb b/config/routes.rb index 787824f888..715c65a8a5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,6 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html + +root 'main#index' + end From ddacf9bc0db011a89ef5131e0a001e4a051a038a Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Tue, 17 Oct 2017 22:34:26 -0700 Subject: [PATCH 014/223] Add more html to main page --- app/assets/stylesheets/application.css | 4 ++-- app/views/main/index.html.erb | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 1a9e9a6836..87f4ead263 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -20,9 +20,9 @@ /*orange buttons #ff8533;*/ /*dark orange on hover #e65c00;*/ - /** { + * { border: 1px solid red; - }*/ + } .page-header { background-color: #66ad1f; diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb index 34095fb80c..34f5b93a52 100644 --- a/app/views/main/index.html.erb +++ b/app/views/main/index.html.erb @@ -1,3 +1,26 @@
<%= image_tag "birds.png" %>
+ + + +
+
+

some heading

+
+
+
+

FREE SHIPPING

+
+
+

10%off

+
+
+
+

some heading

+
+ +
From 0b5d7e60eb6cd4d2433fa1c2ee6b8a6de97cc55a Mon Sep 17 00:00:00 2001 From: VirtualLindsey Date: Tue, 17 Oct 2017 22:35:10 -0700 Subject: [PATCH 015/223] pushing work --- app/assets/javascripts/orders.js | 2 ++ app/assets/stylesheets/orders.scss | 3 ++ app/controllers/orders_controller.rb | 36 +++++++++++++++++++++ app/helpers/orders_helper.rb | 2 ++ db/migrate/20171018045939_spelling_error.rb | 5 +++ db/migrate/20171018052441_add_zipcode.rb | 5 +++ db/schema.rb | 5 +-- test/controllers/orders_controller_test.rb | 7 ++++ 8 files changed, 63 insertions(+), 2 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 db/migrate/20171018045939_spelling_error.rb create mode 100644 db/migrate/20171018052441_add_zipcode.rb 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..8b1bc01a16 --- /dev/null +++ b/app/controllers/orders_controller.rb @@ -0,0 +1,36 @@ +class OrdersController < ApplicationController + def index + @orders = Order.all + end + + def new + @order = Order.new + end + + def create + end + + def update + @order = Order.find(params[:id]) + + @order.status = params[:status] + @order.customer_name = params[:customer_name] + @order.customer_email = params[:customer_email] + @order.customer_address = params[:customer_address] + @order.cc_number = params[:cc_number] + @order.cc_expiration = params[:cc_expiration] + @order.cc_ccv = params[:cc_ccv] + @order.zip_code = params[:zip_code] + + result = @order.save + + if result + flash[:notification] = 'Order was successfully updated' + end + end + + def show + @order = Order.find(params[:id]) + 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/db/migrate/20171018045939_spelling_error.rb b/db/migrate/20171018045939_spelling_error.rb new file mode 100644 index 0000000000..c91828a1d4 --- /dev/null +++ b/db/migrate/20171018045939_spelling_error.rb @@ -0,0 +1,5 @@ +class SpellingError < ActiveRecord::Migration[5.1] + def change + rename_column :orders, :cc_exipration, :cc_expiration + end +end diff --git a/db/migrate/20171018052441_add_zipcode.rb b/db/migrate/20171018052441_add_zipcode.rb new file mode 100644 index 0000000000..d426c9a4ff --- /dev/null +++ b/db/migrate/20171018052441_add_zipcode.rb @@ -0,0 +1,5 @@ +class AddZipcode < ActiveRecord::Migration[5.1] + def change + add_column :orders, :zip_code, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index f4afde3118..5ee50235cd 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: 20171018001235) do +ActiveRecord::Schema.define(version: 20171018052441) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -36,10 +36,11 @@ t.string "customer_email" t.string "customer_address" t.string "cc_number" - t.date "cc_exipration" + t.date "cc_expiration" t.string "cc_ccv" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "zip_code" end create_table "products", force: :cascade do |t| diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb new file mode 100644 index 0000000000..68784595f3 --- /dev/null +++ b/test/controllers/orders_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +describe OrdersController do + # it "must be a real test" do + # flunk "Need real tests" + # end +end From f77ac52f7cbc83b4534fbb78dde0ee2afb4d57c6 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Tue, 17 Oct 2017 22:44:05 -0700 Subject: [PATCH 016/223] Fix layout on main page --- app/assets/stylesheets/application.css | 4 +-- app/views/layouts/application.html.erb | 2 +- app/views/main/index.html.erb | 44 ++++++++++++++------------ 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 87f4ead263..1a9e9a6836 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -20,9 +20,9 @@ /*orange buttons #ff8533;*/ /*dark orange on hover #e65c00;*/ - * { + /** { border: 1px solid red; - } + }*/ .page-header { background-color: #66ad1f; diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 4d6684a2a2..797584e94f 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -15,7 +15,7 @@
diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb index 34f5b93a52..cc519b6250 100644 --- a/app/views/main/index.html.erb +++ b/app/views/main/index.html.erb @@ -2,25 +2,29 @@ <%= image_tag "birds.png" %> - +
+ -
-
-

some heading

-
-
-
-

FREE SHIPPING

-
-
-

10%off

-
-
-
-

some heading

-
-
+
+
+

some heading

+
+
+
+

FREE SHIPPING

+
+
+

10%off

+
+
+
+

some heading

+
+ +
+ +
From f667a65b019a171830850dcdcf4504d57814bbcc Mon Sep 17 00:00:00 2001 From: VirtualLindsey Date: Tue, 17 Oct 2017 22:51:26 -0700 Subject: [PATCH 017/223] adding more controller functions --- app/controllers/orders_controller.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 8b1bc01a16..c621225398 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -8,6 +8,28 @@ def new end def create + if params[:work][:status] == " " + flash[:failed] = 'Enter a status' + else + @order = Order.new( + status: 'pending', + customer_name: params[:order][:customer_name], + customer_email: params[:order][:customer_email], + customer_address: params[:order][:customer_address], + cc_number: params[:order][:cc_number], + cc_expiration: params[:order][:cc_expiration], + cc_ccv: params[:order][:cc_ccv], + zip_code: params[:order][:zip_code], + ) + result = @order.save + + if result + flash[:success] = 'Your order has been placed' + redirect_to orders_path + else + flash[:failure] = 'Something went wrong. Please place your order again' + redirect_to orders_path + end end def update @@ -26,6 +48,8 @@ def update if result flash[:notification] = 'Order was successfully updated' + else + flash[:failure] = 'Order was not updated' end end From 8b6bcbf03f8aaf232b783e8a19fda455545203ac Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Tue, 17 Oct 2017 22:55:36 -0700 Subject: [PATCH 018/223] Start doing ads on main page --- app/assets/images/.DS_Store | Bin 6148 -> 6148 bytes app/assets/images/truck.gif | Bin 0 -> 4667 bytes app/assets/stylesheets/application.css | 10 ++++++++-- app/views/main/index.html.erb | 9 ++++++--- 4 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 app/assets/images/truck.gif diff --git a/app/assets/images/.DS_Store b/app/assets/images/.DS_Store index d5b9b6a2410a92ed34440c63740bfd7fa2b869db..e67924d3de1b2b9d56ff7b9a109f5e019c922f1f 100644 GIT binary patch delta 111 zcmZoMXfc@J&&akhU^gQp+h!gnWkyYPhJ1!1hD3%uhIEEh23>{{Ag`1mnIRj9 G%MSo%t-G%WyZ~OnX_0XHsoz)=lIJH0HHSu1ONa4 diff --git a/app/assets/images/truck.gif b/app/assets/images/truck.gif new file mode 100644 index 0000000000000000000000000000000000000000..bed690e3c2f32e5a6138e733da1811eb5ca9f766 GIT binary patch literal 4667 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 literal 0 HcmV?d00001 diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 1a9e9a6836..d7f977b832 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -20,9 +20,9 @@ /*orange buttons #ff8533;*/ /*dark orange on hover #e65c00;*/ - /** { + * { border: 1px solid red; - }*/ + } .page-header { background-color: #66ad1f; @@ -38,3 +38,9 @@ .nav a:hover { background-color: #e65c00; } + + .ads { + height: 10rem; + background-color: pink; + padding: 1rem; + } diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb index cc519b6250..8934fbce68 100644 --- a/app/views/main/index.html.erb +++ b/app/views/main/index.html.erb @@ -14,10 +14,13 @@

some heading

-
-

FREE SHIPPING

+
+

+ <%= image_tag "truck.gif" %> + FREE SHIPPING

+

on order over $30

-
+

10%off

From 16d0fedc228ad925a2ac6dfab0ff8bb4442b78a0 Mon Sep 17 00:00:00 2001 From: VirtualLindsey Date: Tue, 17 Oct 2017 23:02:53 -0700 Subject: [PATCH 019/223] creating routes and views --- app/views/orders/index.html.erb | 0 app/views/orders/new.html.erb | 0 app/views/orders/show.html.erb | 0 app/views/orders/update.html.erb | 0 config/routes.rb | 7 ++++++- 5 files changed, 6 insertions(+), 1 deletion(-) 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 diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/views/orders/new.html.erb b/app/views/orders/new.html.erb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/views/orders/update.html.erb b/app/views/orders/update.html.erb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/config/routes.rb b/config/routes.rb index 787824f888..9441c0cab9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,8 @@ Rails.application.routes.draw do - # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html + get '/orders', to: 'orders#index', as: 'orders' + get '/orders/new', to: 'orders#new', as: 'new_order' + post '/orders', to: 'orders#create' + patch '/orders/:id', to: 'orders#update' + + resources :orders end From b3a1b608be64d41febd82c2c3641864c6d616967 Mon Sep 17 00:00:00 2001 From: VirtualLindsey Date: Tue, 17 Oct 2017 23:15:02 -0700 Subject: [PATCH 020/223] adding index and show pages --- app/controllers/orders_controller.rb | 1 + app/views/orders/index.html.erb | 14 ++++++++++++++ app/views/orders/show.html.erb | 13 +++++++++++++ config/routes.rb | 1 + 4 files changed, 29 insertions(+) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index c621225398..e5313bd894 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -29,6 +29,7 @@ def create else flash[:failure] = 'Something went wrong. Please place your order again' redirect_to orders_path + end end end diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb index e69de29bb2..01d1e0dec5 100644 --- a/app/views/orders/index.html.erb +++ b/app/views/orders/index.html.erb @@ -0,0 +1,14 @@ +

All Orders

+ +<% @orders.each do |order| %> +
    +
  • ID: <%= link_to order.id, order_path(order) %>
  • +
  • Status: <%= order.status %>
  • +
  • Customer Name: <%= order.customer_name %>
  • +
  • Customer Email Address: <%= order.customer_email %>
  • +
  • Credit Card Number: <%= order.cc_number %>
  • +
  • Credit Card Expiration Date: <%= order.cc_expiration %>
  • +
  • Credit Card CCV: <%= order.cc_ccv %>
  • +
  • Billing Zipcode: <%= order.zip_code %>
  • +
+<% end %> diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb index e69de29bb2..a6b1d8dcb7 100644 --- a/app/views/orders/show.html.erb +++ b/app/views/orders/show.html.erb @@ -0,0 +1,13 @@ +

Order#: <%= @order.id %>

+ +
    +
  • Status: <%= @order.status %>
  • +
  • Customer Name: <%= @order.customer_name %>
  • +
  • Customer Email Address: <%= @order.customer_email %>
  • +
  • Credit Card Number: <%= @order.cc_number %>
  • +
  • Credit Card Expiration Date: <%= @order.cc_expiration %>
  • +
  • Credit Card CCV: <%= @order.cc_ccv %>
  • +
  • Billing Zipcode: <%= @order.zip_code %>
  • +
+ +<%= link_to 'All Orders', orders_path %> diff --git a/config/routes.rb b/config/routes.rb index 9441c0cab9..dcb35a8cd7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,7 @@ Rails.application.routes.draw do get '/orders', to: 'orders#index', as: 'orders' get '/orders/new', to: 'orders#new', as: 'new_order' + get '/orders/:id', to: 'orders#show', as: 'order' post '/orders', to: 'orders#create' patch '/orders/:id', to: 'orders#update' From 1b0e3ec5336d1671557ace2d42ebe3b6a38bffd7 Mon Sep 17 00:00:00 2001 From: VirtualLindsey Date: Tue, 17 Oct 2017 23:45:23 -0700 Subject: [PATCH 021/223] adding edit and create --- app/controllers/orders_controller.rb | 23 +++++++++++-------- app/views/orders/edit.html.erb | 33 +++++++++++++++++++++++++++ app/views/orders/new.html.erb | 34 ++++++++++++++++++++++++++++ app/views/orders/show.html.erb | 1 + app/views/orders/update.html.erb | 0 config/routes.rb | 3 ++- 6 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 app/views/orders/edit.html.erb delete mode 100644 app/views/orders/update.html.erb diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index e5313bd894..2f8fddb7fb 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -8,7 +8,7 @@ def new end def create - if params[:work][:status] == " " + if params[:order][:status] == " " flash[:failed] = 'Enter a status' else @order = Order.new( @@ -36,14 +36,14 @@ def create def update @order = Order.find(params[:id]) - @order.status = params[:status] - @order.customer_name = params[:customer_name] - @order.customer_email = params[:customer_email] - @order.customer_address = params[:customer_address] - @order.cc_number = params[:cc_number] - @order.cc_expiration = params[:cc_expiration] - @order.cc_ccv = params[:cc_ccv] - @order.zip_code = params[:zip_code] + @order.status = params[:order][:status] + @order.customer_name = params[:order][:customer_name] + @order.customer_email = params[:order][:customer_email] + @order.customer_address = params[:order][:customer_address] + @order.cc_number = params[:order][:cc_number] + @order.cc_expiration = params[:order][:cc_expiration] + @order.cc_ccv = params[:order][:cc_ccv] + @order.zip_code = params[:order][:zip_code] result = @order.save @@ -52,6 +52,11 @@ def update else flash[:failure] = 'Order was not updated' end + redirect_to orders_path + end + + def edit + @order = Order.find(params[:id]) end def show diff --git a/app/views/orders/edit.html.erb b/app/views/orders/edit.html.erb new file mode 100644 index 0000000000..9cca8e7ac1 --- /dev/null +++ b/app/views/orders/edit.html.erb @@ -0,0 +1,33 @@ +<%= form_for @order do |f| %> + <%= f.label :status %> + <%= f.select :status, [ + ['pending', 'pending'], + ['paid', 'paid'], + ['complete', 'complete'], + ['closed', 'closed'] + ] %> + + <%= f.label :customer_name %> + <%= f.text_field :customer_name %> + + <%= f.label :customer_email %> + <%= f.text_field :customer_email %> + + <%= f.label :customer_address %> + <%= f.text_field :customer_address %> + + <%= f.label :cc_number %> + <%= f.text_area :cc_number %> + + <%= f.label :cc_expiration %> + <%= f.text_area :cc_expiration %> + + <%= f.label :cc_ccv %> + <%= f.text_area :cc_ccv %> + + <%= f.label :zip_code %> + <%= f.text_area :zip_code %> + + <%= f.submit%> + +<% end %> diff --git a/app/views/orders/new.html.erb b/app/views/orders/new.html.erb index e69de29bb2..9def79a9ef 100644 --- a/app/views/orders/new.html.erb +++ b/app/views/orders/new.html.erb @@ -0,0 +1,34 @@ +

Create new order

+<%= form_for @order do |f| %> + <%= f.label :status %> + <%= f.select :status, [ + ['pending', 'pending'], + ['paid', 'paid'], + ['complete', 'complete'], + ['closed', 'closed'] + ] %> + + <%= f.label :customer_name %> + <%= f.text_field :customer_name %> + + <%= f.label :customer_email %> + <%= f.text_field :customer_email %> + + <%= f.label :customer_address %> + <%= f.text_field :customer_address %> + + <%= f.label :cc_number %> + <%= f.text_area :cc_number %> + + <%= f.label :cc_expiration %> + <%= f.text_area :cc_expiration %> + + <%= f.label :cc_ccv %> + <%= f.text_area :cc_ccv %> + + <%= f.label :zip_code %> + <%= f.text_area :zip_code %> + + <%= f.submit%> + +<% end %> diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb index a6b1d8dcb7..1a1caab3da 100644 --- a/app/views/orders/show.html.erb +++ b/app/views/orders/show.html.erb @@ -11,3 +11,4 @@ <%= link_to 'All Orders', orders_path %> +<%= link_to 'Edit Order', edit_order_path %> diff --git a/app/views/orders/update.html.erb b/app/views/orders/update.html.erb deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/config/routes.rb b/config/routes.rb index dcb35a8cd7..8f0c152ecc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,8 +1,9 @@ Rails.application.routes.draw do get '/orders', to: 'orders#index', as: 'orders' get '/orders/new', to: 'orders#new', as: 'new_order' - get '/orders/:id', to: 'orders#show', as: 'order' post '/orders', to: 'orders#create' + get '/orders/:id', to: 'orders#show', as: 'order' + get '/orders/:id/edit', to: 'orders#edit', as: 'edit_order' patch '/orders/:id', to: 'orders#update' resources :orders From 90d57f460b9d44a29a93aef74c3416530a0d9c9d Mon Sep 17 00:00:00 2001 From: VirtualLindsey Date: Tue, 17 Oct 2017 23:56:39 -0700 Subject: [PATCH 022/223] adding tests for model --- app/models/order.rb | 4 ++++ test/models/order_test.rb | 20 +++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/app/models/order.rb b/app/models/order.rb index 10281b3450..2fc8a8dd32 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,2 +1,6 @@ class Order < ApplicationRecord + validates :status, + :customer_name, :customer_email, :customer_address, + :cc_number,:cc_expiration, :cc_ccv, + :zip_code, presence: true end diff --git a/test/models/order_test.rb b/test/models/order_test.rb index df80f10fb6..715e3ad5e9 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -1,9 +1,23 @@ require "test_helper" describe Order do - let(:order) { Order.new } + it "must be invalid" do + order = Order.new + result = order.valid? + result.must_equal false + end - it "must be valid" do - value(order).must_be :valid? + it 'must be valid' do + order = Order.new + order.status = 'pending' + order.customer_name = 'Sue' + order.customer_email = 'Sue@gmail.com' + order.customer_address = '123 internet street' + order.cc_number = '123123123' + order.cc_expiration = '2020-10-01' + order.cc_ccv = '980' + order.zip_code = '98101' + result = order.valid? + result.must_equal true end end From f7c1f44044a037153bfd61561239fb23404e8d26 Mon Sep 17 00:00:00 2001 From: VirtualLindsey Date: Wed, 18 Oct 2017 00:22:19 -0700 Subject: [PATCH 023/223] adding tests --- app/controllers/application_controller.rb | 6 +++ app/controllers/orders_controller.rb | 3 +- test/controllers/orders_controller_test.rb | 63 ++++++++++++++++++++-- test/fixtures/orders.yml | 22 +++++++- 4 files changed, 88 insertions(+), 6 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1c07694e9d..f6c1df3ce5 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,3 +1,9 @@ class ApplicationController < ActionController::Base protect_from_forgery with: :exception + rescue_from ActiveRecord::RecordNotFound, :with => :render_404 + + + def render_404 + render :file => "#{Rails.root}/public/404.html", :status => 404 + end end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 2f8fddb7fb..748b2e7232 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -9,7 +9,8 @@ def new def create if params[:order][:status] == " " - flash[:failed] = 'Enter a status' + flash[:failure] = 'Please enter the required fields.' + redirect_to new_order_path else @order = Order.new( status: 'pending', diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 68784595f3..0fa87a7f52 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -1,7 +1,64 @@ require "test_helper" describe OrdersController do - # it "must be a real test" do - # flunk "Need real tests" - # end + describe 'primary pages' do + it "must be get index page" do + get orders_path + assert_response :success + end + + it 'must get show page' do + get orders_path(orders(:one).id) + assert_response :success + end + + it 'must not find invalid show page' do + get order_path(999999) + must_respond_with :missing + end + + it 'must get edit page' do + get edit_order_path(orders(:two).id) + assert_response :success + end + + it 'must not find an invalid edit page' do + get edit_order_path(99999) + must_respond_with :missing + end + + it 'must get new order page' do + get new_order_path + assert_response :success + end + end + + describe 'Validations' do + it 'adds a new valid order' do + post orders_path, params: { + order: { + status: 'john', + customer_name: 'creator 1', + customer_email: 'john@gmail.com', + customer_address: '123 5th ave', + cc_number: '12312312312', + cc_expiration: '2019-10-10', + cc_ccv: '907', + zip_code: '98101' + } + } + must_respond_with :redirect + end + + it 'adds an new invalid order' do + post orders_path, params: { + order: { + status: 'john', + } + } + must_respond_with :redirect + end + + + end end diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index dc3ee79b5d..0370a5e776 100644 --- a/test/fixtures/orders.yml +++ b/test/fixtures/orders.yml @@ -4,8 +4,26 @@ # model remove the "{}" from the fixture names and add the columns immediately # below each fixture, per the syntax in the comments below # -one: {} +one: + id: 1, + customer_name: 'sue' + customer_email: 'sue@gmail.com' + customer_address: '420 blaze ave' + cc_number: '12312312' + cc_expiration: '2020-01-01' + cc_ccv: '908' + zip_code: '98101' + # column: value # -two: {} +two: + id: 2, + customer_name: 'suzie' + customer_email: 'suzie@gmail.com' + customer_address: '123 internet ave' + cc_number: '333333' + cc_expiration: '2222-22-22' + cc_ccv: '222' + zip_code: '22222' + # column: value From 8fe0af37d5a4ac3985c11dcdbec8d540424ea910 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Wed, 18 Oct 2017 09:37:36 -0700 Subject: [PATCH 024/223] Add styles to ads --- app/assets/images/.DS_Store | Bin 6148 -> 6148 bytes app/assets/images/phone.png | Bin 0 -> 5830 bytes app/assets/images/{truck.gif => truck-1.gif} | Bin app/assets/images/truck.png | Bin 0 -> 3126 bytes app/assets/stylesheets/application.css | 30 ++++++++++++++++--- app/views/main/index.html.erb | 23 +++++++++----- 6 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 app/assets/images/phone.png rename app/assets/images/{truck.gif => truck-1.gif} (100%) create mode 100644 app/assets/images/truck.png diff --git a/app/assets/images/.DS_Store b/app/assets/images/.DS_Store index e67924d3de1b2b9d56ff7b9a109f5e019c922f1f..786bfb95480ed40af63f945548b466163b40e307 100644 GIT binary patch delta 113 zcmZoMXfc=|#>B!ku~2NHo+2ar#(>?7i&&T#**EhrJ!aJ9WGG=MVkl)uX2@pHV<=$A zV@UVR$xlwo$xmWnU=RReHz1w?#9aUXZ~n;qnsGBb2R{eUKp^Kk^JIPzM-D~?1}2~a KhRqQoYnTBnIU5WB delta 67 zcmZoMXfc=|#>B)qu~2NHo+2aL#(>?7jBJ~ESRONO7UK|Pnb^R-nVo~51E^%PAjfy+ V$^0UY91K9f$iTp|IYML&GXOMN4*~!H diff --git a/app/assets/images/phone.png b/app/assets/images/phone.png new file mode 100644 index 0000000000000000000000000000000000000000..facc46d7fde9d3232eda2f298216016af47ba171 GIT binary patch literal 5830 zcmZ`+<6pgazwL6C+cr5iz%ZVnI$Q8>CgMIE} z#OQW|palr!K}e4ex(r^CjP%|BDT&YsA!wcJR#q6`TY2F0Lz_f;dZ|)>{q-?#fCYSs zyF-KZ+w8M{JkvWlW=sIC!i=!EA1ehCn50$TNA>0zWB4+e<4vf*8}dAy{7R>LNMl*EF8G0E+4fmE1Ax3?pPIVOQU&mn zrW=p$u;w{Lyip*fI*vF80MMOs}6qwYj(asZyi)?1Mn5z1!8#B*u3$lXD!`?Gqj zJ2L^Uq@IuK;hw69%Le=yeu{t^=M)7r7G1}5oA{$D(9x0Z?6%Ea$HFR|pVp(qpf~Ev z8S5b;M+TOoyXtUQ$=5~>xMtSNq^)mH{sL%l#FR#^SE`>d0M1_k8dkC{=t3Qg5_&iA z+3=zc4;{Xt<=XRd?Y=|h209OSgo@mxj~t`4#fmAUps$t51T7Vi#U;fb^GvR-9Ipj#u>Z`uKcz4m7L{MNJ*mxi zV}Ngnh{hjftU+f9fZS_zW+y3cpznb`kpS*sd#g=Ve9gDmH{MS>_w;xMkxuKXGE7?A z*Z8p(t}OZ7R0XTS4qd=kaae9YafP6~{6KCK0#JaU3;GHJAUHsY2t5UzR|#k?vIuuv-o!UlJbtjT+lWnoctF0HHlA(td<>ZVwyIR$Ws7mv#EkawOohNQg^W1DLYn4irTDK~=$K)7rfHPq{ZyM_y0CRKZPQsZ z751{Pe)5|#+Jm8>*V4d~Mvz2p&^d#_Q*SAx%AB^p|{vdz4)mZxe4z@TP zJq-K6my9V4%nr<-iKwx6upfhoyM;8NrRr`>p+sK224);}G4nF5${<#?L{jBYW{OYD z9O(_v&&qa8hO82-ZH$RSq84CRN?mCq^=jr^24j|&2~rwK?5w2fDj)^f1vL?sW@#^J zFS(*m1f@>Xkn*&aY(4chd0!P@K5(L7>P712P*q|@ynXUPst=2L(p;)Xsxfaan=zxm z%2V;fAE0KJbe9&ipjJCialN5iB1BmsBR|6Ln!^j_^G zOA#Zr>{OB0t`rWom97`5UeIz>)grr8+4}Ze!<~O+& z{6tj*ON7B;u@^$y&4^9Jl5mZ!(Q_+D@*SrW=Z|EjWUFMfi8QzL$La62k;u{dY1=22ENXvg#lBAbiF(nkRXZnz>cEg&p7yegEOkzYL2eQ8JlbrFoHg z9i};^1?%Ro%i}91I1BU&#QNWxH-3#glibv2t&PZ5PEd{>`lvNOz4Fg(AIPu$r>k43IQvtiM||){fmh}o7oJ2EBr2PHncSHBh+B*2fSX>IL-z&5v0=aV zzGtyF!`{%`cOcYm)4YDXczOGGRTwm`2V4GNMK5TVU$|bAWy5k(<1mgvG_!OrU(>#=}6JOW=fL!Bw zEqGzZo-TRQUzUyET0TKDys8U(B8E+|QxZG2UZT;_TuUVkly0 zV@cw@!Fl!KJ4R0zS{FQ!o^R5a**G$aMATQvTOuV9cSF7`<0W9hMsnn=sAL zD&P<-n+#*X-Tf)_q3i9jJz-VI zY_-8svzmutSIhcU`$4QDgQL>I>4@S;v?a}|Q{>9D=1>gCP;n~i8J6t?wI^;z8un98Odr{$5#eEx9>yH3xjAGZF0 zh#x1*$`r}<@H?074>^m9pa>Jyag%Im*qY3)uB~1ffu`0Noi)3bEw!N@zNA)ISBn^m z`DXjJ9fdwd&(gtjQj8D%Z1;YjIJWJ%)IX+dR>icx@ZGsLMDeX$xA-Dsp0jDtqcHD} zdE0%Sjs8jO`K~-pV3oZzk{b1X|7i1Qez=*>hO5q*Q!Z8YICDE^Rn~TS_;bz#Q6Fv{ z8~R6%?>YIdM!n|+q71>M*r2!%t^y-qcd%vey34-P5m@TfW=IFeQ{zqYL`ANj2dd55 zY^e9te&QfqN@bKgi(hcdq$h~GO@zg17pjh6EG zf%9-XQL#Bov5{RRNwk^C>w02x`7002Ihvb@Y^Pqd>GYAP`UnTWj_85Tb|)+M#uoZO<0;B!aK9^(=>A|bQ&3E$`ZD%o;4E;Jd^)6CEuDki0n8b% zq#xkQ4z|E+=5JzLWdCgrp9wb}xp!)y#tYFc_H=4qdR`4}_+uAqcxxBy-%njVaeg#RNCH=IoT2p46X;3k z3CoV5lE+U<96KcE5iT<(xjWzwnmK)Nvi;f{JO1jUQ30Y-)tm4JD#9moTN))7(VP~H zGs>e5sI$dk_I?_cS)}(;OoMtxA|txI6p!_A6uU8|KdvMNZvrL(KM+rM+DjmHDtHG3 z6LgK>p{;YycaZ?BWF$dM21P3B36uitt7L~ytUKSHE>I7;#a&<4cDXdr+9!}sRl5q{ z=>6p(t0Pk4IMp zJH7OT4A||(M$@fHr?1$AIs`0KcnyF+4C<*3>J1Fu5swscQtEi)>i+Z-Y{ey)Kk>hy z7La6V3en*bA#{06sbd)6J^N!zGeU{l&MXE@I6Aea67{71l3Qe?mW;S1wxJ)j*?Bs{ zK7=QUJ5MGDmH&hdc>X5qidHV01y$<6w_O2}sRmE`v$OFO6ZIT$PEq=2H-e9Q3|4L< zR%pG?f1em0Fdp8wzVM^=BXsW%!k@3&(iB8Tv3?gn%$!oWP2$#ho!VttC~@J?r&%my zqMw!iE?{B6Alf-#N}+{;BSwDl8|rP@#CvH|a6$Y(&ya*_O8!%o?}v`6+IK^KZjI=Y zpn*e&Tf!Mli(gTRRg}8>sy-9$jRq2%X?2k6x=H_G$tRXZo%Oz^kkfeWmolJK-wG-A zqRl|Ex(@!osN9Nqvih@5DEf0oPELE;`M|o?`d3E}k9zQQMQyVY!(4ZQOtcDzK(r7w ziH`cmk3R^&L%eDfU!O99C5z_n-#$y8`<#L~e5|xU z5&ZG(GHHmrC(m&uOn#xXURL%+mp)&=uE3##cskmF30{cbH2?kJn%n(@3aOYWWcB{y zV9d6bl*Bqer-Znto|MnoEbTa;dOq#*OlV&C9X94V(Eg0V=(;M+#*hkaeNc?X(u z+WOw`NXgqI4VDTX6QaXcKkXC`li`C-+3gKTQ_x0dbo$PFT#*3 zXzgx8gdFD+C>+24=RZ-MSGNW8*@`Vi;z7@Vn$S)0LWoLWCC?_iKF@WTxp57oP0ZWi zG3C85Lw4aUe|=1O#U~om*p1FDh|be%>SsK0-g74wlL&T1r-$`s;9@jr&TGIYrIF2q z4awn2Z@}DS*OEp~BR0IRG)GM|nOrJ9&@V7qFg}ldda$;`f5_=NOQNY>5!h&Bmv{*$ zaQwz{|M`jJff?lX`o&4vwU72VqeH_=F}rjB3ZF&`x*w6dy{I`};C6Vw=Vqm$H2N~o)6ofAJgs+}^=fHq za?e%w){lwT8qYhI2WICZ-OSX$|L{=3$BjoDGN)iSUb9NB$*L3KIU|-ldzcd#%@w{% zh$^2Qqc_}>3kNUEz)O? zTat4Q+NJ;iteBjv=}y5*61Y_-Lf*xw z(D1?Hy+yTFWb;e4{O|*MCN967)8Day34vvL-K%c1?-= z?kE#>?pV>Rz^>GPZgDc#K5X=^IBd8|W?e4UG>p)V4TCB7&f3x_pK2Os;0XvXf>XS# znNdmlgdgz1E6!l&7j<4aiuw`WC&hVK2WbFt zyKj)qjQbPDtgmnI&|C=aupJtb_hLH;2EICr#k#gCxWSw9CiDM%xbH)fzLx7}@hz36 zqOS?3(KBjUWyIqwqpb7y2G!wb0T?mjR)^yIDvYgvT3-EaV*!P=mELesQ84fpJh-@% zuWi{Cg+rWP=Gw&Crv?wXMiewW#Itp_7byi{)c947)`U?k-ai3@t4~6d>G#4CR(n1H zrYf(Vq7579XD;~?~6Rxn*bEjlmQ_|4FR^u$P*$0X9U#yJpJ1 ze=WFgzXmt4)ga0&Amj_Iu}STZkI4wHD(Tf^eyjiu)#8wLk;3r2MG?5Wxch7-&+$n@ z4)`(A%Uh`h^Nttrwy&hto9RhDz98u$HXJMB;9RX$?3&P}M$s#lQ{B^@HK`t%zOxD8 za9H+w+NA=v$Z0vqQ`(5MT}S7UBX6}2IZ6{W$HX?IBfQXYE}<;D6#rB-&NVf3YWLnO zhD&XFk2(_8RgvW`30TD$piMOMpY|YPMlMfW{0*L(J9;v>EGqgKM4{0%hjW_lLRI#< zXnBG==D&X5IaVv4yTLP^R|BpInDh2kdyGU%LP&`aW3}rOywaWmE7fGmXu2*tOyHwD`=cgsnPenWoqB}fgD`B?El^4rNn7`7*ALYdv@FckoJN9z63y7K~26| I)+F$M0F(Y*Bme*a literal 0 HcmV?d00001 diff --git a/app/assets/images/truck.gif b/app/assets/images/truck-1.gif similarity index 100% rename from app/assets/images/truck.gif rename to app/assets/images/truck-1.gif diff --git a/app/assets/images/truck.png b/app/assets/images/truck.png new file mode 100644 index 0000000000000000000000000000000000000000..fa5143034fd7db023bb55c7a1f4966c632082f79 GIT binary patch literal 3126 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 heading
-
-

- <%= image_tag "truck.gif" %> - FREE SHIPPING

-

on order over $30

+
+
+ <%= image_tag "truck.png" %> +
+
+

FREE SHIPPING

+

on order over $50

+
-
-

10%off

+
+
+ <%= image_tag "phone.png" %> +
+
+

GIVE US A CALL

+

1-800-11-BIRDS

+
From b8927c14ed16754abde9c42a5569b40bf37e0b7f Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Wed, 18 Oct 2017 10:47:49 -0700 Subject: [PATCH 025/223] Change phone number --- app/views/main/index.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb index 57caaec0e1..90c18646b0 100644 --- a/app/views/main/index.html.erb +++ b/app/views/main/index.html.erb @@ -29,7 +29,7 @@

GIVE US A CALL

-

1-800-11-BIRDS

+

1-800-00-BIRDS

From b01c1464dada1b5f57d32d94969cecc5aaf61cac Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Wed, 18 Oct 2017 11:33:48 -0700 Subject: [PATCH 026/223] ?? --- app/assets/images/.DS_Store | Bin 6148 -> 6148 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/app/assets/images/.DS_Store b/app/assets/images/.DS_Store index 786bfb95480ed40af63f945548b466163b40e307..a9a0a77e8cee6185316e0cf6ea7561f79a9d2d56 100644 GIT binary patch delta 127 zcmZoMXfc@J&&ahgU^g=(*JK_RQ(i8HB!*0eB8C)(Vus4ezgVRw_p{h+E@aVRx>N`M+l8Il>Y8FU#88T1&^fkvcx=Hw?Q<>V(Z aFfa%J@fjeV@gE2_zhG@<+|17LmmdHn2_p>v delta 40 wcmZoMXfc@J&&a+pU^g=(`(z##)6JzUF^rR$*@8BAv(+$8Y?!l|o#QV*0Qdn6q5uE@ From a0537f93c0b2875db40c77d7e462e4fd64ca612f Mon Sep 17 00:00:00 2001 From: Rebecca Bergena Date: Wed, 18 Oct 2017 11:52:27 -0700 Subject: [PATCH 027/223] order items controller and model --- app/controllers/order_items_controller.rb | 59 +++++++++++++++++++ app/models/order_item.rb | 2 + config/routes.rb | 3 + .../order_items_controller_test.rb | 36 +++++++++++ test/models/order_item_test.rb | 20 ++++++- 5 files changed, 117 insertions(+), 3 deletions(-) diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb index 357e7f5c80..c7b9f5fe31 100644 --- a/app/controllers/order_items_controller.rb +++ b/app/controllers/order_items_controller.rb @@ -1,2 +1,61 @@ class OrderItemsController < ApplicationController + + def index + #maybe just for that merchant + @order_items = OrderItem.all + end + + def create + @order_item = OrderItem.new(order_item_params) + if @order_item.save + # probably only need flash messages for the order? + # flash[:status] = :success + # flash[:result_text] = "Successfully created order item" + redirect_to root_path + else + # + # render :new + flash[:status] = :failure + flash[:result_text] = "Could not create order item" + flash[:details] = @order_item.errors.messages + end + end + + def update + @order_item = OrderItem.find(params[:id]) + @order_item.update_attributes(order_item_params) + if @order_item.save + redirect_to root_path + else + # render :edit + end + end + + @work.update_attributes(work_params) + if save_and_flash(@work, "update") + redirect_to work_path(@work.id) + else + render :edit, status: :bad_request + end + def destroy + current_merchant = Merchant.find_by(id: session[:logged_in_merchant]) + @order = OrderItem.find_by(id: params[:id]) + if current_merchant == order.product.merchant + @order.destroy + flash[:status] = :success + flash[:result_text] = "Successfully destroyed order item." + redirect_to root_path + else + flash[:status] = :failure + flash[:message] = "You must be the merchant for that item to do that!" + redirect_to root_path + return + end + end + + private + + def order_item_params + return params.require(:orderitem).permit(:product_id, :quantity, :order_id) + end end diff --git a/app/models/order_item.rb b/app/models/order_item.rb index acc6099fd0..bc16957ca1 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -1,2 +1,4 @@ class OrderItem < ApplicationRecord + belongs_to :order + belongs_to :product end diff --git a/config/routes.rb b/config/routes.rb index 787824f888..c718db5468 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,6 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html + + resources :orderitems, only: [:create, :index, :destroy, :update] + end diff --git a/test/controllers/order_items_controller_test.rb b/test/controllers/order_items_controller_test.rb index 96e3063c9c..81e9e3fb9f 100644 --- a/test/controllers/order_items_controller_test.rb +++ b/test/controllers/order_items_controller_test.rb @@ -4,4 +4,40 @@ # it "must be a real test" do # flunk "Need real tests" # end + describe "index" do + it "succeeds when there are order items" do + OrderItem.count.must_be :>, 0, "No order items in the test fixtures" + get orderitems_path + must_respond_with :success + end + + it "succeeds when there are no order items" do + OrderItem.destroy_all + get orderitems_path + must_respond_with :success + end + end + describe "destroy" do + it "succeeds for an extant order item ID" do + order_item_id = OrderItem.first.id + + delete work_path(order_item_id) + must_redirect_to root_path + + OrderItem.find_by(id: order_item_id).must_be_nil + end + + # it "renders 404 not_found and does not update the DB for a bogus work ID" do + # start_count = OrderItem.count + # + # bogus_order_item_id = OrderItem.last.id + 1 + # delete work_path(bogus_order_item_id) + # must_respond_with :not_found + # + # Work.count.must_equal start_count + # end + + end + + end diff --git a/test/models/order_item_test.rb b/test/models/order_item_test.rb index 19a9bf8f58..eedf08069e 100644 --- a/test/models/order_item_test.rb +++ b/test/models/order_item_test.rb @@ -1,9 +1,23 @@ require "test_helper" describe OrderItem do - let(:order_item) { OrderItem.new } + # let(:order_item) { OrderItem.new } + # + # it "must be valid" do + # value(order_item).must_be :valid? + # end - it "must be valid" do - value(order_item).must_be :valid? + describe "relations" do + it "has an order" do + o = orderitems(:one) + o.must_respond_to :order + o.order.must_be_kind_of Order + end + + it "has a product" do + o = orderitems(:one) + o.must_respond_to :product + o.order.must_be_kind_of Product + end end end From 0ae136a8dfd4f8414bdaa3fd3760698d58852e07 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Wed, 18 Oct 2017 12:19:58 -0700 Subject: [PATCH 028/223] Add seeds for merchant and product --- db/merchant_seeds.csv | 4 +++ db/product_seeds.csv | 11 ++++++++ db/{ => seed_data}/schema.rb | 0 db/seed_data/seeds.rb | 54 ++++++++++++++++++++++++++++++++++++ db/seeds.rb | 7 ----- 5 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 db/merchant_seeds.csv create mode 100644 db/product_seeds.csv rename db/{ => seed_data}/schema.rb (100%) create mode 100644 db/seed_data/seeds.rb delete mode 100644 db/seeds.rb diff --git a/db/merchant_seeds.csv b/db/merchant_seeds.csv new file mode 100644 index 0000000000..0def0031ef --- /dev/null +++ b/db/merchant_seeds.csv @@ -0,0 +1,4 @@ +id,username,email +1,Eva,eva@email.com +2,Rebecca,rebecca@email.com +3,Lindsey,lindsey@email.com diff --git a/db/product_seeds.csv b/db/product_seeds.csv new file mode 100644 index 0000000000..beb8c985aa --- /dev/null +++ b/db/product_seeds.csv @@ -0,0 +1,11 @@ +id,name,price,stock,description,retired,image_url,merchant_id +1,owl_1,20,5,nice bird,false,http://via.placeholder.com/100x70,1 +2,owl_2,30,5,nice bird,false,http://via.placeholder.com/100x70,1 +3,owl_3,25,2,nice bird,false,http://via.placeholder.com/100x70,1 +4,hawk_1,50,5,nice bird,false,http://via.placeholder.com/100x70,2 +5,hawk_2,55,4,nice bird,false,http://via.placeholder.com/100x70,2 +6,hawk_3,25,5,nice bird,false,http://via.placeholder.com/100x70,2 +7,eagle_1,40,5,nice bird,false,http://via.placeholder.com/100x70,3 +8,eagle_2,60,1,nice bird,false,http://via.placeholder.com/100x70,3 +9,eagle_3,90,5,nice bird,false,http://via.placeholder.com/100x70,3 +10,eagle_4,100,3,nice bird,false,http://via.placeholder.com/100x70,3 diff --git a/db/schema.rb b/db/seed_data/schema.rb similarity index 100% rename from db/schema.rb rename to db/seed_data/schema.rb diff --git a/db/seed_data/seeds.rb b/db/seed_data/seeds.rb new file mode 100644 index 0000000000..023aa34b82 --- /dev/null +++ b/db/seed_data/seeds.rb @@ -0,0 +1,54 @@ +require 'csv' + +# 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) + +PRODUCT_FILE = Rails.root.join('db', 'seed_data', 'product_seeds.csv') +puts "Loading raw driver data from #{PRODUCT_FILE}" + +product_failures = [] +CSV.foreach(PRODUCT_FILE, :headers => true) do |row| + product = Product.new + product.id = row['id'] + product.name = row['name'] + product.price = row['price'] + product.stock = row['stock'] + product.description = row['description'] + product.retired = row['retired'] + product.image_url = row['image_url'] + product.merchant_id = row['merchant_id'] + puts "Created product: #{product.inspect}" + successful = product.save + if !successful + product_failures << product + end +end + +puts "Added #{Product.count} product records" +puts "#{product_failures.length} products failed to save" + + + +MERCHANT_FILE = Rails.root.join('db', 'seed_data', 'merchant_seeds.csv') +puts "Loading raw driver data from #{MERCHANT_FILE}" + +merchant_failures = [] +CSV.foreach(MERCHANT_FILE, :headers => true) do |row| + merchant = Merchant.new + merchant.id = row['id'] + merchant.username = row['username'] + merchant.email = row['email'] + puts "Created merchant: #{merchant.inspect}" + successful = merchant.save + if !successful + merchant_failures << merchant + end +end + +puts "Added #{Merchant.count} merchant records" +puts "#{merchant_failures.length} merchants failed to save" diff --git a/db/seeds.rb b/db/seeds.rb deleted file mode 100644 index 1beea2accd..0000000000 --- a/db/seeds.rb +++ /dev/null @@ -1,7 +0,0 @@ -# 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) From 808e73744b17546d414cf51cbac5e649635d40da Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Wed, 18 Oct 2017 12:35:04 -0700 Subject: [PATCH 029/223] Fix seed data location --- app/views/products/index.html.erb | 8 ++++++++ db/{seed_data => }/schema.rb | 6 ------ db/{ => seed_data}/merchant_seeds.csv | 0 db/{ => seed_data}/product_seeds.csv | 0 db/{seed_data => }/seeds.rb | 0 5 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 app/views/products/index.html.erb rename db/{seed_data => }/schema.rb (93%) rename db/{ => seed_data}/merchant_seeds.csv (100%) rename db/{ => seed_data}/product_seeds.csv (100%) rename db/{seed_data => }/seeds.rb (100%) diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb new file mode 100644 index 0000000000..8441e5c285 --- /dev/null +++ b/app/views/products/index.html.erb @@ -0,0 +1,8 @@ +

products

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

<%= product.name %>

+

<%= product.price %>

+

<%= product.description %>

+
+<% end %> diff --git a/db/seed_data/schema.rb b/db/schema.rb similarity index 93% rename from db/seed_data/schema.rb rename to db/schema.rb index 4b2b847ee9..5ee50235cd 100644 --- a/db/seed_data/schema.rb +++ b/db/schema.rb @@ -34,16 +34,10 @@ t.string "status" t.string "customer_name" t.string "customer_email" -<<<<<<< HEAD - t.integer "cc_number" - t.date "cc_exipration" - t.integer "cc_ccv" -======= t.string "customer_address" t.string "cc_number" t.date "cc_expiration" t.string "cc_ccv" ->>>>>>> 8f95f564eb21c8e4e6a908d48fbe79f5210ec9a0 t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "zip_code" diff --git a/db/merchant_seeds.csv b/db/seed_data/merchant_seeds.csv similarity index 100% rename from db/merchant_seeds.csv rename to db/seed_data/merchant_seeds.csv diff --git a/db/product_seeds.csv b/db/seed_data/product_seeds.csv similarity index 100% rename from db/product_seeds.csv rename to db/seed_data/product_seeds.csv diff --git a/db/seed_data/seeds.rb b/db/seeds.rb similarity index 100% rename from db/seed_data/seeds.rb rename to db/seeds.rb From 9726c5e5c26426dccaf96185aaeb53b935b0e676 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Wed, 18 Oct 2017 13:15:18 -0700 Subject: [PATCH 030/223] Seed the data for merchant and product --- app/views/products/index.html.erb | 2 +- db/seeds.rb | 41 +++++++++++++++---------------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 8441e5c285..afe073a29c 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,5 +1,5 @@

products

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

<%= product.name %>

<%= product.price %>

diff --git a/db/seeds.rb b/db/seeds.rb index 023aa34b82..c272e98f2f 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -7,6 +7,26 @@ # # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) # Character.create(name: 'Luke', movie: movies.first) +MERCHANT_FILE = Rails.root.join('db', 'seed_data', 'merchant_seeds.csv') +puts "Loading raw merchant data from #{MERCHANT_FILE}" + +merchant_failures = [] +CSV.foreach(MERCHANT_FILE, :headers => true) do |row| + merchant = Merchant.new + merchant.id = row['id'] + merchant.username = row['username'] + merchant.email = row['email'] + puts "Created merchant: #{merchant.inspect}" + successful = merchant.save + if !successful + merchant_failures << merchant + end +end + +puts "Added #{Merchant.count} merchant records" +puts "#{merchant_failures.length} merchants failed to save" + + PRODUCT_FILE = Rails.root.join('db', 'seed_data', 'product_seeds.csv') puts "Loading raw driver data from #{PRODUCT_FILE}" @@ -31,24 +51,3 @@ puts "Added #{Product.count} product records" puts "#{product_failures.length} products failed to save" - - - -MERCHANT_FILE = Rails.root.join('db', 'seed_data', 'merchant_seeds.csv') -puts "Loading raw driver data from #{MERCHANT_FILE}" - -merchant_failures = [] -CSV.foreach(MERCHANT_FILE, :headers => true) do |row| - merchant = Merchant.new - merchant.id = row['id'] - merchant.username = row['username'] - merchant.email = row['email'] - puts "Created merchant: #{merchant.inspect}" - successful = merchant.save - if !successful - merchant_failures << merchant - end -end - -puts "Added #{Merchant.count} merchant records" -puts "#{merchant_failures.length} merchants failed to save" From 088ffb6d9eea4de1ad05d5aa8175d36395002377 Mon Sep 17 00:00:00 2001 From: Rebecca Bergena Date: Wed, 18 Oct 2017 15:21:46 -0700 Subject: [PATCH 031/223] merge changes --- db/schema.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 4b2b847ee9..5ee50235cd 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -34,16 +34,10 @@ t.string "status" t.string "customer_name" t.string "customer_email" -<<<<<<< HEAD - t.integer "cc_number" - t.date "cc_exipration" - t.integer "cc_ccv" -======= t.string "customer_address" t.string "cc_number" t.date "cc_expiration" t.string "cc_ccv" ->>>>>>> 8f95f564eb21c8e4e6a908d48fbe79f5210ec9a0 t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "zip_code" From 6102d2cf60b7fc81b2686d71b0c272147f621953 Mon Sep 17 00:00:00 2001 From: VirtualLindsey Date: Wed, 18 Oct 2017 15:46:44 -0700 Subject: [PATCH 032/223] saving files --- app/views/merchants/show.html.erb | 9 +++++++++ app/views/products/edit.html.erb | 26 ++++++++++++++++++++++++++ app/views/products/index.html.erb | 17 +++++++++++------ app/views/products/new.html.erb | 27 +++++++++++++++++++++++++++ app/views/products/show.html.erb | 11 +++++++++++ 5 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 app/views/merchants/show.html.erb create mode 100644 app/views/products/edit.html.erb create mode 100644 app/views/products/new.html.erb create mode 100644 app/views/products/show.html.erb diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb new file mode 100644 index 0000000000..a70ab1ed88 --- /dev/null +++ b/app/views/merchants/show.html.erb @@ -0,0 +1,9 @@ +

Product#: <%= @merchant.id %>

+ +
    + +
  • Name: <%= @merchant.name %>
  • +
  • Email: <%= @merchant.email %>
  • + + +
diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb new file mode 100644 index 0000000000..fd2fc2d598 --- /dev/null +++ b/app/views/products/edit.html.erb @@ -0,0 +1,26 @@ +<%= form_for @product do |f| %> + <%= f.label :name %> + <%= f.text_field :name %> + + <%= f.label :price %> + <%= f.text_field :price %> + + <%= f.label :stock %> + <%= f.text_field :stock %> + + <%= f.label :retired %> + <%= f.text_field :retired %> + + <%= f.label :description %> + <%= f.text_area :description %> + + <%= f.label :image_url %> + <%= f.text_area :image_url %> + + <%= f.label :merchant_id %> + <%= f.text_area :merchant_id %> + + + <%= f.submit%> + +<% end %> diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index afe073a29c..d60a195912 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,8 +1,13 @@ -

products

+

All Orders

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

<%= product.name %>

-

<%= product.price %>

-

<%= product.description %>

-
+
    +
  • ID: <%= link_to product.id, product_path(product) %>
  • +
  • Price: <%= product.price %>
  • +
  • Stock: <%= product.stock %>
  • +
  • Retired?: <%= product.retired %>
  • +
  • Description: <%= product.description %>
  • +
  • Image URL: <%= product.image_url %>
  • + +
<% end %> diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb new file mode 100644 index 0000000000..a6feb7f823 --- /dev/null +++ b/app/views/products/new.html.erb @@ -0,0 +1,27 @@ +

Create new product

+<%= form_for @product do |f| %> + <%= f.label :name %> + <%= f.text_field :name %> + + <%= f.label :price %> + <%= f.text_field :price %> + + <%= f.label :stock %> + <%= f.text_field :stock %> + + <%= f.label :retired %> + <%= f.text_field :retired %> + + <%= f.label :description %> + <%= f.text_area :description %> + + <%= f.label :image_url %> + <%= f.text_area :image_url %> + + <%= f.label :merchant_id %> + <%= f.text_area :merchant_id %> + + + <%= f.submit%> + +<% end %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb new file mode 100644 index 0000000000..d143025042 --- /dev/null +++ b/app/views/products/show.html.erb @@ -0,0 +1,11 @@ +

Product#: <%= @product.id %>

+ +
    +
  • ID: <%= link_to product.id, product_path(product) %>
  • +
  • Price: <%= product.price %>
  • +
  • Stock: <%= product.stock %>
  • +
  • Retired?: <%= product.retired %>
  • +
  • Description: <%= product.description %>
  • +
  • Image URL: <%= product.image_url %>
  • + +
From 20111c0a90caefeb3a82ddff33343c7b25cb5a2b Mon Sep 17 00:00:00 2001 From: VirtualLindsey Date: Wed, 18 Oct 2017 15:49:47 -0700 Subject: [PATCH 033/223] making files --- Gemfile.lock | 7 +++++++ app/assets/javascripts/reviews.js | 2 ++ app/assets/stylesheets/reviews.scss | 3 +++ app/controllers/reviews_controller.rb | 2 ++ app/helpers/reviews_helper.rb | 2 ++ app/models/review.rb | 2 ++ app/views/order_item/index.html.erb | 10 ++++++++++ db/migrate/20171018224742_create_reviews.rb | 10 ++++++++++ test/controllers/reviews_controller_test.rb | 7 +++++++ test/fixtures/reviews.yml | 9 +++++++++ test/models/review_test.rb | 9 +++++++++ 11 files changed, 63 insertions(+) create mode 100644 app/assets/javascripts/reviews.js create mode 100644 app/assets/stylesheets/reviews.scss create mode 100644 app/controllers/reviews_controller.rb create mode 100644 app/helpers/reviews_helper.rb create mode 100644 app/models/review.rb create mode 100644 app/views/order_item/index.html.erb create mode 100644 db/migrate/20171018224742_create_reviews.rb create mode 100644 test/controllers/reviews_controller_test.rb create mode 100644 test/fixtures/reviews.yml create mode 100644 test/models/review_test.rb diff --git a/Gemfile.lock b/Gemfile.lock index 511ae2017e..2599b628c8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -71,6 +71,7 @@ GEM erubi (1.7.0) execjs (2.7.0) ffi (1.9.18) + ffi (1.9.18-x86-mingw32) foundation-rails (6.3.1.0) railties (>= 3.1.0) sass (>= 3.3.0, < 3.5) @@ -113,7 +114,10 @@ GEM nio4r (2.1.0) nokogiri (1.8.1) mini_portile2 (~> 2.3.0) + nokogiri (1.8.1-x86-mingw32) + mini_portile2 (~> 2.3.0) pg (0.21.0) + pg (0.21.0-x86-mingw32) pry (0.11.1) coderay (~> 1.1.0) method_source (~> 0.9.0) @@ -188,6 +192,8 @@ GEM turbolinks-source (5.0.3) tzinfo (1.2.3) thread_safe (~> 0.1) + tzinfo-data (1.2017.2) + tzinfo (>= 1.0.0) uglifier (3.2.0) execjs (>= 0.3.0, < 3) web-console (3.5.1) @@ -203,6 +209,7 @@ GEM PLATFORMS ruby + x86-mingw32 DEPENDENCIES better_errors 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/reviews.scss b/app/assets/stylesheets/reviews.scss new file mode 100644 index 0000000000..6ea2454d26 --- /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/reviews_controller.rb b/app/controllers/reviews_controller.rb new file mode 100644 index 0000000000..b3d77cc1c3 --- /dev/null +++ b/app/controllers/reviews_controller.rb @@ -0,0 +1,2 @@ +class ReviewsController < ApplicationController +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/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/app/views/order_item/index.html.erb b/app/views/order_item/index.html.erb new file mode 100644 index 0000000000..6534150c57 --- /dev/null +++ b/app/views/order_item/index.html.erb @@ -0,0 +1,10 @@ +

All Order Items

+ +<% @order_items.each do |order_item| %> +
    +
  • ID: <%= link_to order_item.id, order_items_path(order_item) %>
  • +
  • Quantity: <%= order_item.quantity %>
  • +
  • Product ID: <%= order_item.product_id %>
  • +
  • Order ID: <%= order_item.order_id %>
  • +
+<% end %> diff --git a/db/migrate/20171018224742_create_reviews.rb b/db/migrate/20171018224742_create_reviews.rb new file mode 100644 index 0000000000..14b85f5be4 --- /dev/null +++ b/db/migrate/20171018224742_create_reviews.rb @@ -0,0 +1,10 @@ +class CreateReviews < ActiveRecord::Migration[5.1] + def change + create_table :reviews do |t| + t.integer :product_id + t.string :text + + t.timestamps + end + end +end diff --git a/test/controllers/reviews_controller_test.rb b/test/controllers/reviews_controller_test.rb new file mode 100644 index 0000000000..386065239a --- /dev/null +++ b/test/controllers/reviews_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +describe ReviewsController do + # it "must be a real test" do + # flunk "Need real tests" + # end +end diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml new file mode 100644 index 0000000000..49520a6432 --- /dev/null +++ b/test/fixtures/reviews.yml @@ -0,0 +1,9 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + product_id: 1 + text: MyString + +two: + product_id: 1 + text: MyString 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 e154b048072cc845a166429d0d2107c6062e9a5c Mon Sep 17 00:00:00 2001 From: VirtualLindsey Date: Wed, 18 Oct 2017 15:57:03 -0700 Subject: [PATCH 034/223] updates for reviews --- app/controllers/reviews_controller.rb | 35 +++++++++++++++++++++++++++ config/routes.rb | 7 ++++++ 2 files changed, 42 insertions(+) diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index b3d77cc1c3..41b545af5a 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -1,2 +1,37 @@ class ReviewsController < ApplicationController + def index + @reviews = Review.all() + end + + def show + @review = Review.find(params[:id]) + end + + def edit + @review = Review.find(params[:id]) + end + + def new + @review = Review.new() + end + + def create + @review = Review.new(review_params) + if @review.save + flash[:status] = :success + flash[:result_text] = "Successfully created #{@review.id}" + redirect_to review_path(@review) + else + flash[:status] = :failure + flash[:result_text] = "Could not create review ID number #{@review.id}" + flash[:messages] = @review.errors.messages + render :new, status: :bad_request + end + end + + private + + def review_params + params.require(:product_id).permit(:text) + end end diff --git a/config/routes.rb b/config/routes.rb index 4bbec6ec80..66e170b432 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -12,7 +12,14 @@ get '/orders/:id/edit', to: 'orders#edit', as: 'edit_order' patch '/orders/:id', to: 'orders#update' + get '/reviews', to: 'reviews#index', as: 'reviews' + get '/reviews/new', to: 'reviews#new', as: 'new_review' + post '/reviews', to: 'reviews#create' + get '/reviews/:id', to: 'review#show', as: 'review' + get '/reviews/:id/edit', to: 'reviews#edit', as: 'edit_review' + resources :orders + resources :reviews root 'main#index' resources :orderitems, only: [:create, :index, :destroy, :update] From 524551814fd55d7d1c797de95a327ba604bd8e52 Mon Sep 17 00:00:00 2001 From: Rebecca Bergena Date: Wed, 18 Oct 2017 19:17:37 -0700 Subject: [PATCH 035/223] create categories model and categores_products join table --- app/models/category.rb | 2 ++ db/migrate/20171019021137_create_categories.rb | 9 +++++++++ ...9021545_create_categories_products_join_table.rb | 5 +++++ db/schema.rb | 13 ++++++++++++- test/fixtures/categories.yml | 7 +++++++ test/models/category_test.rb | 9 +++++++++ 6 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 app/models/category.rb create mode 100644 db/migrate/20171019021137_create_categories.rb create mode 100644 db/migrate/20171019021545_create_categories_products_join_table.rb create mode 100644 test/fixtures/categories.yml create mode 100644 test/models/category_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/db/migrate/20171019021137_create_categories.rb b/db/migrate/20171019021137_create_categories.rb new file mode 100644 index 0000000000..5bef4913b8 --- /dev/null +++ b/db/migrate/20171019021137_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/20171019021545_create_categories_products_join_table.rb b/db/migrate/20171019021545_create_categories_products_join_table.rb new file mode 100644 index 0000000000..30c328c6eb --- /dev/null +++ b/db/migrate/20171019021545_create_categories_products_join_table.rb @@ -0,0 +1,5 @@ +class CreateCategoriesProductsJoinTable < ActiveRecord::Migration[5.1] + def change + create_join_table :categories, :products + end +end diff --git a/db/schema.rb b/db/schema.rb index 5ee50235cd..3d6c0946c8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,11 +10,22 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20171018052441) do +ActiveRecord::Schema.define(version: 20171019021545) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + create_table "categories", force: :cascade do |t| + t.string "name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "categories_products", id: false, force: :cascade do |t| + t.bigint "category_id", null: false + t.bigint "product_id", null: false + end + create_table "merchants", force: :cascade do |t| t.string "username" t.string "email" 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/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 From 5e10572e6a820d5d2f6f4a518d9a7f970fd6d539 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Wed, 18 Oct 2017 21:28:18 -0700 Subject: [PATCH 036/223] Initial omniauth setup --- .gitignore | 1 + Gemfile | 5 +++++ Gemfile.lock | 28 +++++++++++++++++++++++++ app/controllers/merchants_controller.rb | 6 ------ config/initializers/omniauth.rb | 3 +++ config/routes.rb | 2 ++ 6 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 config/initializers/omniauth.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 b105f8ecb6..c8032a2be3 100644 --- a/Gemfile +++ b/Gemfile @@ -35,6 +35,9 @@ gem 'jbuilder', '~> 2.5' gem 'foundation-rails', '~> 6.3.1' +gem 'omniauth' +gem 'omniauth-github' + 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] @@ -50,6 +53,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' + + gem 'dotenv-rails' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem diff --git a/Gemfile.lock b/Gemfile.lock index 511ae2017e..86c3d1f5ca 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -68,8 +68,14 @@ GEM concurrent-ruby (1.0.5) crass (1.0.2) debug_inspector (0.0.3) + dotenv (2.2.1) + dotenv-rails (2.2.1) + dotenv (= 2.2.1) + railties (>= 3.2, < 5.2) erubi (1.7.0) execjs (2.7.0) + faraday (0.12.2) + multipart-post (>= 1.2, < 3) ffi (1.9.18) foundation-rails (6.3.1.0) railties (>= 3.1.0) @@ -77,6 +83,7 @@ GEM sprockets-es6 (>= 0.9.0) globalid (0.4.0) activesupport (>= 4.2.0) + hashie (3.5.6) i18n (0.9.0) concurrent-ruby (~> 1.0) jbuilder (2.7.0) @@ -85,6 +92,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) @@ -110,9 +118,26 @@ GEM minitest (>= 5.0) ruby-progressbar multi_json (1.12.2) + multi_xml (0.6.0) + multipart-post (2.0.0) nio4r (2.1.0) nokogiri (1.8.1) mini_portile2 (~> 2.3.0) + oauth2 (1.4.0) + faraday (>= 0.8, < 0.13) + jwt (~> 1.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + omniauth (1.7.1) + hashie (>= 3.4.6, < 3.6.0) + rack (>= 1.6.2, < 3) + omniauth-github (1.3.0) + omniauth (~> 1.5) + omniauth-oauth2 (>= 1.4.0, < 2.0) + omniauth-oauth2 (1.4.0) + oauth2 (~> 1.0) + omniauth (~> 1.2) pg (0.21.0) pry (0.11.1) coderay (~> 1.1.0) @@ -209,12 +234,15 @@ DEPENDENCIES binding_of_caller byebug capybara (~> 2.13) + dotenv-rails foundation-rails (~> 6.3.1) jbuilder (~> 2.5) jquery-turbolinks listen (>= 3.0.5, < 3.2) minitest-rails minitest-reporters + omniauth + omniauth-github pg (~> 0.18) pry-rails puma (~> 3.7) diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 4ccb1c1a3f..93aacaf651 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -1,11 +1,5 @@ class MerchantsController < ApplicationController - def new - end - - def create - end - def login end diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb new file mode 100644 index 0000000000..fd4416122a --- /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 4bbec6ec80..f749440be2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -17,4 +17,6 @@ resources :orderitems, only: [:create, :index, :destroy, :update] + + end From e9250f8f21225aaf5e3a8b4aa6237553c5790e08 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Wed, 18 Oct 2017 21:56:31 -0700 Subject: [PATCH 037/223] Add uid and provider to merchant and seed data --- app/controllers/merchants_controller.rb | 4 +++- config/routes.rb | 2 +- .../20171019043601_add_uid_and_provider_to_merchant.rb | 6 ++++++ db/schema.rb | 4 +++- db/seed_data/merchant_seeds.csv | 8 ++++---- db/seeds.rb | 2 ++ 6 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 db/migrate/20171019043601_add_uid_and_provider_to_merchant.rb diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 93aacaf651..f29d63b6d8 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -1,6 +1,8 @@ class MerchantsController < ApplicationController - + def login + auth_hash = request.env['omniauth.auth'] + raise end def logout diff --git a/config/routes.rb b/config/routes.rb index f749440be2..873f37770c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -17,6 +17,6 @@ resources :orderitems, only: [:create, :index, :destroy, :update] - + get '/auth/:provider/callback', to: 'merchants#login' end diff --git a/db/migrate/20171019043601_add_uid_and_provider_to_merchant.rb b/db/migrate/20171019043601_add_uid_and_provider_to_merchant.rb new file mode 100644 index 0000000000..80e3da689f --- /dev/null +++ b/db/migrate/20171019043601_add_uid_and_provider_to_merchant.rb @@ -0,0 +1,6 @@ +class AddUidAndProviderToMerchant < ActiveRecord::Migration[5.1] + def change + add_column :merchants, :provider, :string, null: false + add_column :merchants, :uid, :integer, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 5ee50235cd..f3086347e2 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: 20171018052441) do +ActiveRecord::Schema.define(version: 20171019043601) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -20,6 +20,8 @@ t.string "email" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "provider", null: false + t.integer "uid", null: false end create_table "order_items", force: :cascade do |t| diff --git a/db/seed_data/merchant_seeds.csv b/db/seed_data/merchant_seeds.csv index 0def0031ef..4af0f2a1c4 100644 --- a/db/seed_data/merchant_seeds.csv +++ b/db/seed_data/merchant_seeds.csv @@ -1,4 +1,4 @@ -id,username,email -1,Eva,eva@email.com -2,Rebecca,rebecca@email.com -3,Lindsey,lindsey@email.com +id,username,email,uid,provider +1,Eva,eva@email.com,123,github +2,Rebecca,rebecca@email.com,234,github +3,Lindsey,lindsey@email.com,345,github diff --git a/db/seeds.rb b/db/seeds.rb index c272e98f2f..290b33724f 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -16,6 +16,8 @@ merchant.id = row['id'] merchant.username = row['username'] merchant.email = row['email'] + merchant.uid = row['uid'] + merchant.provider = row['provider'] puts "Created merchant: #{merchant.inspect}" successful = merchant.save if !successful From e0795d70942aa776af6e3aeb7bac250c8a1eff80 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Wed, 18 Oct 2017 22:10:22 -0700 Subject: [PATCH 038/223] Add login controller merhod to merchant --- app/controllers/merchants_controller.rb | 25 ++++++++++++++++++++++++- app/models/merchant.rb | 10 ++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index f29d63b6d8..7f1475f4e4 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -2,7 +2,30 @@ class MerchantsController < ApplicationController def login auth_hash = request.env['omniauth.auth'] - raise + + if auth_hash['uid'] + merchant = Merchant.find_by(uid: auth_hash[:uid], provider: params[:provider]) + if merchant.nil? + #merchant has not logged in before + #create a new record + merchant = Merchant.from_auth_hash(params[:provider], auth_hash) + if merchant.save + flash[:status] = :success + flash[:notice] = "Logged in successfully as new merchant #{merchant.username}" + else + flash[:status] = :failure + flash[:notice] = "Could not log in" + end + else + flash[:status] = :success + flash[:notice] = "Logged in successfully as existing merchant as #{merchant.username}" + end + session[:merchant_id] = merchant.id + else + flash[:status] = :failure + flash[:notice] = "Could not log in" + end + redirect_to root_path end def logout diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 0440407160..7539c63202 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -1,2 +1,12 @@ class Merchant < ApplicationRecord + + def self.from_auth_hash(provider, auth_hash) + merchant = new + merchant.provider = provider + merchant.uid = auth_hash['uid'] + merchant.email = auth_hash['info']['email'] + merchant.username = auth_hash['info']['nickname'] + + return merchant + end end From f1da4171f0d5020f21960d71b58afa458ffa5689 Mon Sep 17 00:00:00 2001 From: Rebecca Bergena Date: Wed, 18 Oct 2017 22:30:43 -0700 Subject: [PATCH 039/223] create categories controller and add controller tests and some fixtures --- app/assets/javascripts/categories.js | 2 + app/assets/stylesheets/categories.scss | 3 + app/controllers/categories_controller.rb | 25 +++++++ app/helpers/categories_helper.rb | 2 + app/models/category.rb | 2 + app/views/categories/new.html.erb | 7 ++ config/routes.rb | 6 ++ .../controllers/categories_controller_test.rb | 67 +++++++++++++++++++ test/fixtures/merchants.yml | 10 ++- test/fixtures/products.yml | 20 +++++- 10 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 app/assets/javascripts/categories.js create mode 100644 app/assets/stylesheets/categories.scss create mode 100644 app/controllers/categories_controller.rb create mode 100644 app/helpers/categories_helper.rb create mode 100644 app/views/categories/new.html.erb create mode 100644 test/controllers/categories_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/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/controllers/categories_controller.rb b/app/controllers/categories_controller.rb new file mode 100644 index 0000000000..5a51b9a526 --- /dev/null +++ b/app/controllers/categories_controller.rb @@ -0,0 +1,25 @@ +class CategoriesController < ApplicationController + def new + @category = Category.new + end + + def create + @category = Category.new(category_params) + if @category.save + flash[:status] = :success + flash[:message] = "Successfully created category: #{@category.name}" + redirect_to root_path + else + flash[:status] = :failure + flash[:message] = "Could not create category" + flash[:details] = @category.errors.messages + render :new, status: :bad_request + end + end + + private + +def category_params + return params.require(:category).permit(:name) +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/models/category.rb b/app/models/category.rb index 54cb6aee3f..cb498c0b5b 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,2 +1,4 @@ class Category < ApplicationRecord + has_and_belongs_to_many :products + validates :name, presence: true end diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb new file mode 100644 index 0000000000..61bb407a83 --- /dev/null +++ b/app/views/categories/new.html.erb @@ -0,0 +1,7 @@ +

Make a New Category

+ + <%= form_for @category do |f| %> + <%=f.label :name %> + <%=f.text_field :name %> + <%= f.submit %> + <%end%> diff --git a/config/routes.rb b/config/routes.rb index 4bbec6ec80..e95a24b115 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -17,4 +17,10 @@ resources :orderitems, only: [:create, :index, :destroy, :update] + resources :categories, only: [:new, :create] + + # nested routes + resources :categories do + resources :products, only: [:index] + end end diff --git a/test/controllers/categories_controller_test.rb b/test/controllers/categories_controller_test.rb new file mode 100644 index 0000000000..b0e0e6810b --- /dev/null +++ b/test/controllers/categories_controller_test.rb @@ -0,0 +1,67 @@ +require "test_helper" + +describe CategoriesController do + + describe "new" do + it "gets new and returns a success status for the new page" do + get new_category_path + must_respond_with :success + end + end + + + describe "create" do + it "redirects to root page when the category data is valid" do + category_data = { + category: { + name: "mugs", + } + } + + Category.new(category_data[:category]).must_be :valid? + test_category = Category.create!(category_data[:category]) + + start_category_count = Category.count + + proc { + post categories_path, params: category_data + }.must_change 'Category.count', 1 + + + ####CHANGE REDIRECT TO PATH WHEN PAGE IS CREATED + must_respond_with :redirect + must_redirect_to root_path + flash[:message].must_equal "Successfully created category: #{test_category.name}" + flash[:status].must_equal :success + + Category.count.must_equal start_category_count + 1 + end + + it "sends bad_request when the category data is invalid" do + # this data is not valid because there is no name + invalid_category_data = { + category: { + name: "" + } + } + + # makes sure test breaks if we change the model (i.e., test data no longer vaild) + Category.new(invalid_category_data[:category]).wont_be :valid? + + start_category_count = Category.count + + #Act + proc { + post categories_path, params: invalid_category_data + }.must_change 'Category.count', 0 + + + #Assert + must_respond_with :bad_request + flash[:message].must_equal "Could not create category" + flash[:status].must_equal :failure + + Category.count.must_equal start_category_count + end + end +end diff --git a/test/fixtures/merchants.yml b/test/fixtures/merchants.yml index dc3ee79b5d..2603862fbc 100644 --- a/test/fixtures/merchants.yml +++ b/test/fixtures/merchants.yml @@ -4,8 +4,14 @@ # model remove the "{}" from the fixture names and add the columns immediately # below each fixture, per the syntax in the comments below # -one: {} +one: + username: test + email: test + # column: value # -two: {} +two: + username: test2 + email: test2 + # column: value diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index dc3ee79b5d..d5ccabc273 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -4,8 +4,24 @@ # model remove the "{}" from the fixture names and add the columns immediately # below each fixture, per the syntax in the comments below # -one: {} +one: + name: product + price: 2.0 + stock: 3 + retired: false + description: testing + image_url: addtesturl + merchant: one + # column: value # -two: {} +two: + name: product2 + price: 3.0 + stock: 4 + retired: false + description: testing2 + image_url: addtesturl2 + merchant: two + # column: value From bd718fa662c1ff4ef2a16df03398fba9cdad8318 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Wed, 18 Oct 2017 22:33:42 -0700 Subject: [PATCH 040/223] Add logout method and change html and css nav --- app/assets/stylesheets/application.css | 2 +- app/controllers/merchants_controller.rb | 6 ++++-- app/views/layouts/application.html.erb | 8 +++++++- config/routes.rb | 1 + 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 6657dfe5d2..697863d99a 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -30,7 +30,7 @@ max-width: 100%; } - .nav a { + .nav a, .nav p { margin: .5rem .1rem; background-color: #ff8533; font-weight: bold; diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 7f1475f4e4..7d181478c6 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -6,8 +6,6 @@ def login if auth_hash['uid'] merchant = Merchant.find_by(uid: auth_hash[:uid], provider: params[:provider]) if merchant.nil? - #merchant has not logged in before - #create a new record merchant = Merchant.from_auth_hash(params[:provider], auth_hash) if merchant.save flash[:status] = :success @@ -29,5 +27,9 @@ def login end def logout + session[:merchant_id] = nil + flash[:status] = :success + flash[:notice] = "Successfully logged out" + redirect_to root_path end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 797584e94f..d2ddf19f2d 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -24,7 +24,13 @@ <%= link_to "home", root_path, class: "button" %> <%= link_to "shop by category", root_path, class: "button" %> <%= link_to "shop by merchant", root_path, class: "button" %> - <%= link_to "login", root_path, class: "button float-right" %> + <% if session[:merchant_id] %> +
+

loggen in as <%= Merchant.find(session[:merchant_id]).username %>

+ <%= link_to "log out", logout_path, class: "button" %>
+ <% else %> + <%= link_to "login", '/auth/github', class: "button float-right" %> + <% end %>
diff --git a/config/routes.rb b/config/routes.rb index 873f37770c..c6e235c1f4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -18,5 +18,6 @@ resources :orderitems, only: [:create, :index, :destroy, :update] get '/auth/:provider/callback', to: 'merchants#login' + get 'logout', to: 'merchants#logout', as: 'logout' end From 1bb1aea3107048983894b8f3775e61350e509a01 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Wed, 18 Oct 2017 23:20:42 -0700 Subject: [PATCH 041/223] Setup for login testing --- app/assets/stylesheets/application.css | 2 +- test/controllers/merchants_controller_test.rb | 8 +++++--- test/fixtures/merchants.yml | 16 +++++++++++----- test/test_helper.rb | 14 ++++++++++++++ 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 697863d99a..34ff01efb3 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -36,7 +36,7 @@ font-weight: bold; } - .nav a:hover { + .nav a:hover, .nav p:hover { background-color: #e65c00; } diff --git a/test/controllers/merchants_controller_test.rb b/test/controllers/merchants_controller_test.rb index 6eb57f7baa..df6b6dd971 100644 --- a/test/controllers/merchants_controller_test.rb +++ b/test/controllers/merchants_controller_test.rb @@ -1,7 +1,9 @@ require "test_helper" describe MerchantsController do - # it "must be a real test" do - # flunk "Need real tests" - # end + describe "login" do + it "" do + + end + end end diff --git a/test/fixtures/merchants.yml b/test/fixtures/merchants.yml index dc3ee79b5d..09a6dcd2b9 100644 --- a/test/fixtures/merchants.yml +++ b/test/fixtures/merchants.yml @@ -4,8 +4,14 @@ # model remove the "{}" from the fixture names and add the columns immediately # below each fixture, per the syntax in the comments below # -one: {} -# column: value -# -two: {} -# column: value +eva: + username: eva + email: eva@email.com + provider: github + uid: 123 + +emma: + username: emma + email: emma@email.com + provider: github + uid: 234 diff --git a/test/test_helper.rb b/test/test_helper.rb index 10594a3248..0b69853e82 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -23,4 +23,18 @@ 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(merchant) + return { + provider: merchant.provider, + uid: merchant.uid, + info: { + nickname: merchant.username, + email: merchant.email + } + } + end end From 45c46110c54af59f8110c25a25b20da720767b9a Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Wed, 18 Oct 2017 23:57:47 -0700 Subject: [PATCH 042/223] Add tests for login --- config/routes.rb | 2 +- test/controllers/merchants_controller_test.rb | 47 ++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index c6e235c1f4..80dbd55b63 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -17,7 +17,7 @@ resources :orderitems, only: [:create, :index, :destroy, :update] - get '/auth/:provider/callback', to: 'merchants#login' + get '/auth/:provider/callback', to: 'merchants#login', as: 'auth_callback' get 'logout', to: 'merchants#logout', as: 'logout' end diff --git a/test/controllers/merchants_controller_test.rb b/test/controllers/merchants_controller_test.rb index df6b6dd971..c31c7184b0 100644 --- a/test/controllers/merchants_controller_test.rb +++ b/test/controllers/merchants_controller_test.rb @@ -2,8 +2,51 @@ describe MerchantsController do describe "login" do - it "" do - + it "logs in an existing merchant and redirects to the root path" do + start_count = Merchant.count + + merchant = merchants(:eva) + + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(merchant)) + + get auth_callback_path(:github) + + must_respond_with :redirect + must_redirect_to root_path + session[:merchant_id].must_equal merchant.id + Merchant.count.must_equal start_count + + end + + it "creates an account for a new user and redirects to the root path" do + start_count = Merchant.count + + merchant = Merchant.new(provider: "github", uid: 456, username: "new_merchant", email: "new@mail.com") + + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(merchant)) + + get auth_callback_path(:github) + + must_respond_with :redirect + must_redirect_to root_path + session[:merchant_id].must_equal Merchant.last.id + Merchant.count.must_equal start_count + 1 + + end + + it "redirects to the root path if given invalid user data" do + start_count = Merchant.count + + merchant = Merchant.new(username: "new_merchant", email: "new@mail.com") + + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(merchant)) + + get auth_callback_path(:github) + + must_respond_with :redirect + must_redirect_to root_path + session[:merchant_id].must_equal nil + Merchant.count.must_equal start_count end end end From c57fbb7332b5693367156cb2e905975faad68a0c Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Thu, 19 Oct 2017 09:14:56 -0700 Subject: [PATCH 043/223] Add test for login and test_helper method login --- test/controllers/merchants_controller_test.rb | 25 ++++++++++++------- test/test_helper.rb | 5 ++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/test/controllers/merchants_controller_test.rb b/test/controllers/merchants_controller_test.rb index c31c7184b0..e8ab38aec5 100644 --- a/test/controllers/merchants_controller_test.rb +++ b/test/controllers/merchants_controller_test.rb @@ -7,9 +7,7 @@ merchant = merchants(:eva) - OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(merchant)) - - get auth_callback_path(:github) + login(merchant) must_respond_with :redirect must_redirect_to root_path @@ -23,9 +21,7 @@ merchant = Merchant.new(provider: "github", uid: 456, username: "new_merchant", email: "new@mail.com") - OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(merchant)) - - get auth_callback_path(:github) + login(merchant) must_respond_with :redirect must_redirect_to root_path @@ -39,9 +35,7 @@ merchant = Merchant.new(username: "new_merchant", email: "new@mail.com") - OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(merchant)) - - get auth_callback_path(:github) + login(merchant) must_respond_with :redirect must_redirect_to root_path @@ -49,4 +43,17 @@ Merchant.count.must_equal start_count end end + + describe "logout" do + it "logs out merchant and redirects to the root path" do + merchant = merchants(:eva) + + login(merchant) + get logout_path + + must_respond_with :redirect + must_redirect_to root_path + session[:merchant_id].must_equal nil + end + end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 0b69853e82..4a280010c8 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -37,4 +37,9 @@ def mock_auth_hash(merchant) } } end + + def login(merchant) + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(merchant)) + get auth_callback_path(:github) + end end From 54f0c2020a905e3aeb26f9e5a20053d68017f1da Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Thu, 19 Oct 2017 09:58:11 -0700 Subject: [PATCH 044/223] Work on main page --- app/views/main/index.html.erb | 3 +++ db/schema.rb | 7 +++++++ db/seed_data/merchant_seeds.csv | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb index 90c18646b0..8aa47fa940 100644 --- a/app/views/main/index.html.erb +++ b/app/views/main/index.html.erb @@ -12,6 +12,9 @@

some heading

+
+ +
diff --git a/db/schema.rb b/db/schema.rb index f3086347e2..d829ec59ed 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -57,4 +57,11 @@ t.datetime "updated_at", null: false end + create_table "reviews", force: :cascade do |t| + t.integer "product_id" + t.string "text" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + end diff --git a/db/seed_data/merchant_seeds.csv b/db/seed_data/merchant_seeds.csv index 4af0f2a1c4..d5c42987d6 100644 --- a/db/seed_data/merchant_seeds.csv +++ b/db/seed_data/merchant_seeds.csv @@ -1,4 +1,4 @@ id,username,email,uid,provider -1,Eva,eva@email.com,123,github +1,Julia,julia@email.com,123,github 2,Rebecca,rebecca@email.com,234,github 3,Lindsey,lindsey@email.com,345,github From ff1382a77c2b69baeefa7d6c10b049d22a63cca2 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Thu, 19 Oct 2017 10:17:13 -0700 Subject: [PATCH 045/223] Add styles to show page --- app/assets/stylesheets/application.css | 9 +++++++++ app/views/products/show.html.erb | 25 ++++++++++++++++--------- db/seed_data/product_seeds.csv | 20 ++++++++++---------- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 34ff01efb3..952f9fe4ef 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -66,3 +66,12 @@ .ads h3 { margin: 0; } + + .show-im { + max-width: 100%; + max-height: 100%; + } + + .show-desc li { + list-style-type: none; + } diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index d143025042..c271b95d66 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,11 +1,18 @@ -

Product#: <%= @product.id %>

+
+

<%= @product.name %>

-
    -
  • ID: <%= link_to product.id, product_path(product) %>
  • -
  • Price: <%= product.price %>
  • -
  • Stock: <%= product.stock %>
  • -
  • Retired?: <%= product.retired %>
  • -
  • Description: <%= product.description %>
  • -
  • Image URL: <%= product.image_url %>
  • +
    + <%= image_tag(@product.image_url) %> +
    +
    +
      +
    • Price: <%= @product.price %>
    • +
    • Stock: <%= @product.stock %>
    • +
    • Retired?: <%= @product.retired %>
    • +
    • Description: <%= @product.description %>
    • +
    • Image URL: <%= @product.image_url %>
    • -
    +
+
+ +
diff --git a/db/seed_data/product_seeds.csv b/db/seed_data/product_seeds.csv index beb8c985aa..cff12df64f 100644 --- a/db/seed_data/product_seeds.csv +++ b/db/seed_data/product_seeds.csv @@ -1,11 +1,11 @@ id,name,price,stock,description,retired,image_url,merchant_id -1,owl_1,20,5,nice bird,false,http://via.placeholder.com/100x70,1 -2,owl_2,30,5,nice bird,false,http://via.placeholder.com/100x70,1 -3,owl_3,25,2,nice bird,false,http://via.placeholder.com/100x70,1 -4,hawk_1,50,5,nice bird,false,http://via.placeholder.com/100x70,2 -5,hawk_2,55,4,nice bird,false,http://via.placeholder.com/100x70,2 -6,hawk_3,25,5,nice bird,false,http://via.placeholder.com/100x70,2 -7,eagle_1,40,5,nice bird,false,http://via.placeholder.com/100x70,3 -8,eagle_2,60,1,nice bird,false,http://via.placeholder.com/100x70,3 -9,eagle_3,90,5,nice bird,false,http://via.placeholder.com/100x70,3 -10,eagle_4,100,3,nice bird,false,http://via.placeholder.com/100x70,3 +1,owl_1,20,5,nice bird,false,http://via.placeholder.com/300x250,1 +2,owl_2,30,5,nice bird,false,http://via.placeholder.com/300x250,1 +3,owl_3,25,2,nice bird,false,http://via.placeholder.com/300x250,1 +4,hawk_1,50,5,nice bird,false,http://via.placeholder.com/300x250,2 +5,hawk_2,55,4,nice bird,false,http://via.placeholder.com/300x250,2 +6,hawk_3,25,5,nice bird,false,http://via.placeholder.com/300x250,2 +7,eagle_1,40,5,nice bird,false,http://via.placeholder.com/300x250,3 +8,eagle_2,60,1,nice bird,false,http://via.placeholder.com/300x250,3 +9,eagle_3,90,5,nice bird,false,http://via.placeholder.com/300x250,3 +10,eagle_4,100,3,nice bird,false,http://via.placeholder.com/300x250,3 From ff0d93ba6de3d04e86f6005cf4b938e701406ca8 Mon Sep 17 00:00:00 2001 From: Eva Sawyer Date: Thu, 19 Oct 2017 13:04:16 -0700 Subject: [PATCH 046/223] added basic layout and functions to merchant show and merchant index --- app/controllers/merchants_controller.rb | 16 ++++++++++++++++ app/models/merchant.rb | 3 +++ app/views/layouts/application.html.erb | 4 ++-- app/views/merchants/index.html.erb | 8 ++++++++ app/views/merchants/show.html.erb | 20 +++++++++++++++----- config/routes.rb | 1 + 6 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 app/views/merchants/index.html.erb diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 7d181478c6..ea56380688 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -1,5 +1,21 @@ class MerchantsController < ApplicationController + + def new + @merchant = Merchant.new + end + + def index + @merchants = Merchant.all + end + + def show + @merchant = Merchant.find(params[:id]) + @products = @merchant.product + end + + + def login auth_hash = request.env['omniauth.auth'] diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 7539c63202..11fe3dc406 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -1,4 +1,5 @@ class Merchant < ApplicationRecord + has_many :product def self.from_auth_hash(provider, auth_hash) merchant = new @@ -9,4 +10,6 @@ def self.from_auth_hash(provider, auth_hash) return merchant end + + end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index d2ddf19f2d..902f4352a3 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -23,14 +23,14 @@ diff --git a/app/views/merchants/index.html.erb b/app/views/merchants/index.html.erb new file mode 100644 index 0000000000..b551da7965 --- /dev/null +++ b/app/views/merchants/index.html.erb @@ -0,0 +1,8 @@ +

Shop by merchant

+
    + <% @merchants.each do |merchant| %> +
  • + <%=link_to merchant.username, merchant_path(merchant) %> +
  • + <% end %> +
      diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index a70ab1ed88..baab1b9f87 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -1,9 +1,19 @@ -

      Product#: <%= @merchant.id %>

      +

      <%= @merchant.username %>

        - -
      • Name: <%= @merchant.name %>
      • +
      • Name: <%= @merchant.username %>
      • Email: <%= @merchant.email %>
      • - - +
      +

      Products sold by <%=@merchant.username%>

      +
        +<% @merchant.product.each do |product|%> +
      • + + +
        + <%= link_to product.name, product_path(product) %> +
        +
        +
      • + <% end %>
      diff --git a/config/routes.rb b/config/routes.rb index ec0d0c8471..4a9d1d7171 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,6 +3,7 @@ resources :products + resources :merchants get '/orders', to: 'orders#index', as: 'orders' From e259988dbc6f2db52dcd523feabf94c87286f433 Mon Sep 17 00:00:00 2001 From: Rebecca Bergena Date: Thu, 19 Oct 2017 13:27:34 -0700 Subject: [PATCH 047/223] add index method for nested route --- app/controllers/products_controller.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index e4afc8dd02..54681912ab 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -41,7 +41,12 @@ def update def index - @products = Product.all + if params[:category_id] + category = Category.find_by(id: params[:category_id]) + @products = category.products + else + @products = Product.all + end end private From f355e2ed0e489b6e24b699258e6ad455bd6a622d Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Thu, 19 Oct 2017 13:57:25 -0700 Subject: [PATCH 048/223] Add show page layout and styles for product --- app/assets/stylesheets/application.css | 27 ++++++++++++++++++++-- app/views/products/show.html.erb | 31 ++++++++++++++++++++------ 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 952f9fe4ef..0f5d8ba206 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -20,6 +20,8 @@ /*orange buttons #ff8533;*/ /*dark orange on hover #e65c00;*/ /*yellow #ffd24d;*/ + /*green for text #009933;*/ + /*grey #cccccc;*/ /** { border: 1px solid red; @@ -40,6 +42,13 @@ background-color: #e65c00; } + .cart { + margin: .5rem .1rem; + background-color: #ffd24d; + font-weight: bold; + margin-top: 3.6rem; + } + .ads { height: 7rem; padding: 1rem; @@ -68,10 +77,24 @@ } .show-im { - max-width: 100%; - max-height: 100%; + padding: 1rem 0; + text-align: center; } .show-desc li { list-style-type: none; + margin-right: 5rem; + } + + .rating { + border-bottom: 1px solid #cccccc; + } + + .green { + color: #009933; + font-weight: bold; + } + + .product { + border-bottom: 1px solid #cccccc; } diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index c271b95d66..3d6fc67a44 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,18 +1,35 @@ -
      -

      <%= @product.name %>

      +
      <%= image_tag(@product.image_url) %>
        +
      • <%= @product.name %>

      • +
      • rating in stars, 10 customer reviews
      • Price: <%= @product.price %>
      • -
      • Stock: <%= @product.stock %>
      • -
      • Retired?: <%= @product.retired %>
      • -
      • Description: <%= @product.description %>
      • -
      • Image URL: <%= @product.image_url %>
      • - + <% if @product.stock != nil %> +
      • In Stock (only <%= @product.stock %> left)
      • + <% else %> +
      • Out of Stock
      • + <% end %> +
      • <%= @product.description %>
      • +
      • Add to Cart

      +
      + + + + + + + <%# @product.reviews.each do |review| %> + + + <%# end %> + + +
      From 6269e5678f4c92f238544bd9b263ccad186e3f79 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Thu, 19 Oct 2017 14:47:55 -0700 Subject: [PATCH 049/223] Add layout and styles to root page --- app/assets/stylesheets/application.css | 32 +++++++++++++- app/controllers/main_controller.rb | 2 +- app/views/layouts/application.html.erb | 4 +- app/views/main/index.html.erb | 61 +++++++++++++++++++++++--- app/views/products/show.html.erb | 2 +- 5 files changed, 90 insertions(+), 11 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 0f5d8ba206..f422467fa9 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -16,7 +16,7 @@ */ - /*green header #66ad1f;*/ + /*green header&footer #66ad1f;*/ /*orange buttons #ff8533;*/ /*dark orange on hover #e65c00;*/ /*yellow #ffd24d;*/ @@ -98,3 +98,33 @@ .product { border-bottom: 1px solid #cccccc; } + + .media-highlight img { + margin-bottom: 1.5rem; + } + + aside li { + list-style-type: none; + border: 1px solid red; + } + + aside li img { + width: 50px; + } + + aside ul { + margin: 0; + } + + footer { + height: 5rem; + margin-top: 4rem; + background-color: #66ad1f; + text-align: center; + color: #fff; + font-weight: bold; + } + + footer p { + padding: 2rem; + } diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index 86dda5ef32..82096de823 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -1,5 +1,5 @@ class MainController < ApplicationController def index - + @products = Product.all end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index d2ddf19f2d..4d04596bc4 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -30,7 +30,7 @@ <%= link_to "log out", logout_path, class: "button" %> <% else %> <%= link_to "login", '/auth/github', class: "button float-right" %> - <% end %> + <% end %> @@ -39,7 +39,7 @@
      - +

      © 2017, The Big Bird, Inc.

      diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb index 8aa47fa940..33a231bd46 100644 --- a/app/views/main/index.html.erb +++ b/app/views/main/index.html.erb @@ -1,19 +1,51 @@ -
      +
      <%= image_tag "birds.png" %>
      -

      some heading

      +
      - +
      + <%= image_tag(@products.first.image_url) %> + <%= @products.first.name %> + <%= @products.first.price %> +
      +
      + <%= image_tag(@products.last.image_url) %> + <%= @products.last.name %> + <%= @products.last.price %> +
      +
      + <%= image_tag(@products.first.image_url) %> + <%= @products.first.name %> + <%= @products.first.price %> +
      @@ -37,7 +69,24 @@
-

some heading

+ +
+
+ <%= image_tag(@products.first.image_url) %> + <%= @products.first.name %> + <%= @products.first.price %> +
+
+ <%= image_tag(@products.last.image_url) %> + <%= @products.last.name %> + <%= @products.last.price %> +
+
+ <%= image_tag(@products.first.image_url) %> + <%= @products.first.name %> + <%= @products.first.price %> +
+
diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 3d6fc67a44..3a04b86856 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -5,7 +5,7 @@
diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index a6feb7f823..2d02c0418e 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -1,27 +1,22 @@ -

Create new product

-<%= form_for @product do |f| %> - <%= f.label :name %> - <%= f.text_field :name %> +
+

Create new product

+ <%= form_for @product do |f| %> + <%= f.label :name %> + <%= f.text_field :name %> - <%= f.label :price %> - <%= f.text_field :price %> + <%= f.label :price %> + <%= f.text_field :price %> - <%= f.label :stock %> - <%= f.text_field :stock %> + <%= f.label :stock %> + <%= f.text_field :stock %> - <%= f.label :retired %> - <%= f.text_field :retired %> + <%= f.label :description %> + <%= f.text_area :description %> - <%= f.label :description %> - <%= f.text_area :description %> + <%= f.label :image_url %> + <%= f.text_field :image_url %> - <%= f.label :image_url %> - <%= f.text_area :image_url %> + <%= f.submit class: "button"%> - <%= f.label :merchant_id %> - <%= f.text_area :merchant_id %> - - - <%= f.submit%> - -<% end %> + <% end %> +
diff --git a/db/seeds.rb b/db/seeds.rb index 18631865e3..38643fe6ac 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -87,6 +87,8 @@ puts "#{category2.name} has #{product.name}" end - +ActiveRecord::Base.connection.tables.each do |t| + ActiveRecord::Base.connection.reset_pk_sequence!(t) +end # puts "Added #{CategoriesProducts.count} categories products records" # puts "#{categories_failures.length} categories products failed to save" From be31093a32037282270d1f8101a7ab276dc55a70 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Fri, 20 Oct 2017 14:04:39 -0700 Subject: [PATCH 073/223] Fix products#index view to not show retired products --- app/views/products/index.html.erb | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 7dec18845e..334eb18a2c 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,9 +1,15 @@ -
- <% @products.each do |product| %> +<% products = @products.where(retired: false) %> +
+<% if !products.nil? %> + <% products.each do |product| %>
<%= link_to (image_tag(product.image_url)), product_path(product) %>

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

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

Sorry! We don't have any products

+<% end %> From 2b2999128d5473c0ddf5bfb0c975e8cb0b3c86bc Mon Sep 17 00:00:00 2001 From: Eva Sawyer Date: Fri, 20 Oct 2017 14:13:41 -0700 Subject: [PATCH 074/223] we can now buy things --- app/controllers/order_items_controller.rb | 40 ++++++++++++++--------- app/controllers/orders_controller.rb | 13 +++++--- app/controllers/products_controller.rb | 1 + app/models/order.rb | 8 ++--- app/views/order_item/index.html.erb | 10 ------ app/views/order_items/create.html.erb | 1 + app/views/order_items/index.html.erb | 17 ++++++++++ app/views/orders/edit.html.erb | 14 +++----- app/views/orders/show.html.erb | 4 +-- app/views/products/show.html.erb | 12 +++++++ config/routes.rb | 5 +-- 11 files changed, 77 insertions(+), 48 deletions(-) delete mode 100644 app/views/order_item/index.html.erb create mode 100644 app/views/order_items/create.html.erb create mode 100644 app/views/order_items/index.html.erb diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb index 240c8b5885..38ee515309 100644 --- a/app/controllers/order_items_controller.rb +++ b/app/controllers/order_items_controller.rb @@ -2,23 +2,31 @@ class OrderItemsController < ApplicationController def index #maybe just for that merchant - @order_items = OrderItem.all + @order_items = OrderItem.where(order_id: session[:order_id]) + end + + def new + @order_item = OrderItem.new end def create - @order_item = OrderItem.new(order_item_params) - if @order_item.save - # probably only need flash messages for the order? - # flash[:status] = :success - # flash[:result_text] = "Successfully created order item" - redirect_to root_path - else - # - # render :new - flash[:status] = :failure - flash[:result_text] = "Could not create order item" - flash[:details] = @order_item.errors.messages + #if there is already an open order, set the order_item order_id to that order. + #otherwise make a new order + if session[:order_id] == nil + @order = Order.create(status: "pending") + session[:order_id] = @order.id end + @order_item = OrderItem.new(product_id: params[:order_item][:product_id], quantity: params[:order_item][:quantity], order_id: session[:order_id]) + + @order_item.save! + redirect_to order_items_path + # else + # # + # # render :new + # flash[:status] = :failure + # flash[:result_text] = "Could not create order item" + # flash[:details] = @order_item.errors.messages + # end end def update @@ -58,7 +66,7 @@ def destroy private - def order_item_params - return params.require(:orderitem).permit(:product_id, :quantity, :order_id) - end + # def order_item_params + # return params.require(:orderitem).permit(:product_id, :quantity, :order_id) + # end end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 748b2e7232..9a9f34158d 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,5 +1,6 @@ class OrdersController < ApplicationController def index + @orders = Order.all end @@ -37,7 +38,6 @@ def create def update @order = Order.find(params[:id]) - @order.status = params[:order][:status] @order.customer_name = params[:order][:customer_name] @order.customer_email = params[:order][:customer_email] @order.customer_address = params[:order][:customer_address] @@ -46,14 +46,19 @@ def update @order.cc_ccv = params[:order][:cc_ccv] @order.zip_code = params[:order][:zip_code] - result = @order.save + # result = @order.save + puts "session before #{session[:order_id]}" - if result + if @order.save! flash[:notification] = 'Order was successfully updated' + @order.status = "paid" + @order.save + session[:order_id] = nil else flash[:failure] = 'Order was not updated' end - redirect_to orders_path + puts "session after #{session[:order_id]}" + redirect_to order_path(@order.id) end def edit diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 569e6eede2..9443f0a4fb 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -27,6 +27,7 @@ def edit def show @product = Product.find(params[:id]) + @order_item = OrderItem.new(product_id: params[:id]) end def update diff --git a/app/models/order.rb b/app/models/order.rb index 2fc8a8dd32..a0a8a71b96 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,6 +1,6 @@ class Order < ApplicationRecord - validates :status, - :customer_name, :customer_email, :customer_address, - :cc_number,:cc_expiration, :cc_ccv, - :zip_code, presence: true + validates :status, presence: true + # :customer_name, :customer_email, :customer_address, + # :cc_number,:cc_expiration, :cc_ccv, + # :zip_code, presence: true end diff --git a/app/views/order_item/index.html.erb b/app/views/order_item/index.html.erb deleted file mode 100644 index 6534150c57..0000000000 --- a/app/views/order_item/index.html.erb +++ /dev/null @@ -1,10 +0,0 @@ -

All Order Items

- -<% @order_items.each do |order_item| %> -
    -
  • ID: <%= link_to order_item.id, order_items_path(order_item) %>
  • -
  • Quantity: <%= order_item.quantity %>
  • -
  • Product ID: <%= order_item.product_id %>
  • -
  • Order ID: <%= order_item.order_id %>
  • -
-<% end %> diff --git a/app/views/order_items/create.html.erb b/app/views/order_items/create.html.erb new file mode 100644 index 0000000000..a9c74084a0 --- /dev/null +++ b/app/views/order_items/create.html.erb @@ -0,0 +1 @@ +

orderitem create

diff --git a/app/views/order_items/index.html.erb b/app/views/order_items/index.html.erb new file mode 100644 index 0000000000..66a0ad7a4e --- /dev/null +++ b/app/views/order_items/index.html.erb @@ -0,0 +1,17 @@ +

All Order Items

+ +<% @order_items.each do |order_item| %> +
    + +
  • <%= link_to order_item.product.name, order_items_path(order_item) %>
  • +
  • Quantity: <%= order_item.quantity %>
  • +
  • Product ID: <%= order_item.product_id %>
  • + <%@order_id = order_item.order_id %> +
  • Order ID: <%= order_item.order_id %>
  • +
+<% end %> + + +<%=link_to "Submit order", edit_order_path(@order_id), class: "button"%> + + diff --git a/app/views/orders/edit.html.erb b/app/views/orders/edit.html.erb index 9cca8e7ac1..0100786648 100644 --- a/app/views/orders/edit.html.erb +++ b/app/views/orders/edit.html.erb @@ -1,12 +1,6 @@ -<%= form_for @order do |f| %> - <%= f.label :status %> - <%= f.select :status, [ - ['pending', 'pending'], - ['paid', 'paid'], - ['complete', 'complete'], - ['closed', 'closed'] - ] %> +

Please enter billing and shipping information

+<%= form_for @order do |f| %> <%= f.label :customer_name %> <%= f.text_field :customer_name %> @@ -18,7 +12,7 @@ <%= f.label :cc_number %> <%= f.text_area :cc_number %> - + <%= f.label :cc_expiration %> <%= f.text_area :cc_expiration %> @@ -28,6 +22,6 @@ <%= f.label :zip_code %> <%= f.text_area :zip_code %> - <%= f.submit%> + <%= f.submit "Checkout"%> <% end %> diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb index 1a1caab3da..a3f4006d93 100644 --- a/app/views/orders/show.html.erb +++ b/app/views/orders/show.html.erb @@ -1,4 +1,4 @@ -

Order#: <%= @order.id %>

+

Confirmation page for Order#: <%= @order.id %>

  • Status: <%= @order.status %>
  • @@ -10,5 +10,5 @@
  • Billing Zipcode: <%= @order.zip_code %>
-<%= link_to 'All Orders', orders_path %> +<%#= link_to 'All Orders', orders_path %> <%= link_to 'Edit Order', edit_order_path %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 3a04b86856..226d3ee2d9 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -15,6 +15,18 @@ <% end %>
  • <%= @product.description %>
  • Add to Cart

  • +
    + + <%= form_for @order_item do |f| %> + <%= f.hidden_field :product_id, value: @product.id%> + <%= f.label :Quantity %> + <%= f.select :quantity, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] %> + <%= f.submit "Add to Cart", class: "button"%> + <% end %> + + + + <%#= link_to "Add to Cart", order_items_path, method: :post %> diff --git a/config/routes.rb b/config/routes.rb index 4a9d1d7171..aab53d1725 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,7 +10,8 @@ get '/orders/new', to: 'orders#new', as: 'new_order' post '/orders', to: 'orders#create' get '/orders/:id', to: 'orders#show', as: 'order' - get '/orders/:id/edit', to: 'orders#edit', as: 'edit_order' + get '/orders/:id/edit', to: 'orders#edit' + #, as: 'edit_order' patch '/orders/:id', to: 'orders#update' get '/reviews', to: 'reviews#index', as: 'reviews' @@ -23,7 +24,7 @@ resources :reviews root 'main#index' - resources :orderitems, only: [:create, :index, :destroy, :update] + resources :order_items, only: [:create, :index, :destroy, :update] resources :categories, only: [:new, :create] From 42876974b57ea23acee3cf5451293af5daa4241a Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Fri, 20 Oct 2017 14:17:45 -0700 Subject: [PATCH 075/223] Last changes --- app/views/products/merchant_products.html.erb | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/app/views/products/merchant_products.html.erb b/app/views/products/merchant_products.html.erb index 95fe9620c3..a6d50199d6 100644 --- a/app/views/products/merchant_products.html.erb +++ b/app/views/products/merchant_products.html.erb @@ -3,31 +3,33 @@
    <%= link_to "New Product", new_product_path, class: "button" %> <%= link_to "New Category", new_category_path, class: "button" %> -

    Products

    - - - - - - - - - - - - <% @merchant.products.each do |product| %> + <%# @merchant.products.group_by{ ||}(retired:) %> + +

    Products

    +
    ImageNameQuantityPriceManage
    + - - - - - + + + + + - <% end %> - -
    <%= image_tag product.image_url %><%= product.name %><%= product.stock %><%= product.price %><%= link_to "Edit", edit_product_path(product.id), class: "button" %> - <%= link_to "Retire", product_path(product.id), class: "button" %> - <%= link_to "Add quantity", product_path(product.id), class: "button" %>ImageNameQuantityPriceManage
    + + + <% @merchant.products.each do |product| %> + + <%= image_tag product.image_url %> + <%= product.name %> + <%= product.stock %> + <%= product.price %> + <%= link_to "Edit", edit_product_path(product.id), class: "button" %> + <%= link_to "Retire", product_path(product.id), class: "button" %> + <%= link_to "Add quantity", product_path(product.id), class: "button" %> + + <% end %> + +
    From 1c64e38a625484f5d2190947676eb06a4fc2b119 Mon Sep 17 00:00:00 2001 From: Eva Sawyer Date: Fri, 20 Oct 2017 14:22:41 -0700 Subject: [PATCH 076/223] merge problems --- config/routes.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index aab53d1725..850fb52ae4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,6 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html - resources :products resources :merchants @@ -20,6 +19,10 @@ get '/reviews/:id', to: 'review#show', as: 'review' get '/reviews/:id/edit', to: 'reviews#edit', as: 'edit_review' + get '/auth/:provider' + get '/auth/:provider/callback' + + resources :orders resources :reviews root 'main#index' From 26ea6016b1709b32c27e788d3f07c73c3ff2af77 Mon Sep 17 00:00:00 2001 From: Eva Sawyer Date: Fri, 20 Oct 2017 14:31:56 -0700 Subject: [PATCH 077/223] fix routes --- config/routes.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 0d1315ffcb..c656c9ba3c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -20,8 +20,9 @@ get '/reviews/:id', to: 'review#show', as: 'review' get '/reviews/:id/edit', to: 'reviews#edit', as: 'edit_review' - get '/auth/:provider' - get '/auth/:provider/callback' + # BUG?? + # get '/auth/:provider' + # get '/auth/:provider/callback' resources :orders From 55140ca7ada12c3e9f2d0222f103fe1a62163081 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Fri, 20 Oct 2017 14:58:28 -0700 Subject: [PATCH 078/223] Add partial view for form --- app/controllers/products_controller.rb | 3 ++- app/views/products/_form.html.erb | 22 +++++++++++++++ app/views/products/edit.html.erb | 27 +------------------ app/views/products/merchant_products.html.erb | 2 +- app/views/products/new.html.erb | 23 +--------------- 5 files changed, 27 insertions(+), 50 deletions(-) create mode 100644 app/views/products/_form.html.erb diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index a8e9c0a051..142c18707a 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -35,7 +35,8 @@ def update if @product.save flash[:status] = :success flash[:result_text] = "Successfully updated #{@product.name}, ID number #{@product.id}" - redirect_to product_path(@product) + # redirect_to product_path(@product) + redirect_to merchant_products_path(session[:merchant_id]) else flash[:status] = :failure flash[:result_text] = "Could not updated #{@product.name}, ID number #{@product.id}" diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb new file mode 100644 index 0000000000..2d02c0418e --- /dev/null +++ b/app/views/products/_form.html.erb @@ -0,0 +1,22 @@ +
    +

    Create new product

    + <%= form_for @product do |f| %> + <%= f.label :name %> + <%= f.text_field :name %> + + <%= f.label :price %> + <%= f.text_field :price %> + + <%= f.label :stock %> + <%= f.text_field :stock %> + + <%= f.label :description %> + <%= f.text_area :description %> + + <%= f.label :image_url %> + <%= f.text_field :image_url %> + + <%= f.submit class: "button"%> + + <% end %> +
    diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb index fd2fc2d598..d44c608b6a 100644 --- a/app/views/products/edit.html.erb +++ b/app/views/products/edit.html.erb @@ -1,26 +1 @@ -<%= form_for @product do |f| %> - <%= f.label :name %> - <%= f.text_field :name %> - - <%= f.label :price %> - <%= f.text_field :price %> - - <%= f.label :stock %> - <%= f.text_field :stock %> - - <%= f.label :retired %> - <%= f.text_field :retired %> - - <%= f.label :description %> - <%= f.text_area :description %> - - <%= f.label :image_url %> - <%= f.text_area :image_url %> - - <%= f.label :merchant_id %> - <%= f.text_area :merchant_id %> - - - <%= f.submit%> - -<% end %> +<%= render partial: "form" %> diff --git a/app/views/products/merchant_products.html.erb b/app/views/products/merchant_products.html.erb index a6d50199d6..e5e91823a3 100644 --- a/app/views/products/merchant_products.html.erb +++ b/app/views/products/merchant_products.html.erb @@ -20,7 +20,7 @@ <% @merchant.products.each do |product| %> <%= image_tag product.image_url %> - <%= product.name %> + <%= link_to product.name, product_path(product.id) %> <%= product.stock %> <%= product.price %> <%= link_to "Edit", edit_product_path(product.id), class: "button" %> diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index 2d02c0418e..d44c608b6a 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -1,22 +1 @@ -
    -

    Create new product

    - <%= form_for @product do |f| %> - <%= f.label :name %> - <%= f.text_field :name %> - - <%= f.label :price %> - <%= f.text_field :price %> - - <%= f.label :stock %> - <%= f.text_field :stock %> - - <%= f.label :description %> - <%= f.text_area :description %> - - <%= f.label :image_url %> - <%= f.text_field :image_url %> - - <%= f.submit class: "button"%> - - <% end %> -
    +<%= render partial: "form" %> From 2c4032231de8679d7cbe3542b339945c63237d94 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Fri, 20 Oct 2017 18:36:04 -0700 Subject: [PATCH 079/223] Add view for both statuses of products --- app/controllers/products_controller.rb | 3 +-- app/views/products/_form.html.erb | 3 +++ app/views/products/merchant_products.html.erb | 18 ++++++++++++++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 142c18707a..015c6f02cb 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -35,7 +35,6 @@ def update if @product.save flash[:status] = :success flash[:result_text] = "Successfully updated #{@product.name}, ID number #{@product.id}" - # redirect_to product_path(@product) redirect_to merchant_products_path(session[:merchant_id]) else flash[:status] = :failure @@ -62,7 +61,7 @@ def index private def product_params - params.require(:product).permit(:name, :price, :stock, :description, :image_url) + params.require(:product).permit(:name, :price, :stock, :retired, :description, :image_url) end end diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb index 2d02c0418e..a45c7163dd 100644 --- a/app/views/products/_form.html.erb +++ b/app/views/products/_form.html.erb @@ -10,6 +10,9 @@ <%= f.label :stock %> <%= f.text_field :stock %> + <%= f.hidden_field :retired %> + <%= f.hidden_field :retired %> + <%= f.label :description %> <%= f.text_area :description %> diff --git a/app/views/products/merchant_products.html.erb b/app/views/products/merchant_products.html.erb index e5e91823a3..eb55b3ebc2 100644 --- a/app/views/products/merchant_products.html.erb +++ b/app/views/products/merchant_products.html.erb @@ -3,9 +3,14 @@
    <%= link_to "New Product", new_product_path, class: "button" %> <%= link_to "New Category", new_category_path, class: "button" %> - <%# @merchant.products.group_by{ ||}(retired:) %> -

    Products

    + <% products_by_status = @merchant.products.group_by{ |p| p.retired } %> + <% products_by_status.each do |status, products| %> + <% if status %> +

    Retired Products

    + <% else %> +

    Active Products

    + <% end %> @@ -17,19 +22,24 @@ - <% @merchant.products.each do |product| %> + <% products.each do |product| %> <% end %>
    <%= image_tag product.image_url %> <%= link_to product.name, product_path(product.id) %> <%= product.stock %> <%= product.price %> <%= link_to "Edit", edit_product_path(product.id), class: "button" %> - <%= link_to "Retire", product_path(product.id), class: "button" %> + <% if !product.retired %> + <%= link_to "Retire", product_path(product.id, :product => {:retired => true }), method: :patch, class: "button" %> + <% else %> + <%= link_to "Activate", product_path(product.id, :product => {:retired => false }), method: :patch, class: "button" %> + <% end %> <%= link_to "Add quantity", product_path(product.id), class: "button" %>
    + <% end %>
    From 2a0d8c820c82a06089ec24ae163e23f0e3594ea8 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Fri, 20 Oct 2017 20:51:01 -0700 Subject: [PATCH 080/223] Add categories#index view --- app/assets/stylesheets/application.css | 4 +-- app/controllers/categories_controller.rb | 13 +++----- app/controllers/products_controller.rb | 2 -- app/views/categories/index.html.erb | 30 +++++++++++++++++++ app/views/merchants/_nav_aside.html.erb | 1 + app/views/products/merchant_products.html.erb | 8 +++-- config/routes.rb | 2 +- 7 files changed, 43 insertions(+), 17 deletions(-) create mode 100644 app/views/categories/index.html.erb diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index fd67585d3a..dfa59a42d2 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -133,8 +133,8 @@ margin-top: 1rem; } -.merchant-show section:first-of-type{ - border-right: 1px solid #cccccc;; +.merchant-show section:last-of-type{ + border-left: 1px solid #cccccc;; } .merchant-show li:nth-child(-n+2) { diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 6d40b04b1e..1210d81459 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -3,15 +3,10 @@ def new @category = Category.new end - # def index - # @categoty = Category.all - # end - # - # def show - # @categories = Category.find(params[:id]) - # @category = @category.product - # end - + def index + @categories = Category.all + # @merchant = Merchant.find(params[:id]) + end def create @category = Category.new(category_params) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 015c6f02cb..dcc88931d1 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -64,5 +64,3 @@ def product_params params.require(:product).permit(:name, :price, :stock, :retired, :description, :image_url) end end - -# name: params[:product][:name],price: params[:product][:price], stock: params[:product][:stock], retired: params[:product][:retired], description: params[:product][:description], image_url: params[:product][:image_url], merchant: params[:product][:merchant] diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb new file mode 100644 index 0000000000..1b9727e34e --- /dev/null +++ b/app/views/categories/index.html.erb @@ -0,0 +1,30 @@ +
    + <%= render partial: "merchants/nav_aside" %> +
    + <%= link_to "New Product", new_product_path, class: "button" %> + <%= link_to "New Category", new_category_path, class: "button" %> + +

    Available Categories

    + + + + + + + + + + + <% @categories.each do |category| %> + + + + + + + <% end %> + +
    CategoryProductsMy ProductsAdd Product
    <%= link_to category.name, category_products_path(category.id) %><%= link_to category.products.count, category_products_path(category.id) %><%#= link_to %>my products<%= link_to "New Product", new_product_path, class: "button" %>
    +
    + +
    diff --git a/app/views/merchants/_nav_aside.html.erb b/app/views/merchants/_nav_aside.html.erb index 394e1542fa..dbcae555ae 100644 --- a/app/views/merchants/_nav_aside.html.erb +++ b/app/views/merchants/_nav_aside.html.erb @@ -5,6 +5,7 @@
  • <%= @merchant.email %>
  • <%= link_to "Dashboard", merchant_path(@merchant.id) %>
  • <%= link_to "Manage Products", merchant_products_path(@merchant.id) %>
  • +
  • <%= link_to "Manage Categories", categories_path %>
  • <%= link_to "Manage Orders", merchant_path(@merchant.id) %>
  • <% end %> diff --git a/app/views/products/merchant_products.html.erb b/app/views/products/merchant_products.html.erb index eb55b3ebc2..f9a4082f09 100644 --- a/app/views/products/merchant_products.html.erb +++ b/app/views/products/merchant_products.html.erb @@ -16,8 +16,9 @@ Image Name - Quantity - Price + Rating + Quantity + Price Manage @@ -26,6 +27,7 @@ <%= image_tag product.image_url %> <%= link_to product.name, product_path(product.id) %> + rating <%= product.stock %> <%= product.price %> <%= link_to "Edit", edit_product_path(product.id), class: "button" %> @@ -34,7 +36,7 @@ <% else %> <%= link_to "Activate", product_path(product.id, :product => {:retired => false }), method: :patch, class: "button" %> <% end %> - <%= link_to "Add quantity", product_path(product.id), class: "button" %> + <% end %> diff --git a/config/routes.rb b/config/routes.rb index 9f6bb36cd8..f9c72adfba 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -32,7 +32,7 @@ resources :order_items, only: [:create, :index, :destroy, :update] - resources :categories, only: [:new, :create] + resources :categories, only: [:new, :create, :index] # nested routes resources :categories do From b62507798eb6b0749b8bc133c129f7efd3ffa31b Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Fri, 20 Oct 2017 22:07:33 -0700 Subject: [PATCH 081/223] Add categories page for merchants --- app/controllers/categories_controller.rb | 4 ++-- app/views/categories/new.html.erb | 5 ++++- app/views/merchants/_nav_aside.html.erb | 2 +- app/views/products/_form.html.erb | 3 +++ app/views/products/merchant_products.html.erb | 4 ++-- config/routes.rb | 10 ++++++++++ 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 1210d81459..c4eb7beed3 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -5,7 +5,7 @@ def new def index @categories = Category.all - # @merchant = Merchant.find(params[:id]) + @merchant = Merchant.find_by(id: params[:merchant_id]) end def create @@ -13,7 +13,7 @@ def create if @category.save flash[:status] = :success flash[:message] = "Successfully created category: #{@category.name}" - redirect_to root_path + redirect_to categories_path else flash[:status] = :failure flash[:message] = "Could not create category" diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb index 61bb407a83..872195f4d4 100644 --- a/app/views/categories/new.html.erb +++ b/app/views/categories/new.html.erb @@ -1,7 +1,10 @@ -

    Make a New Category

    +
    +

    Create new category

    <%= form_for @category do |f| %> <%=f.label :name %> <%=f.text_field :name %> + <%= f.submit %> <%end%> +
    diff --git a/app/views/merchants/_nav_aside.html.erb b/app/views/merchants/_nav_aside.html.erb index dbcae555ae..1163303673 100644 --- a/app/views/merchants/_nav_aside.html.erb +++ b/app/views/merchants/_nav_aside.html.erb @@ -5,7 +5,7 @@
  • <%= @merchant.email %>
  • <%= link_to "Dashboard", merchant_path(@merchant.id) %>
  • <%= link_to "Manage Products", merchant_products_path(@merchant.id) %>
  • -
  • <%= link_to "Manage Categories", categories_path %>
  • +
  • <%= link_to "Manage Categories", merchant_categories_path %>
  • <%= link_to "Manage Orders", merchant_path(@merchant.id) %>
  • <% end %> diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb index a45c7163dd..e65597d913 100644 --- a/app/views/products/_form.html.erb +++ b/app/views/products/_form.html.erb @@ -19,6 +19,9 @@ <%= f.label :image_url %> <%= f.text_field :image_url %> + <%#= f.label :category %> + <%#= f.collection_select(:category_id, Category.all, :id, :name, {}, {:multiple => true}) %> + <%= f.submit class: "button"%> <% end %> diff --git a/app/views/products/merchant_products.html.erb b/app/views/products/merchant_products.html.erb index f9a4082f09..f5e5b0001e 100644 --- a/app/views/products/merchant_products.html.erb +++ b/app/views/products/merchant_products.html.erb @@ -4,8 +4,8 @@ <%= link_to "New Product", new_product_path, class: "button" %> <%= link_to "New Category", new_category_path, class: "button" %> - <% products_by_status = @merchant.products.group_by{ |p| p.retired } %> - <% products_by_status.each do |status, products| %> + <% [false, true].each do |status| %> + <% products = @merchant.products.where(retired: status) %> <% if status %>

    Retired Products

    <% else %> diff --git a/config/routes.rb b/config/routes.rb index f9c72adfba..0a51b54dfb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -43,6 +43,16 @@ resources :products, only: [:index] end + resources :merchants do + resources :categories, only: [:index] + end + + resources :merchants do + resources :categories, only: [:show] do + resources :products, only: [:index] + end + end + get '/auth/:provider/callback', to: 'merchants#login', as: 'auth_callback' get 'logout', to: 'merchants#logout', as: 'logout' From e09db29be5b5e630f173cb3247171c73fdd4b71e Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Fri, 20 Oct 2017 22:18:38 -0700 Subject: [PATCH 082/223] Add join table for products and categories and set relationships --- app/models/product.rb | 1 + .../20171021051351_create_products_categories_join.rb | 10 ++++++++++ db/schema.rb | 11 ++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20171021051351_create_products_categories_join.rb diff --git a/app/models/product.rb b/app/models/product.rb index af9012c3a6..d19a85ceef 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,5 +1,6 @@ class Product < ApplicationRecord + has_and_belongs_to_many :categories belongs_to :merchant has_many :order_item diff --git a/db/migrate/20171021051351_create_products_categories_join.rb b/db/migrate/20171021051351_create_products_categories_join.rb new file mode 100644 index 0000000000..6ef2b60ebd --- /dev/null +++ b/db/migrate/20171021051351_create_products_categories_join.rb @@ -0,0 +1,10 @@ +class CreateProductsCategoriesJoin < ActiveRecord::Migration[5.1] + def change + create_table :products_categories_joins do |t| + t.belongs_to :product, index: true + t.belongs_to :category, index: true + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 8e32ca3ef3..6c60076189 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: 20171019043601) do +ActiveRecord::Schema.define(version: 20171021051351) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -68,6 +68,15 @@ t.datetime "updated_at", null: false end + create_table "products_categories_joins", force: :cascade do |t| + t.bigint "product_id" + t.bigint "category_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["category_id"], name: "index_products_categories_joins_on_category_id" + t.index ["product_id"], name: "index_products_categories_joins_on_product_id" + end + create_table "reviews", force: :cascade do |t| t.integer "product_id" t.string "text" From 29a0b3888c013699a5cd3463b5914a858b68e07d Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Fri, 20 Oct 2017 22:32:38 -0700 Subject: [PATCH 083/223] Fix merchant_category route --- app/views/merchants/_nav_aside.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/merchants/_nav_aside.html.erb b/app/views/merchants/_nav_aside.html.erb index 1163303673..6549666795 100644 --- a/app/views/merchants/_nav_aside.html.erb +++ b/app/views/merchants/_nav_aside.html.erb @@ -5,7 +5,7 @@
  • <%= @merchant.email %>
  • <%= link_to "Dashboard", merchant_path(@merchant.id) %>
  • <%= link_to "Manage Products", merchant_products_path(@merchant.id) %>
  • -
  • <%= link_to "Manage Categories", merchant_categories_path %>
  • +
  • <%= link_to "Manage Categories", merchant_categories_path(@merchant.id) %>
  • <%= link_to "Manage Orders", merchant_path(@merchant.id) %>
  • <% end %> From 4a153baa65891282ecb4fcc9e5a6fc8d4e5223a1 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Fri, 20 Oct 2017 22:53:53 -0700 Subject: [PATCH 084/223] Add check boxes to product form --- app/views/products/_form.html.erb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb index e65597d913..5e006e6d53 100644 --- a/app/views/products/_form.html.erb +++ b/app/views/products/_form.html.erb @@ -19,10 +19,15 @@ <%= f.label :image_url %> <%= f.text_field :image_url %> - <%#= f.label :category %> - <%#= f.collection_select(:category_id, Category.all, :id, :name, {}, {:multiple => true}) %> + <%= f.collection_check_boxes :category_ids, Category.all, :id, :name do |b| %> + <%= b.check_box %> + <%= b.label %> + <% end %> + +
    + <%= f.submit class: "button"%> +
    - <%= f.submit class: "button"%> <% end %>
    From 3bbec13d27d3ee68ffa7b65ea1d637c302072cac Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Fri, 20 Oct 2017 23:34:29 -0700 Subject: [PATCH 085/223] Fix new and update for creating product with categories --- app/controllers/products_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index dcc88931d1..9521c1c02f 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -61,6 +61,6 @@ def index private def product_params - params.require(:product).permit(:name, :price, :stock, :retired, :description, :image_url) + params.require(:product).permit(:name, :price, :stock, :retired, :description, :image_url, category_ids: []) end end From 92b46f14d57c8aac9f877ec7767f8a7b589bf3c0 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Sat, 21 Oct 2017 11:20:44 -0700 Subject: [PATCH 086/223] Add max quantity to cart --- app/assets/stylesheets/application.css | 13 ++++++++++++- app/views/products/show.html.erb | 11 +++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index dfa59a42d2..847a5efeb4 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -46,7 +46,6 @@ margin: .5rem .1rem; background-color: #ffd24d; font-weight: bold; - margin-top: 3.6rem; } .ads { @@ -81,6 +80,10 @@ text-align: center; } + .show-desc { + margin-top: 1.3rem; + } + .show-desc li { list-style-type: none; margin-right: 5rem; @@ -157,3 +160,11 @@ .merchant-show table .button { margin: 0; } + +#merchant { + line-height: 1px; +} + +.show-desc form { + margin-top: 2rem; +} diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 226d3ee2d9..fa99bd60a1 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -5,6 +5,7 @@
      +
    • <%= link_to @product.merchant.username, root_path %>
    • <%= @product.name %>

    • rating in stars, 10 customer reviews
    • Price: <%= @product.price %>
    • @@ -14,19 +15,13 @@
    • Out of Stock
    • <% end %>
    • <%= @product.description %>
    • -
    • Add to Cart

    • -
      <%= form_for @order_item do |f| %> <%= f.hidden_field :product_id, value: @product.id%> <%= f.label :Quantity %> - <%= f.select :quantity, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] %> - <%= f.submit "Add to Cart", class: "button"%> + <%= f.select :quantity, (1..@product.stock).to_a %> + <%= f.submit "Add to Cart", class: "cart button"%> <% end %> - - - - <%#= link_to "Add to Cart", order_items_path, method: :post %>
    From 0f9f6bfb419c14c0618c4267658c088643567732 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Sat, 21 Oct 2017 11:31:30 -0700 Subject: [PATCH 087/223] Add nice view of cart button and merchant to product page --- app/assets/stylesheets/application.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 847a5efeb4..8181de61b2 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -168,3 +168,9 @@ .show-desc form { margin-top: 2rem; } + +.show-desc select { + width: 100px; + margin: .5rem .1rem; + height: 40.469px; +} From 747d592c847b94be29b682b2aae02de95ad6c724 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Sat, 21 Oct 2017 13:36:39 -0700 Subject: [PATCH 088/223] Add categories to product show page and double nested route for products by category and merchant --- app/assets/stylesheets/application.css | 14 +++++++++++- app/controllers/products_controller.rb | 6 ++++- app/views/categories/index.html.erb | 2 +- app/views/products/show.html.erb | 7 +++++- config/routes.rb | 31 +++++++++++--------------- 5 files changed, 38 insertions(+), 22 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 8181de61b2..2b6b7c96e0 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -21,7 +21,8 @@ /*dark orange on hover #e65c00;*/ /*yellow #ffd24d;*/ /*green for text #009933;*/ - /*grey #cccccc;*/ + /*grey border #cccccc;*/ + /*grey category buttons #a6a6a6;*/ /** { border: 1px solid red; @@ -174,3 +175,14 @@ margin: .5rem .1rem; height: 40.469px; } + +/*product#show*/ +.categories a { + margin-top: 1rem; + color: #fff; + font-weight: bold; +} + +.categories .button { + background-color: #a6a6a6; +} diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 9521c1c02f..d54ad7d72e 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -46,7 +46,11 @@ def update def index - if params[:category_id] + if params[:merchant_id] && params[:category_id] + @merchant = Merchant.find_by(id: params[:merchant_id]) + @category = Category.find_by(id: params[:category_id]) + @products = @category.products.where(merchant: @merchant) + elsif params[:category_id] category = Category.find_by(id: params[:category_id]) @products = category.products elsif params[:merchant_id] diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index 1b9727e34e..2da274a830 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -19,7 +19,7 @@ <%= link_to category.name, category_products_path(category.id) %> <%= link_to category.products.count, category_products_path(category.id) %> - <%#= link_to %>my products + <%= link_to category.products.where(merchant: @merchant).count, merchant_category_products_path(@merchant.id, category.id)%> <%= link_to "New Product", new_product_path, class: "button" %> <% end %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index fa99bd60a1..8880c47a08 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -2,10 +2,15 @@
    <%= image_tag(@product.image_url) %> +
    + <% @product.categories.each do |category| %> + <%= link_to category.name, category_products_path(category.id), class: "button small" %> + <% end %> +
      -
    • <%= link_to @product.merchant.username, root_path %>
    • +
    • <%= link_to @product.merchant.username, merchant_path(@product.merchant) %>
    • <%= @product.name %>

    • rating in stars, 10 customer reviews
    • Price: <%= @product.price %>
    • diff --git a/config/routes.rb b/config/routes.rb index 0a51b54dfb..b9cfecfbf2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,24 +6,19 @@ resources :merchants - get '/orders', to: 'orders#index', as: 'orders' - get '/orders/new', to: 'orders#new', as: 'new_order' - post '/orders', to: 'orders#create' - get '/orders/:id', to: 'orders#show', as: 'order' - get '/orders/:id/edit', to: 'orders#edit' - #, as: 'edit_order' - patch '/orders/:id', to: 'orders#update' - - get '/reviews', to: 'reviews#index', as: 'reviews' - get '/reviews/new', to: 'reviews#new', as: 'new_review' - post '/reviews', to: 'reviews#create' - get '/reviews/:id', to: 'review#show', as: 'review' - get '/reviews/:id/edit', to: 'reviews#edit', as: 'edit_review' - - # BUG?? - # get '/auth/:provider' - # get '/auth/:provider/callback' - + # get '/orders', to: 'orders#index', as: 'orders' + # get '/orders/new', to: 'orders#new', as: 'new_order' + # post '/orders', to: 'orders#create' + # get '/orders/:id', to: 'orders#show', as: 'order' + # get '/orders/:id/edit', to: 'orders#edit' + # #, as: 'edit_order' + # patch '/orders/:id', to: 'orders#update' + + # get '/reviews', to: 'reviews#index', as: 'reviews' + # get '/reviews/new', to: 'reviews#new', as: 'new_review' + # post '/reviews', to: 'reviews#create' + # get '/reviews/:id', to: 'review#show', as: 'review' + # get '/reviews/:id/edit', to: 'reviews#edit', as: 'edit_review' resources :orders resources :reviews From 336094181a4993e9e5cfc5a0639bf541b0336d6a Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Sat, 21 Oct 2017 20:20:01 -0700 Subject: [PATCH 089/223] Fix create new category --- app/assets/stylesheets/application.css | 1 - app/controllers/categories_controller.rb | 17 ++++++++++---- app/views/categories/index.html.erb | 6 ++--- app/views/categories/new.html.erb | 14 +++++++---- app/views/layouts/application.html.erb | 23 ++++++++++++++++++- app/views/products/merchant_products.html.erb | 2 +- config/routes.rb | 4 ++-- 7 files changed, 48 insertions(+), 19 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 2b6b7c96e0..ec4dddd619 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -109,7 +109,6 @@ aside li, .merchant-show li { list-style-type: none; - border: 1px solid red; } aside li img { diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index c4eb7beed3..f077c1019f 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -1,6 +1,7 @@ class CategoriesController < ApplicationController def new @category = Category.new + @merchant = Merchant.find_by(id: params[:merchant_id]) end def index @@ -10,15 +11,21 @@ def index def create @category = Category.new(category_params) - if @category.save + @merchant = Merchant.find_by(id: session[:merchant_id]) + + if Category.all.find_by(name: @category.name) + flash[:status] = :failure + flash[:notice] = "Category with this name already exist" + redirect_to new_merchant_category_path(@merchant.id) + elsif @category.save flash[:status] = :success - flash[:message] = "Successfully created category: #{@category.name}" - redirect_to categories_path + flash[:notice] = "Successfully created category: #{@category.name}" + redirect_to merchant_categories_path(@merchant.id) else flash[:status] = :failure - flash[:message] = "Could not create category" + flash[:notice] = "Could not create category" flash[:details] = @category.errors.messages - render :new, status: :bad_request + redirect_to new_merchant_category_path(@merchant.id) end end diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index 2da274a830..ecb6278db9 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -2,16 +2,15 @@ <%= render partial: "merchants/nav_aside" %>
      <%= link_to "New Product", new_product_path, class: "button" %> - <%= link_to "New Category", new_category_path, class: "button" %> + <%= link_to "New Category", new_merchant_category_path, class: "button" %>

      Available Categories

      - + - @@ -20,7 +19,6 @@ - <% end %> diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb index 872195f4d4..1e22d03dfb 100644 --- a/app/views/categories/new.html.erb +++ b/app/views/categories/new.html.erb @@ -1,10 +1,14 @@ -
      -

      Create new category

      +
      + <%= render partial: "merchants/nav_aside" %> + +
      +

      Create new category

      - <%= form_for @category do |f| %> + <%= form_for @category do |f| %> <%=f.label :name %> <%=f.text_field :name %> <%= f.submit %> - <%end%> -
      + <%end%> +
      + diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index b110ca8536..f1900f43af 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -21,7 +21,6 @@
      CategoryCategory Products My ProductsAdd Product
      <%= link_to category.name, category_products_path(category.id) %> <%= link_to category.products.count, category_products_path(category.id) %> <%= link_to category.products.where(merchant: @merchant).count, merchant_category_products_path(@merchant.id, category.id)%><%= link_to "New Product", new_product_path, class: "button" %>
      + + + + + + + + + + + + + + <% @quantity_sum = 0 %> + <% @total = 0 %> + <% @order_items.each do |order_item| %> + + + + + + + + + + <% @quantity_sum += order_item.quantity %> + <%@total+=order_item.product.price * order_item.quantity%> + + + <% end %> + + + + + + +
      OrderDateProductPriceQuantitySubtotalItem StatusOrder Status
      <%=link_to order_item.order_id, order_path(order_item.order_id)%><%=order_item.created_at%><%=link_to order_item.product.name, product_path(order_item.product_id)%><%=order_item.product.price%><%=order_item.quantity%><%=order_item.product.price * order_item.quantity%> + <%#form_for%> + <%# link_to "Edit", edit_product_path(product.id), class: "button" %> + <% if order_item.order.status != "Shipped" %> + <%= link_to "Ship", order_path(order_item.order_id, :order => {:status => "Shipped" }), method: :patch, class: "button" %> + <% else %> + <%="Shipped"%> + <% end %> + <%=link_to "cancel", order_item_path(order_item.id), method: :delete, class: "button"%> + + <%#link_to "Submit order", edit_order_path(@order_id), class: "button"%> + + <%=order_item.order.status%>
      total<%=@quantity_sum%><%=@total%>
      +
      +
    From 652b4ed7c190d845310382bcd2165fdc0b3e282f Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Mon, 23 Oct 2017 11:05:42 -0700 Subject: [PATCH 110/223] Add test for double login case --- test/controllers/merchants_controller_test.rb | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/test/controllers/merchants_controller_test.rb b/test/controllers/merchants_controller_test.rb index 9aace6ac64..a821f0d267 100644 --- a/test/controllers/merchants_controller_test.rb +++ b/test/controllers/merchants_controller_test.rb @@ -71,20 +71,19 @@ end - # it "tells the merchant that they're already logged in if that is true" do - # start_count = Merchant.count - # - # merchant = merchants(:eva) - # - # login(merchant) - # login(merchant) - # - # must_respond_with :bad_request - # must_redirect_to root_path - # session[:merchant_id].must_equal merchant.id - # Merchant.count.must_equal start_count - # - # end + it "tells the merchant that they're already logged in if that is true" do + start_count = Merchant.count + + merchant = merchants(:eva) + + login(merchant) + login(merchant) + + must_respond_with :redirect + must_redirect_to root_path + Merchant.count.must_equal start_count + + end it "redirects to the root path if given invalid user data" do start_count = Merchant.count From c68f67435832e40ead44fdf2ba4e402b2e3b218e Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Mon, 23 Oct 2017 11:39:26 -0700 Subject: [PATCH 111/223] Add new relation of product with review and tests --- app/models/product.rb | 3 ++- app/models/review.rb | 5 +++++ db/migrate/20171023181913_add_rating_to_reviews.rb | 5 +++++ db/schema.rb | 3 ++- test/models/product_test.rb | 7 +++++++ test/models/review_test.rb | 12 +++++++++--- 6 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 db/migrate/20171023181913_add_rating_to_reviews.rb diff --git a/app/models/product.rb b/app/models/product.rb index 368571e0d8..7e9ee3e7bd 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -2,11 +2,12 @@ class Product < ApplicationRecord has_and_belongs_to_many :categories belongs_to :merchant + has_many :reviews has_many :order_items validates :name, presence: true, uniqueness: true validates :price, presence: true - validates_numericality_of :price, greater_than: 0 + validates :price, numericality: { greater_than: 0 } def self.random_products(number) diff --git a/app/models/review.rb b/app/models/review.rb index b2ca4935ed..552aa441e2 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -1,2 +1,7 @@ class Review < ApplicationRecord + + belongs_to :product + + validates :rating, presence: true + validates :rating, numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 5, message: "Please enter a rating from 1 to 5" } end diff --git a/db/migrate/20171023181913_add_rating_to_reviews.rb b/db/migrate/20171023181913_add_rating_to_reviews.rb new file mode 100644 index 0000000000..8d3a2febcc --- /dev/null +++ b/db/migrate/20171023181913_add_rating_to_reviews.rb @@ -0,0 +1,5 @@ +class AddRatingToReviews < ActiveRecord::Migration[5.1] + def change + add_column :reviews, :rating, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 6c60076189..8adde15c1d 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: 20171021051351) do +ActiveRecord::Schema.define(version: 20171023181913) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -82,6 +82,7 @@ t.string "text" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "rating" end end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index 2fd3983696..adc6131ccd 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -24,6 +24,13 @@ category.must_be_kind_of Category end end + + it "has many reviews" do + @product.must_respond_to :reviews + @product.reviews.each do |review| + review.must_be_kind_of Review + end + end end describe "validations" do diff --git a/test/models/review_test.rb b/test/models/review_test.rb index ce8378a033..8155895708 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -1,9 +1,15 @@ require "test_helper" describe Review do - let(:review) { Review.new } + describe "relations" do + before do + @review = reviews(:one) + end - it "must be valid" do - value(review).must_be :valid? + it "belongs to product" do + @review.must_respond_to :product + @review.product.must_be_kind_of Product + end end + end From 5f0f4b51d1b81239dd643320574b69208b166f3e Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Mon, 23 Oct 2017 11:43:07 -0700 Subject: [PATCH 112/223] Fix fixtures for reviews and add relations of product with reviews and tests --- test/fixtures/reviews.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml index 662f1288bb..90aed236b2 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: - product_id: 1 + product: one text: 'review text 1' two: - product_id: 1 + product: one text: 'review text 2' From 20379cbbc70230cce9fc8279e1a9b765b18afcbb Mon Sep 17 00:00:00 2001 From: Rebecca Bergena Date: Mon, 23 Oct 2017 11:47:29 -0700 Subject: [PATCH 113/223] add status to order item and add functionality to merchant manage orders page --- app/controllers/order_items_controller.rb | 27 +++++++++++-------- app/controllers/orders_controller.rb | 3 +++ app/views/orders/merchant_orders.html.erb | 13 +++------ ...0171023181341_add_status_to_order_items.rb | 5 ++++ db/schema.rb | 3 ++- 5 files changed, 30 insertions(+), 21 deletions(-) create mode 100644 db/migrate/20171023181341_add_status_to_order_items.rb diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb index 794bbf8b9d..51759129e0 100644 --- a/app/controllers/order_items_controller.rb +++ b/app/controllers/order_items_controller.rb @@ -1,4 +1,5 @@ class OrderItemsController < ApplicationController + skip_before_action :require_login def index #maybe just for that merchant @@ -31,17 +32,21 @@ def create def update @order_item = OrderItem.find(params[:id]) - @order_item.update_attributes(order_item_params) - if @order_item.save - redirect_to root_path - else - # render :edit - end + # @order_item.update_attributes(order_item_params) + # if @order_item.save + # redirect_to root_path + # else + # # render :edit + # end @order_item.update_attributes(order_item_params) - if save_and_flash(@order_item, "update") - redirect_to order_item_path(@order_item.id) + # if save_and_flash(@order_item, "update") + if @order_item.save + flash[:status] = :success + flash[:result_text] = "Successfully updated order item." + redirect_back fallback_location: { action: "index"} + # redirect_to order_item_path(@order_item.id) else render :edit, status: :bad_request end @@ -69,7 +74,7 @@ def destroy private - # def order_item_params - # return params.require(:orderitem).permit(:product_id, :quantity, :order_id) - # end + def order_item_params + return params.require(:order_item).permit(:product_id, :quantity, :order_id, :status) + end end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 0e85739d0e..4131a03553 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,4 +1,7 @@ class OrdersController < ApplicationController + + skip_before_action :require_login + def index if params[:merchant_id] @merchant = Merchant.find_by(id: params[:merchant_id]) diff --git a/app/views/orders/merchant_orders.html.erb b/app/views/orders/merchant_orders.html.erb index 631ec17cf7..05d9e1e80d 100644 --- a/app/views/orders/merchant_orders.html.erb +++ b/app/views/orders/merchant_orders.html.erb @@ -27,17 +27,12 @@ <%=order_item.quantity%> <%=order_item.product.price * order_item.quantity%> - <%#form_for%> - <%# link_to "Edit", edit_product_path(product.id), class: "button" %> - <% if order_item.order.status != "Shipped" %> - <%= link_to "Ship", order_path(order_item.order_id, :order => {:status => "Shipped" }), method: :patch, class: "button" %> + <% if order_item.order.status == "paid" && order_item.status == nil %> + <%= link_to "Ship", order_item_path(order_item.id, :order_item => {:status => "Shipped" }), method: :patch, class: "button" %> + <%= link_to "Cancel", order_item_path(order_item.id, :order_item => {:status => "Cancelled" }), method: :patch, class: "button" %> <% else %> - <%="Shipped"%> + <%=order_item.status%> <% end %> - <%=link_to "cancel", order_item_path(order_item.id), method: :delete, class: "button"%> - - <%#link_to "Submit order", edit_order_path(@order_id), class: "button"%> - <%=order_item.order.status%> <% @quantity_sum += order_item.quantity %> diff --git a/db/migrate/20171023181341_add_status_to_order_items.rb b/db/migrate/20171023181341_add_status_to_order_items.rb new file mode 100644 index 0000000000..71ac6b4fa0 --- /dev/null +++ b/db/migrate/20171023181341_add_status_to_order_items.rb @@ -0,0 +1,5 @@ +class AddStatusToOrderItems < ActiveRecord::Migration[5.1] + def change + add_column :order_items, :status, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 6c60076189..409cdac1a5 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: 20171021051351) do +ActiveRecord::Schema.define(version: 20171023181341) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -41,6 +41,7 @@ t.integer "order_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "status" end create_table "orders", force: :cascade do |t| From 5392335ae7f3a555ecaf2df56dacb145b05cc57c Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Mon, 23 Oct 2017 11:51:03 -0700 Subject: [PATCH 114/223] Add tests for review validations --- app/models/review.rb | 2 +- test/models/review_test.rb | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/app/models/review.rb b/app/models/review.rb index 552aa441e2..56568bcce5 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -3,5 +3,5 @@ class Review < ApplicationRecord belongs_to :product validates :rating, presence: true - validates :rating, numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 5, message: "Please enter a rating from 1 to 5" } + validates :rating, numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 5, message: "Please enter a rating from 1 to 5" } end diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 8155895708..45fe438c1d 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -12,4 +12,26 @@ end end + describe "validations" do + it "requires rating to be created" do + review = Review.new + review.wont_be :valid? + end + + it "can be created with valid rating" do + review = Review.new(rating: 4, product: products(:one)) + review.must_be :valid? + end + + it "requires rating to be 1-5" do + review = Review.new(rating: 10, product: products(:one)) + review.wont_be :valid? + end + + it "rating has to be an integer" do + review = Review.new(rating: 4.5, product: products(:one)) + review.wont_be :valid? + end + end + end From 4fc4205774e5006d59f13f6cfa195ecf8d9b8f8e Mon Sep 17 00:00:00 2001 From: Eva Sawyer Date: Mon, 23 Oct 2017 11:57:36 -0700 Subject: [PATCH 115/223] added delete order item --- app/controllers/order_items_controller.rb | 25 +++++++++++------------ app/controllers/orders_controller.rb | 6 +++++- app/views/order_items/index.html.erb | 14 ++++++++++++- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb index 26d75f488b..3872e4f1b3 100644 --- a/app/controllers/order_items_controller.rb +++ b/app/controllers/order_items_controller.rb @@ -1,5 +1,5 @@ class OrderItemsController < ApplicationController -skip_before_action :require_login + skip_before_action :require_login def index @@ -14,12 +14,15 @@ def new def create #if there is already an open order, set the order_item order_id to that order. #otherwise make a new order + puts "before" + puts session[:order_id] if session[:order_id] == nil @order = Order.create(status: "pending") session[:order_id] = @order.id end + puts "after:" + puts session[:order_id] @order_item = OrderItem.new(product_id: params[:order_item][:product_id], quantity: params[:order_item][:quantity], order_id: session[:order_id]) - @order_item.save! redirect_to order_items_path # else @@ -51,18 +54,14 @@ def update def destroy - current_merchant = Merchant.find_by(id: session[:logged_in_merchant]) - @order = OrderItem.find_by(id: params[:id]) - if current_merchant == order.product.merchant - @order.destroy - flash[:status] = :success - flash[:result_text] = "Successfully destroyed order item." - redirect_to root_path + @order_item = OrderItem.find(params[:id]) + if @order_item.destroy + flash.now[:status] = :success + flash.now[:message] = "Successfully removed #{@order_item.product.name} from your cart" + render :index else - flash[:status] = :failure - flash[:message] = "You must be the merchant for that item to do that!" - redirect_to root_path - return + flash.now[:status] = :failure + flash.now[:message] = "Problem encountered when attempting to remove #{@order_item.product.name} from your cart" end end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index c3b1e522f0..f566d845a7 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -2,7 +2,6 @@ class OrdersController < ApplicationController skip_before_action :require_login def index - @orders = Order.all end @@ -11,6 +10,8 @@ def new end def create + puts "**********************" + puts "I am in create" if params[:order][:status] == " " flash[:failure] = 'Please enter the required fields.' redirect_to new_order_path @@ -38,6 +39,9 @@ def create end def update + puts "**********************" + puts "I am in update" + binding pry @order = Order.find(params[:id]) @order.customer_name = params[:order][:customer_name] diff --git a/app/views/order_items/index.html.erb b/app/views/order_items/index.html.erb index 66a0ad7a4e..12a072e35f 100644 --- a/app/views/order_items/index.html.erb +++ b/app/views/order_items/index.html.erb @@ -1,5 +1,6 @@

    All Order Items

    +<% if @order_items %> <% @order_items.each do |order_item| %>
      @@ -8,10 +9,21 @@
    • Product ID: <%= order_item.product_id %>
    • <%@order_id = order_item.order_id %>
    • Order ID: <%= order_item.order_id %>
    • +
    • + + <%=link_to "Delete", order_item_path(order_item), method: :delete, data: { confirm: 'Are you certain you want to delete this item?' }%> +
    <% end %> - <%=link_to "Submit order", edit_order_path(@order_id), class: "button"%> +<% else %> +

    +shopping cart is empty +

    + +<%end%> + + From 49dd9a2b79a810d067fc4de911532ce4fd418fb4 Mon Sep 17 00:00:00 2001 From: Eva Sawyer Date: Mon, 23 Oct 2017 12:25:04 -0700 Subject: [PATCH 116/223] fixed bug with placing order --- app/controllers/orders_controller.rb | 4 +--- app/views/orders/edit.html.erb | 5 +++-- app/views/orders/show.html.erb | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index e64da4a2cd..9f0b82c37f 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -50,9 +50,6 @@ def create end def update - puts "**********************" - puts "I am in update" - binding pry @order = Order.find(params[:id]) @order.customer_name = params[:order][:customer_name] @@ -64,6 +61,7 @@ def update @order.zip_code = params[:order][:zip_code] # result = @order.save + puts "**********************" puts "session before #{session[:order_id]}" if @order.save! diff --git a/app/views/orders/edit.html.erb b/app/views/orders/edit.html.erb index 071fe6fac0..b8add0f80d 100644 --- a/app/views/orders/edit.html.erb +++ b/app/views/orders/edit.html.erb @@ -1,6 +1,7 @@

    Please enter billing and shipping information

    -
    +
    + <%= form_for @order do |f| %> <%= f.label :customer_name %> <%= f.text_field :customer_name %> @@ -26,4 +27,4 @@ <%= f.submit "Checkout"%> <% end %> - +
    diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb index 957b68f6c8..6ede693882 100644 --- a/app/views/orders/show.html.erb +++ b/app/views/orders/show.html.erb @@ -11,5 +11,4 @@ <%#= link_to 'All Orders', orders_path %> -<%= link_to 'Edit Order', edit_order_path %> -<%= link_to 'Cancel Order', cancel_order_path %> +<%#= link_to 'Edit Order', edit_order_path %> From 470805a67603fd33006595a78a2a4d810f998fb8 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Mon, 23 Oct 2017 13:07:57 -0700 Subject: [PATCH 117/223] Add some tests for reviews controller --- app/controllers/reviews_controller.rb | 21 ++-- app/views/products/show.html.erb | 23 +++-- app/views/reviews/new.html.erb | 16 +++ config/routes.rb | 4 +- test/controllers/reviews_controller_test.rb | 105 ++------------------ 5 files changed, 48 insertions(+), 121 deletions(-) create mode 100644 app/views/reviews/new.html.erb diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index 41b545af5a..cc6d8a243b 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -1,29 +1,20 @@ class ReviewsController < ApplicationController - def index - @reviews = Review.all() - end - - def show - @review = Review.find(params[:id]) - end - def edit - @review = Review.find(params[:id]) - end + skip_before_action :require_login def new - @review = Review.new() + @review = Review.new(product_id: params[:id]) end def create @review = Review.new(review_params) if @review.save flash[:status] = :success - flash[:result_text] = "Successfully created #{@review.id}" - redirect_to review_path(@review) + flash[:message] = "Successfully created new review" + redirect_to product_path(@review.product) else flash[:status] = :failure - flash[:result_text] = "Could not create review ID number #{@review.id}" + flash[:message] = "Could not create new review" flash[:messages] = @review.errors.messages render :new, status: :bad_request end @@ -32,6 +23,6 @@ def create private def review_params - params.require(:product_id).permit(:text) + params.require(:review).permit(:rating, :text, :product_id) end end diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 5ab991bdde..e3141ee28c 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -27,21 +27,24 @@ <%= f.select :quantity, (1..@product.stock).to_a %> <%= f.submit "Add to Cart", class: "cart button"%> <% end %> + - - - - - - <%# @product.reviews.each do |review| %> - - - <%# end %> - +
    + + <%= link_to "Write a Review", new_product_review_path, class: "cart button" %> +

    Customer reviews

    +

    rating in stars, 10 customer reviews

    +
    +

    list all review

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

    in stars

    +

    bla bla bla<%= review.text %>

    + <% end %> +
    diff --git a/app/views/reviews/new.html.erb b/app/views/reviews/new.html.erb new file mode 100644 index 0000000000..ce110168d4 --- /dev/null +++ b/app/views/reviews/new.html.erb @@ -0,0 +1,16 @@ +
    +

    Create new review

    + + <%= form_for @review do |f| %> + + <%= f.label :rating %> + <%= f.select :rating, (1..5).to_a %> + + <%= f.hidden_field :product_id %> + + <%= f.label :text, "Comment" %> + <%= f.text_area :text %> + + <%= f.submit %> + <%end%> +
    diff --git a/config/routes.rb b/config/routes.rb index e9fc556f3f..be7ad82a57 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,7 +6,7 @@ resources :merchants resources :orders - resources :reviews + resources :reviews, except: [:new] root 'main#index' resources :order_items, only: [:create, :index, :destroy, :update] @@ -33,6 +33,8 @@ end end + get '/products/:id/reviews/new', to: 'reviews#new', as: 'new_product_review' + get '/products/merchant/:id', to: 'products#index_by_merchant', as: 'products_merchant' get '/products/category/:id', to: 'products#index_by_category', as: 'products_category' diff --git a/test/controllers/reviews_controller_test.rb b/test/controllers/reviews_controller_test.rb index 6bda41dbef..b82a7c8897 100644 --- a/test/controllers/reviews_controller_test.rb +++ b/test/controllers/reviews_controller_test.rb @@ -3,70 +3,29 @@ describe ReviewsController do describe "new" do it "works" do - get new_review_path - must_respond_with :success - end - end - - describe "show" do - it "succeeds for an valid review ID" do - #when we get seed data we can clean this up - get review_path(reviews(:one).product_id) - must_respond_with :success - end - - it "renders 404 not_found for a bogus review ID" do - get review_path(9999) - must_respond_with :not_found - end - end - - describe "edit" do - it "succeeds for an extant review ID" do - #when we get seed data we can clean this up - review = Product.new(product_id: reviews(:one).id, text: 'new review text') - - get edit_review_path(review.id) - must_respond_with :success - end - - it "renders 404 not_found for a bogus review ID" do - #when we get seed data we can clean this up - - get edit_review_path(99999999) - must_respond_with :not_found - end - end - - describe "index" do - it "succeeds when there are reviews" do - #when we get seed data we can clean this up - get reviews_path - must_respond_with :success - end - - it "succeeds when there are no reviews" do - Review.destroy_all - get reviews_path + product = products(:one) + get new_product_review_path(product) must_respond_with :success end end describe "create" do it "creates a review with valid data" do - review = Review.create review_data = { review: { - product_id: 93892, - text: 'review text' + product: products(:one), + rating: 2, + text: "review text" } } + Review.new(review_data[:review]).must_be :valid? start_count = Review.count post reviews_path, params: review_data - must_redirect_to review_path(Review.last) - Review.count.must_equal start_count + 1 + # must_respond_with :redirect + # must_redirect_to product_path(products(:one)) + # Review.count.must_equal start_count + 1 end it "renders bad_request and does not update the DB for bogus data" do @@ -79,53 +38,9 @@ post reviews_path, params: review_data - must_redirect_to review_path(Review.last) + must_respond_with :bad_request Review.count.must_equal start_count end end - - describe "update" do - it "succeeds for valid data and an valid review ID" do - review = Review.create - - - review = Review.first - review_data = { - review: { - product_id: 1, - text: 'new review text' - } - } - start_count = Review.count - - patch review_path(review), params: review_data - - must_redirect_to product_path(Review.last) - Review.count.must_equal start_count - end - - it "renders bad_request for bogus data" do - review = Review.first - review_data = { - review: { - product_id: nil - } - } - start_count = Review.count - - patch review_path(review), params: review_data - - must_redirect_to product_path(Review.last) - Review.count.must_equal start_count - end - - it "renders 404 not_found for a bogus review ID" do - - - - get review_path(999902309123) - must_respond_with :not_found - end - end end From 4dd05399d98d5e00c07a4af1f625c301660087bb Mon Sep 17 00:00:00 2001 From: Eva Sawyer Date: Mon, 23 Oct 2017 13:29:12 -0700 Subject: [PATCH 118/223] met min requirements for order confirmation page --- app/controllers/orders_controller.rb | 9 +-- app/models/order_item.rb | 6 ++ app/views/orders/_orderitem_summary.html.erb | 32 +++++++++++ app/views/orders/edit.html.erb | 2 - app/views/orders/show.html.erb | 58 ++++++++++++++++---- 5 files changed, 88 insertions(+), 19 deletions(-) create mode 100644 app/views/orders/_orderitem_summary.html.erb diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index e64da4a2cd..34514d2489 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -50,9 +50,7 @@ def create end def update - puts "**********************" - puts "I am in update" - binding pry + @order = Order.find(params[:id]) @order.customer_name = params[:order][:customer_name] @@ -63,9 +61,6 @@ def update @order.cc_ccv = params[:order][:cc_ccv] @order.zip_code = params[:order][:zip_code] - # result = @order.save - puts "session before #{session[:order_id]}" - if @order.save! flash[:notification] = 'Order was successfully updated' @order.status = "paid" @@ -74,7 +69,6 @@ def update else flash[:failure] = 'Order was not updated' end - puts "session after #{session[:order_id]}" redirect_to order_path(@order.id) end @@ -84,6 +78,7 @@ def edit def show @order = Order.find(params[:id]) + @order_items = OrderItem.where(order_id: params[:id]) end # def cancel diff --git a/app/models/order_item.rb b/app/models/order_item.rb index bc16957ca1..d1e4a8e9ef 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -1,4 +1,10 @@ class OrderItem < ApplicationRecord belongs_to :order belongs_to :product + + # Make a method for this and put it in _orderitem_summary + # def total_cost(cost) + # cost = @quantity * cost + # return result + # end end diff --git a/app/views/orders/_orderitem_summary.html.erb b/app/views/orders/_orderitem_summary.html.erb new file mode 100644 index 0000000000..9bd0745090 --- /dev/null +++ b/app/views/orders/_orderitem_summary.html.erb @@ -0,0 +1,32 @@ +
    +

    Order Summary

    +<%@order_items.each do |order_item|%> +
    +<%= link_to (image_tag(order_item.product.image_url)), product_path(order_item.product) %> +

    +

      +
    • + <%=link_to order_item.product.name, product_path(order_item.product) %> +
    • +
    • Cost: + <%= order_item.quantity * order_item.product.price %> +
    • +
    • + Number ordered: <%=order_item.quantity %> +
    • + +
    +

    +

    + <%if order_item.status == "Shipped"%> + Item is on it's way! + <% elsif order_item.status == "Cancelled"%> + The merchant, <%=order_item.product.merchant.username%>, has canceled this order. + <%else %> + The order is being processed. + <%end%> +

    +
    +<%end%> + +
    diff --git a/app/views/orders/edit.html.erb b/app/views/orders/edit.html.erb index 071fe6fac0..0100786648 100644 --- a/app/views/orders/edit.html.erb +++ b/app/views/orders/edit.html.erb @@ -1,6 +1,5 @@

    Please enter billing and shipping information

    -
    <%= form_for @order do |f| %> <%= f.label :customer_name %> <%= f.text_field :customer_name %> @@ -26,4 +25,3 @@ <%= f.submit "Checkout"%> <% end %> -
    diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb index 957b68f6c8..e0dd34e684 100644 --- a/app/views/orders/show.html.erb +++ b/app/views/orders/show.html.erb @@ -1,15 +1,53 @@ -

    Confirmation page for Order#: <%= @order.id %>

    +

    Confirmation page for Order <%= @order.id %>

    +<% total = 0%> +<% @order_items.each do |order_item|%> +<% total = order_item.quantity * order_item.product.price %> +<% end %> + + +

    Billing information

      -
    • Status: <%= @order.status %>
    • -
    • Customer Name: <%= @order.customer_name %>
    • -
    • Customer Email Address: <%= @order.customer_email %>
    • -
    • Credit Card Number: <%= @order.cc_number %>
    • -
    • Credit Card Expiration Date: <%= @order.cc_expiration %>
    • -
    • Credit Card CCV: <%= @order.cc_ccv %>
    • -
    • Billing Zipcode: <%= @order.zip_code %>
    • +
    • + Customer Name: <%= @order.customer_name %> +
    • +
    • + Customer Email Address: <%= @order.customer_email %>
    • +
    • + Credit Card Number: <%= @order.cc_number %> +
    • +
    • + Credit Card Expiration Date: <%= @order.cc_expiration %> +
    • +
    • + Credit Card CCV: <%= @order.cc_ccv %> +
    • +
    • + Billing Zipcode: <%= @order.zip_code %> +
    • +
    • + Date and Time Order Placed: <%=@order.created_at %> +
    • +
    • + Order Status: <%= @order.status%> +
    • +
    • + Total Cost: <%=total %> +
    • +
    + + + +<%= render partial: "orderitem_summary" %> + + + + + + + <%#= link_to 'All Orders', orders_path %> -<%= link_to 'Edit Order', edit_order_path %> -<%= link_to 'Cancel Order', cancel_order_path %> +<%#= link_to 'Edit Order', edit_order_path %> +<%#= link_to 'Cancel Order', cancel_order_path %> From b44a1eb36e8e2254f5a963045f4fdb57265a83b5 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Mon, 23 Oct 2017 13:45:49 -0700 Subject: [PATCH 119/223] Add stars --- app/assets/stylesheets/application.css | 30 ++++++++++++++++++++++++++ app/helpers/application_helper.rb | 16 ++++++++++++++ app/views/layouts/_stars.html.erb | 5 +++++ app/views/products/show.html.erb | 19 ++++++++-------- 4 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 app/views/layouts/_stars.html.erb diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index a837eb3288..26d9684bf2 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -242,3 +242,33 @@ margin: .5rem .1rem; height: 40.469px; } + +/*reviews*/ +/*stars*/ +.zero-stars, .zero-stars a{ + color: lightgrey; +} + +.one-star, .one-star a{ + color: #cc0000; +} + +.two-stars, .two-stars a{ + color: #ff8533; +} + +.three-stars, .three-stars a{ + color: #ffcc00; +} + +.four-stars, .four-stars a{ + color: #99db70; +} + +.five-stars, .five-stars a{ + color: #33AC33; +} + +.reviews section { + border-bottom: 1px solid #cccccc; +} diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de6be7945c..396689e00f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,2 +1,18 @@ module ApplicationHelper + def set_class(rating) + case rating + when 0 + "zero-stars" + when 1 + "one-star" + when 2 + "two-stars" + when 3 + "three-stars" + when 4 + "four-stars" + when 5 + "five-stars" + end + end end diff --git a/app/views/layouts/_stars.html.erb b/app/views/layouts/_stars.html.erb new file mode 100644 index 0000000000..83b8ba4247 --- /dev/null +++ b/app/views/layouts/_stars.html.erb @@ -0,0 +1,5 @@ + + <%= '★' * rating %><%= '☆' * (5 - rating) %> + diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index e3141ee28c..766be1ecec 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -12,7 +12,7 @@
    • <%= link_to @product.merchant.username, products_merchant_path(@product.merchant) %>
    • <%= @product.name %>

    • -
    • rating in stars, 10 customer reviews
    • +
    • rating in stars, <%= @product.reviews.count %> customer reviews
    • Price: <%= @product.price %>
    • <% if @product.stock != nil %>
    • In Stock (only <%= @product.stock %> left)
    • @@ -27,23 +27,22 @@ <%= f.select :quantity, (1..@product.stock).to_a %> <%= f.submit "Add to Cart", class: "cart button"%> <% end %> -
    - -
    - <%= link_to "Write a Review", new_product_review_path, class: "cart button" %>

    Customer reviews

    -

    rating in stars, 10 customer reviews

    -
    -

    list all review

    +

    (rating in stars), <%= @product.reviews.count %> customer reviews

    + <%= link_to "Write a Review", new_product_review_path, class: "cart button" %> +
    <% @product.reviews.each do |review| %> - <%= review.rating %>

    in stars

    -

    bla bla bla<%= review.text %>

    +
    + <%= render partial: "layouts/stars", locals: { rating: review.rating } %> +

    left on <%= review.created_at.localtime.strftime("%d %b %Y") %>

    +

    <%= review.text %>

    +
    <% end %>
    From 3017899dc1aca473c07a3432a5421f2d1e4e487f Mon Sep 17 00:00:00 2001 From: Rebecca Bergena Date: Mon, 23 Oct 2017 13:47:28 -0700 Subject: [PATCH 120/223] remove stray heads --- app/controllers/orders_controller.rb | 3 --- app/views/orders/edit.html.erb | 4 ---- 2 files changed, 7 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 79bee7a1a1..34514d2489 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -50,10 +50,7 @@ def create end def update -<<<<<<< HEAD -======= ->>>>>>> ES1019 @order = Order.find(params[:id]) @order.customer_name = params[:order][:customer_name] diff --git a/app/views/orders/edit.html.erb b/app/views/orders/edit.html.erb index b410e16d17..0100786648 100644 --- a/app/views/orders/edit.html.erb +++ b/app/views/orders/edit.html.erb @@ -25,7 +25,3 @@ <%= f.submit "Checkout"%> <% end %> -<<<<<<< HEAD -======= -
    ->>>>>>> ES1019 From 89a9b00450db8351f2263e99539da7739344578b Mon Sep 17 00:00:00 2001 From: VirtualLindsey Date: Mon, 23 Oct 2017 13:53:42 -0700 Subject: [PATCH 121/223] adding logic for order items --- app/controllers/order_items_controller.rb | 26 +++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb index 6ca183615b..0f3138b3e3 100644 --- a/app/controllers/order_items_controller.rb +++ b/app/controllers/order_items_controller.rb @@ -20,11 +20,18 @@ def create @order = Order.create(status: "pending") session[:order_id] = @order.id end - puts "after:" + puts "after:"`` puts session[:order_id] - @order_item = OrderItem.new(product_id: params[:order_item][:product_id], quantity: params[:order_item][:quantity], order_id: session[:order_id]) - @order_item.save! - redirect_to order_items_path + @product = Product.find(params[:order_item][:product_id]) + if params[:order_item][:quantity] > @product.quantity + flash[:status] = :failure + flash[:result_text] = "There is not enough stock. Order a smaller amount" + redirect_to order_items_path + else + @order_item = OrderItem.new(product_id: params[:order_item][:product_id], quantity: params[:order_item][:quantity], order_id: session[:order_id]) + @order_item.save! + redirect_to order_items_path + end # else # # # # render :new @@ -42,6 +49,13 @@ def update # else # # render :edit # end + @product = Product.find(@order_item.product_id) + + if params[:order_item][:quantity] > @product.quantity + flash[:status] = :failure + flash[:result_text] = "There is not enough stock. Order a smaller amount" + redirect_to order_items_path + end @order_item.update_attributes(order_item_params) @@ -59,6 +73,10 @@ def update def destroy @order_item = OrderItem.find(params[:id]) + @product = Product.find(@order_item.product_id) + @product.quantity += @order_item.quantity + @product.save + if @order_item.destroy flash.now[:status] = :success flash.now[:message] = "Successfully removed #{@order_item.product.name} from your cart" From 2ea0edb09cf7d631249049d5b24df6bcbf252cce Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Mon, 23 Oct 2017 14:12:56 -0700 Subject: [PATCH 122/223] Add method for average rating --- app/models/product.rb | 4 ++++ app/models/review.rb | 4 ++++ app/views/products/show.html.erb | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/models/product.rb b/app/models/product.rb index 7e9ee3e7bd..c54e14a725 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -18,4 +18,8 @@ def self.new_products(number) return Product.all.order(:created_at).reverse.first(5) end + def average_rating + return reviews.average(:rating) + end + end diff --git a/app/models/review.rb b/app/models/review.rb index 56568bcce5..27df6a8d57 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -4,4 +4,8 @@ class Review < ApplicationRecord validates :rating, presence: true validates :rating, numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 5, message: "Please enter a rating from 1 to 5" } + + # def average_rating(product) + # return product.reviews.average(:rating) + # end end diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 766be1ecec..d58f11e545 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -12,7 +12,7 @@
    diff --git a/config/routes.rb b/config/routes.rb index 4a9d1d7171..ecf7a8d9b2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -33,6 +33,10 @@ resources :products, only: [:index] end + resources :merchants do + resources :products, only: [:index] + end + get '/auth/:provider/callback', to: 'merchants#login', as: 'auth_callback' get 'logout', to: 'merchants#logout', as: 'logout' From 3b17d53d44fcedd73036344a3f58c1dd5de421cf Mon Sep 17 00:00:00 2001 From: Eva Sawyer Date: Fri, 20 Oct 2017 11:14:33 -0700 Subject: [PATCH 067/223] Checked MerchantController tests --- app/views/merchants/index.html.erb | 12 ++++++++++-- test/controllers/merchants_controller_test.rb | 4 +--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/views/merchants/index.html.erb b/app/views/merchants/index.html.erb index b551da7965..be689655de 100644 --- a/app/views/merchants/index.html.erb +++ b/app/views/merchants/index.html.erb @@ -1,8 +1,16 @@

    Shop by merchant

    + + +<%unless @merchants.count == 0 %>
      <% @merchants.each do |merchant| %> -
    • +
    • <%=link_to merchant.username, merchant_path(merchant) %> -
    • + <% end %>
        +<%else%> +

        + No merchants signed up yet! +

        +<%end%> diff --git a/test/controllers/merchants_controller_test.rb b/test/controllers/merchants_controller_test.rb index 5ae4bf0f51..f3dae347c2 100644 --- a/test/controllers/merchants_controller_test.rb +++ b/test/controllers/merchants_controller_test.rb @@ -27,7 +27,7 @@ must_respond_with :success end - it "succeeds when there are no products" do + it "succeeds when there are no merchantss" do Product.destroy_all get merchants_path must_respond_with :success @@ -35,8 +35,6 @@ end - - describe "login" do it "logs in an existing merchant and redirects to the root path" do start_count = Merchant.count From 54a7e7e0dce666bcfbf793d30a67b6a36c2c3514 Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Fri, 20 Oct 2017 11:27:56 -0700 Subject: [PATCH 068/223] Add routes for products by merchant --- app/controllers/merchants_controller.rb | 2 +- app/controllers/products_controller.rb | 3 +++ app/models/merchant.rb | 2 +- app/views/merchants/_nav_aside.html.erb | 2 +- app/views/merchants/show.html.erb | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index a277cedf0f..7e72b864fa 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -11,7 +11,7 @@ def index def show @merchant = Merchant.find(params[:id]) - @products = @merchant.product + @products = @merchant.products end def login diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 330151a125..ddf6f6d4f3 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -48,6 +48,9 @@ def index if params[:category_id] category = Category.find_by(id: params[:category_id]) @products = category.products + elsif params[:merchant_id] + merchant = Merchant.find_by(id: params[:merchant_id]) + @products = merchant.products else @products = Product.all end diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 11fe3dc406..1dd40d6c2c 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -1,5 +1,5 @@ class Merchant < ApplicationRecord - has_many :product + has_many :products def self.from_auth_hash(provider, auth_hash) merchant = new diff --git a/app/views/merchants/_nav_aside.html.erb b/app/views/merchants/_nav_aside.html.erb index 4c46524120..975eb54438 100644 --- a/app/views/merchants/_nav_aside.html.erb +++ b/app/views/merchants/_nav_aside.html.erb @@ -3,7 +3,7 @@
      • <%= @merchant.username %>
      • <%= @merchant.email %>
      • <%= link_to "Dashboard", merchant_path(@merchant.id) %>
      • -
      • <%= link_to "Manage Products", products_path(@merchant.id) %>
      • +
      • <%= link_to "Manage Products", merchant_products_path(@merchant.id) %>
      • <%= link_to "Manage Orders", merchant_path(@merchant.id) %>
      diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index d62b5c5c88..91cf01c807 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -9,7 +9,7 @@

      Products sold by <%=@merchant.username%>

        - <% @merchant.product.each do |product|%> + <% @merchant.products.each do |product|%>
      • From 4af50877808fafc6b58bb956c545d3b07919de16 Mon Sep 17 00:00:00 2001 From: Eva Sawyer Date: Fri, 20 Oct 2017 11:46:51 -0700 Subject: [PATCH 069/223] first pass at order_itemController tests. Need clarification on role of OrderItems to proceed --- app/controllers/order_items_controller.rb | 15 +++++++++------ test/controllers/order_items_controller_test.rb | 9 +++++---- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb index c7b9f5fe31..240c8b5885 100644 --- a/app/controllers/order_items_controller.rb +++ b/app/controllers/order_items_controller.rb @@ -29,14 +29,17 @@ def update else # render :edit end - end - @work.update_attributes(work_params) - if save_and_flash(@work, "update") - redirect_to work_path(@work.id) - else - render :edit, status: :bad_request + @order_item.update_attributes(order_item_params) + + if save_and_flash(@order_item, "update") + redirect_to order_item_path(@order_item.id) + else + render :edit, status: :bad_request + end end + + def destroy current_merchant = Merchant.find_by(id: session[:logged_in_merchant]) @order = OrderItem.find_by(id: params[:id]) diff --git a/test/controllers/order_items_controller_test.rb b/test/controllers/order_items_controller_test.rb index 81e9e3fb9f..be600e686e 100644 --- a/test/controllers/order_items_controller_test.rb +++ b/test/controllers/order_items_controller_test.rb @@ -17,24 +17,25 @@ must_respond_with :success end end + describe "destroy" do it "succeeds for an extant order item ID" do order_item_id = OrderItem.first.id - delete work_path(order_item_id) + delete order_item_path(order_item_id) must_redirect_to root_path OrderItem.find_by(id: order_item_id).must_be_nil end - # it "renders 404 not_found and does not update the DB for a bogus work ID" do + # it "renders 404 not_found and does not update the DB for a bogus order_item ID" do # start_count = OrderItem.count # # bogus_order_item_id = OrderItem.last.id + 1 - # delete work_path(bogus_order_item_id) + # delete order_item_path(bogus_order_item_id) # must_respond_with :not_found # - # Work.count.must_equal start_count + # order_item.count.must_equal start_count # end end From 752bba822d1cec79623e9478f9bc75a348659a15 Mon Sep 17 00:00:00 2001 From: VirtualLindsey Date: Fri, 20 Oct 2017 12:06:22 -0700 Subject: [PATCH 070/223] Reviews tests --- Gemfile.lock | 7 ++ config/routes.rb | 4 + test/controllers/reviews_controller_test.rb | 130 +++++++++++++++++++- test/fixtures/reviews.yml | 4 +- 4 files changed, 140 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 86c3d1f5ca..f168579858 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -77,6 +77,7 @@ GEM faraday (0.12.2) multipart-post (>= 1.2, < 3) ffi (1.9.18) + ffi (1.9.18-x86-mingw32) foundation-rails (6.3.1.0) railties (>= 3.1.0) sass (>= 3.3.0, < 3.5) @@ -123,6 +124,8 @@ GEM nio4r (2.1.0) nokogiri (1.8.1) mini_portile2 (~> 2.3.0) + nokogiri (1.8.1-x86-mingw32) + mini_portile2 (~> 2.3.0) oauth2 (1.4.0) faraday (>= 0.8, < 0.13) jwt (~> 1.0) @@ -139,6 +142,7 @@ GEM oauth2 (~> 1.0) omniauth (~> 1.2) pg (0.21.0) + pg (0.21.0-x86-mingw32) pry (0.11.1) coderay (~> 1.1.0) method_source (~> 0.9.0) @@ -213,6 +217,8 @@ GEM turbolinks-source (5.0.3) tzinfo (1.2.3) thread_safe (~> 0.1) + tzinfo-data (1.2017.2) + tzinfo (>= 1.0.0) uglifier (3.2.0) execjs (>= 0.3.0, < 3) web-console (3.5.1) @@ -228,6 +234,7 @@ GEM PLATFORMS ruby + x86-mingw32 DEPENDENCIES better_errors diff --git a/config/routes.rb b/config/routes.rb index 031b91259a..456d134ed8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -18,6 +18,10 @@ get '/reviews/:id', to: 'review#show', as: 'review' get '/reviews/:id/edit', to: 'reviews#edit', as: 'edit_review' + get '/auth/:provider' + get '/auth/:provider/callback' + + resources :orders resources :reviews root 'main#index' diff --git a/test/controllers/reviews_controller_test.rb b/test/controllers/reviews_controller_test.rb index 386065239a..6bda41dbef 100644 --- a/test/controllers/reviews_controller_test.rb +++ b/test/controllers/reviews_controller_test.rb @@ -1,7 +1,131 @@ require "test_helper" describe ReviewsController do - # it "must be a real test" do - # flunk "Need real tests" - # end + describe "new" do + it "works" do + get new_review_path + must_respond_with :success + end + end + + describe "show" do + it "succeeds for an valid review ID" do + #when we get seed data we can clean this up + get review_path(reviews(:one).product_id) + must_respond_with :success + end + + it "renders 404 not_found for a bogus review ID" do + get review_path(9999) + must_respond_with :not_found + end + end + + describe "edit" do + it "succeeds for an extant review ID" do + #when we get seed data we can clean this up + review = Product.new(product_id: reviews(:one).id, text: 'new review text') + + get edit_review_path(review.id) + must_respond_with :success + end + + it "renders 404 not_found for a bogus review ID" do + #when we get seed data we can clean this up + + get edit_review_path(99999999) + must_respond_with :not_found + end + end + + describe "index" do + it "succeeds when there are reviews" do + #when we get seed data we can clean this up + get reviews_path + must_respond_with :success + end + + it "succeeds when there are no reviews" do + Review.destroy_all + get reviews_path + must_respond_with :success + end + end + + describe "create" do + it "creates a review with valid data" do + review = Review.create + review_data = { + review: { + product_id: 93892, + text: 'review text' + } + } + start_count = Review.count + + post reviews_path, params: review_data + + must_redirect_to review_path(Review.last) + Review.count.must_equal start_count + 1 + end + + it "renders bad_request and does not update the DB for bogus data" do + review_data = { + review: { + product_id: nil + } + } + start_count = Review.count + + post reviews_path, params: review_data + + must_redirect_to review_path(Review.last) + Review.count.must_equal start_count + end + end + + + describe "update" do + it "succeeds for valid data and an valid review ID" do + review = Review.create + + + review = Review.first + review_data = { + review: { + product_id: 1, + text: 'new review text' + } + } + start_count = Review.count + + patch review_path(review), params: review_data + + must_redirect_to product_path(Review.last) + Review.count.must_equal start_count + end + + it "renders bad_request for bogus data" do + review = Review.first + review_data = { + review: { + product_id: nil + } + } + start_count = Review.count + + patch review_path(review), params: review_data + + must_redirect_to product_path(Review.last) + Review.count.must_equal start_count + end + + it "renders 404 not_found for a bogus review ID" do + + + + get review_path(999902309123) + must_respond_with :not_found + end + end end diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml index 49520a6432..662f1288bb 100644 --- a/test/fixtures/reviews.yml +++ b/test/fixtures/reviews.yml @@ -2,8 +2,8 @@ one: product_id: 1 - text: MyString + text: 'review text 1' two: product_id: 1 - text: MyString + text: 'review text 2' From 934d482ac0e12ef1c1615b011ec57e6019a84d1f Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Fri, 20 Oct 2017 12:23:15 -0700 Subject: [PATCH 071/223] Add custom view for merchant products --- app/assets/stylesheets/application.css | 5 ++ app/controllers/products_controller.rb | 5 +- app/views/merchants/_nav_aside.html.erb | 4 +- app/views/merchants/show.html.erb | 23 ++------- app/views/products/merchant_products.html.erb | 48 +++++++++++++++++++ 5 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 app/views/products/merchant_products.html.erb diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 8180c6b31c..2844687893 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -144,3 +144,8 @@ .merchant-show li { margin: .3rem; } + +.merchant-show .button { + background-color: #ffd24d; + font-weight: bold; +} diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index ddf6f6d4f3..e612449511 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -49,8 +49,9 @@ def index category = Category.find_by(id: params[:category_id]) @products = category.products elsif params[:merchant_id] - merchant = Merchant.find_by(id: params[:merchant_id]) - @products = merchant.products + @merchant = Merchant.find_by(id: params[:merchant_id]) + @products = @merchant.products + render :merchant_products else @products = Product.all end diff --git a/app/views/merchants/_nav_aside.html.erb b/app/views/merchants/_nav_aside.html.erb index 975eb54438..394e1542fa 100644 --- a/app/views/merchants/_nav_aside.html.erb +++ b/app/views/merchants/_nav_aside.html.erb @@ -1,4 +1,5 @@ -
        +
        + <% if @merchant %>
        • <%= @merchant.username %>
        • <%= @merchant.email %>
        • @@ -6,4 +7,5 @@
        • <%= link_to "Manage Products", merchant_products_path(@merchant.id) %>
        • <%= link_to "Manage Orders", merchant_path(@merchant.id) %>
        + <% end %>
        diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb index 91cf01c807..41cb7d810d 100644 --- a/app/views/merchants/show.html.erb +++ b/app/views/merchants/show.html.erb @@ -1,24 +1,7 @@
        <%= render partial: "nav_aside" %> -
        -

        Revenue Summory

        -

        +
        +

        Revenue Summary

        +

        bla bla bla

        - - - -

        Products sold by <%=@merchant.username%>

        -
          - <% @merchant.products.each do |product|%> -
        • - - -
          - <%= link_to product.name, product_path(product) %> -
          -
          -
        • - <% end %> -
        -
        diff --git a/app/views/products/merchant_products.html.erb b/app/views/products/merchant_products.html.erb new file mode 100644 index 0000000000..d49aaee185 --- /dev/null +++ b/app/views/products/merchant_products.html.erb @@ -0,0 +1,48 @@ +
        + <%= render partial: "merchants/nav_aside" %> +
        + <%= link_to "New Product", new_product_path, class: "button" %> + <%= link_to "New Category", new_category_path, class: "button" %> +

        Products

        + + + + + + + + + + + + <% @merchant.products.each do |product| %> + + + + + + + + + <% end %> + +
        ImageNameQuantityPriceManage
        <%= image_tag product.image_url %><%= product.name %><%= product.quantity %><%= link_to "Edit", edit_product_path(product.id), class: "button" %><%= link_to "Retire", product_path(product.id), class: "button" %><%= link_to "Add quantity", product_path(product.id), class: "button" %>
        +
        + + + + + + <%# @merchant.products.each do |product|%> + + + + + <%#= link_to product.name, product_path(product) %> + + + + <%# end %> + + +
        From c2b4986248f2e87c26b3e7d62aaacb6c0de7f95c Mon Sep 17 00:00:00 2001 From: Iuliia Chikulaeva Date: Fri, 20 Oct 2017 13:34:41 -0700 Subject: [PATCH 072/223] Fix creating a new product and view merchant products --- app/assets/stylesheets/application.css | 8 ++++ app/controllers/products_controller.rb | 10 +++-- app/views/layouts/application.html.erb | 2 +- app/views/products/merchant_products.html.erb | 33 +++++------------ app/views/products/new.html.erb | 37 ++++++++----------- db/seeds.rb | 4 +- 6 files changed, 43 insertions(+), 51 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 2844687893..fd67585d3a 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -149,3 +149,11 @@ background-color: #ffd24d; font-weight: bold; } + +.merchant-show table th, .merchant-show table td:nth-last-child(-n+3) { + text-align: center; +} + +.merchant-show table .button { + margin: 0; +} diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index e612449511..6b500370da 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -6,12 +6,14 @@ def new def create @product = Product.new(product_params) - puts @product.name - puts @product.valid? + @product[:merchant_id] = session[:merchant_id] + @product[:retired] = false + puts "products merchant = #{@product[:merchant_id]}" + puts "retired: #{@product[:retired]}" if @product.save flash[:status] = :success flash[:result_text] = "Successfully created #{@product.name}, ID number #{@product.id}" - redirect_to product_path(@product) + redirect_to merchant_products_path(session[:merchant_id]) else flash[:status] = :failure flash[:result_text] = "Could not create #{@product.name}, ID number #{@product.id}" @@ -60,7 +62,7 @@ def index private def product_params - params.require(:product).permit(:price, :stock, :retired, :description, :image_url, :merchant_id) + params.require(:product).permit(:name, :price, :stock, :description, :image_url) end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 13d074959d..b110ca8536 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -25,7 +25,7 @@ <%= link_to "all products", products_path, class: "button" %> <%= link_to "shop by merchant", merchants_path, class: "button" %> <%= link_to "shop by category", root_path, class: "button" %> - <% if session[:merchant_id] %> + <% if session[:merchant_id] && Merchant.find_by(id: session[:merchant_id]) %>
        <%= link_to "logged in as #{Merchant.find(session[:merchant_id]).username}",merchant_path(session[:merchant_id]),class:"button" %> <%= link_to "log out", logout_path, class: "button" %>
        diff --git a/app/views/products/merchant_products.html.erb b/app/views/products/merchant_products.html.erb index d49aaee185..95fe9620c3 100644 --- a/app/views/products/merchant_products.html.erb +++ b/app/views/products/merchant_products.html.erb @@ -7,10 +7,10 @@ - - - - + + + + @@ -19,30 +19,15 @@ - - - - + + + <% end %>
        ImageNameQuantityPriceImageNameQuantityPrice Manage
        <%= image_tag product.image_url %> <%= product.name %><%= product.quantity %><%= link_to "Edit", edit_product_path(product.id), class: "button" %><%= link_to "Retire", product_path(product.id), class: "button" %><%= link_to "Add quantity", product_path(product.id), class: "button" %><%= product.stock %><%= product.price %><%= link_to "Edit", edit_product_path(product.id), class: "button" %> + <%= link_to "Retire", product_path(product.id), class: "button" %> + <%= link_to "Add quantity", product_path(product.id), class: "button" %>
        - - - - - <%# @merchant.products.each do |product|%> - - - - - <%#= link_to product.name, product_path(product) %> - - - - <%# end %> - -