From 44af9cfc3c6962d353d510b151d11312b810b5ee Mon Sep 17 00:00:00 2001 From: Volodya Sveredyuk Date: Wed, 12 May 2021 18:25:48 +0300 Subject: [PATCH 1/4] Shop Engine Init :tada: --- Gemfile | 1 + Gemfile.lock | 7 + app/helpers/admin/navigation_helper.rb | 4 + app/views/layouts/admin/_navigation.slim | 2 +- app/views/layouts/app/_header.slim | 2 + components/shop/.gitignore | 10 ++ components/shop/Gemfile | 18 +++ components/shop/Gemfile.lock | 130 ++++++++++++++++++ components/shop/MIT-LICENSE | 20 +++ components/shop/README.md | 28 ++++ components/shop/Rakefile | 34 +++++ .../shop/app/assets/config/shop_manifest.js | 2 + components/shop/app/assets/images/shop/.keep | 0 .../assets/javascripts/shop/application.js | 15 ++ .../shop/app/assets/stylesheets/scaffold.css | 80 +++++++++++ .../assets/stylesheets/shop/application.css | 15 ++ .../controllers/admin/shop/base_controller.rb | 8 ++ .../admin/shop/items_controller.rb | 51 +++++++ .../app/controllers/shop/base_controller.rb | 21 +++ .../app/controllers/shop/items_controller.rb | 13 ++ .../app/helpers/admin/shop/item_helper.rb | 15 ++ .../app/helpers/admin/shop/shop_helper.rb | 18 +++ .../shop/app/jobs/shop/application_job.rb | 6 + .../app/mailers/shop/application_mailer.rb | 8 ++ .../app/models/shop/application_record.rb | 7 + components/shop/app/models/shop/item.rb | 11 ++ .../shop/app/views/admin/shop/items/form.slim | 16 +++ .../app/views/admin/shop/items/index.slim | 23 ++++ .../shop/app/views/admin/shop/items/show.slim | 13 ++ .../app/views/admin/shop/shared/_nav.slim | 7 + .../shop/app/views/shop/items/index.slim | 11 ++ components/shop/bin/rails | 16 +++ components/shop/config/locales/en.shop.yml | 11 ++ components/shop/config/routes.rb | 13 ++ .../db/migrate/20210510190241_create_items.rb | 14 ++ components/shop/db/seeds.rb | 7 + components/shop/lib/shop.rb | 7 + components/shop/lib/shop/engine.rb | 13 ++ components/shop/lib/shop/version.rb | 5 + components/shop/lib/tasks/shop_tasks.rake | 5 + components/shop/shop.gemspec | 34 +++++ components/shop/spec/dummy/.ruby-version | 1 + components/shop/spec/dummy/Rakefile | 8 ++ .../spec/dummy/app/assets/config/manifest.js | 4 + .../shop/spec/dummy/app/assets/images/.keep | 0 .../app/assets/javascripts/application.js | 15 ++ .../dummy/app/assets/javascripts/cable.js | 13 ++ .../app/assets/javascripts/channels/.keep | 0 .../app/assets/stylesheets/application.css | 15 ++ .../app/controllers/application_controller.rb | 4 + .../spec/dummy/app/controllers/concerns/.keep | 0 .../dummy/app/helpers/application_helper.rb | 7 + .../spec/dummy/app/jobs/application_job.rb | 4 + .../dummy/app/mailers/application_mailer.rb | 6 + .../dummy/app/models/application_record.rb | 5 + .../shop/spec/dummy/app/models/concerns/.keep | 0 components/shop/spec/dummy/bin/bundle | 5 + components/shop/spec/dummy/bin/rails | 6 + components/shop/spec/dummy/bin/rake | 6 + components/shop/spec/dummy/bin/setup | 40 ++++++ components/shop/spec/dummy/bin/update | 35 +++++ components/shop/spec/dummy/bin/yarn | 11 ++ components/shop/spec/dummy/config.ru | 7 + .../shop/spec/dummy/config/application.rb | 20 +++ components/shop/spec/dummy/config/boot.rb | 7 + components/shop/spec/dummy/config/cable.yml | 10 ++ .../shop/spec/dummy/config/database.yml | 25 ++++ .../shop/spec/dummy/config/environment.rb | 7 + .../dummy/config/environments/development.rb | 63 +++++++++ .../dummy/config/environments/production.rb | 96 +++++++++++++ .../spec/dummy/config/environments/test.rb | 48 +++++++ .../application_controller_renderer.rb | 9 ++ .../spec/dummy/config/initializers/assets.rb | 16 +++ .../initializers/backtrace_silencers.rb | 8 ++ .../initializers/content_security_policy.rb | 26 ++++ .../config/initializers/cookies_serializer.rb | 7 + .../initializers/filter_parameter_logging.rb | 6 + .../dummy/config/initializers/inflections.rb | 17 +++ .../dummy/config/initializers/mime_types.rb | 5 + .../config/initializers/wrap_parameters.rb | 16 +++ .../shop/spec/dummy/config/locales/en.yml | 33 +++++ components/shop/spec/dummy/config/puma.rb | 36 +++++ components/shop/spec/dummy/config/routes.rb | 5 + components/shop/spec/dummy/config/spring.rb | 8 ++ components/shop/spec/dummy/config/storage.yml | 34 +++++ components/shop/spec/dummy/db/schema.rb | 24 ++++ components/shop/spec/dummy/lib/assets/.keep | 0 components/shop/spec/dummy/log/.keep | 0 components/shop/spec/dummy/package.json | 5 + components/shop/spec/dummy/public/404.html | 67 +++++++++ components/shop/spec/dummy/public/422.html | 67 +++++++++ components/shop/spec/dummy/public/500.html | 66 +++++++++ .../public/apple-touch-icon-precomposed.png | 0 .../spec/dummy/public/apple-touch-icon.png | 0 components/shop/spec/dummy/public/favicon.ico | 0 components/shop/spec/fixtures/items.yml | 13 ++ components/shop/spec/fixtures/shop/items.yml | 13 ++ .../shop/spec/integration/navigation_test.rb | 9 ++ components/shop/spec/models/item_test.rb | 9 ++ components/shop/spec/models/shop/item_test.rb | 11 ++ components/shop/spec/shop_test.rb | 11 ++ components/shop/spec/test_helper.rb | 21 +++ ...isit_request_attendance_confirmed_email.rb | 1 - db/schema.rb | 11 +- db/seeds.rb | 2 + 105 files changed, 1742 insertions(+), 3 deletions(-) create mode 100644 components/shop/.gitignore create mode 100644 components/shop/Gemfile create mode 100644 components/shop/Gemfile.lock create mode 100644 components/shop/MIT-LICENSE create mode 100644 components/shop/README.md create mode 100644 components/shop/Rakefile create mode 100644 components/shop/app/assets/config/shop_manifest.js create mode 100644 components/shop/app/assets/images/shop/.keep create mode 100644 components/shop/app/assets/javascripts/shop/application.js create mode 100644 components/shop/app/assets/stylesheets/scaffold.css create mode 100644 components/shop/app/assets/stylesheets/shop/application.css create mode 100644 components/shop/app/controllers/admin/shop/base_controller.rb create mode 100644 components/shop/app/controllers/admin/shop/items_controller.rb create mode 100644 components/shop/app/controllers/shop/base_controller.rb create mode 100644 components/shop/app/controllers/shop/items_controller.rb create mode 100644 components/shop/app/helpers/admin/shop/item_helper.rb create mode 100644 components/shop/app/helpers/admin/shop/shop_helper.rb create mode 100644 components/shop/app/jobs/shop/application_job.rb create mode 100644 components/shop/app/mailers/shop/application_mailer.rb create mode 100644 components/shop/app/models/shop/application_record.rb create mode 100644 components/shop/app/models/shop/item.rb create mode 100644 components/shop/app/views/admin/shop/items/form.slim create mode 100644 components/shop/app/views/admin/shop/items/index.slim create mode 100644 components/shop/app/views/admin/shop/items/show.slim create mode 100644 components/shop/app/views/admin/shop/shared/_nav.slim create mode 100644 components/shop/app/views/shop/items/index.slim create mode 100755 components/shop/bin/rails create mode 100644 components/shop/config/locales/en.shop.yml create mode 100644 components/shop/config/routes.rb create mode 100644 components/shop/db/migrate/20210510190241_create_items.rb create mode 100644 components/shop/db/seeds.rb create mode 100644 components/shop/lib/shop.rb create mode 100644 components/shop/lib/shop/engine.rb create mode 100644 components/shop/lib/shop/version.rb create mode 100644 components/shop/lib/tasks/shop_tasks.rake create mode 100644 components/shop/shop.gemspec create mode 100644 components/shop/spec/dummy/.ruby-version create mode 100644 components/shop/spec/dummy/Rakefile create mode 100644 components/shop/spec/dummy/app/assets/config/manifest.js create mode 100644 components/shop/spec/dummy/app/assets/images/.keep create mode 100644 components/shop/spec/dummy/app/assets/javascripts/application.js create mode 100644 components/shop/spec/dummy/app/assets/javascripts/cable.js create mode 100644 components/shop/spec/dummy/app/assets/javascripts/channels/.keep create mode 100644 components/shop/spec/dummy/app/assets/stylesheets/application.css create mode 100644 components/shop/spec/dummy/app/controllers/application_controller.rb create mode 100644 components/shop/spec/dummy/app/controllers/concerns/.keep create mode 100644 components/shop/spec/dummy/app/helpers/application_helper.rb create mode 100644 components/shop/spec/dummy/app/jobs/application_job.rb create mode 100644 components/shop/spec/dummy/app/mailers/application_mailer.rb create mode 100644 components/shop/spec/dummy/app/models/application_record.rb create mode 100644 components/shop/spec/dummy/app/models/concerns/.keep create mode 100755 components/shop/spec/dummy/bin/bundle create mode 100755 components/shop/spec/dummy/bin/rails create mode 100755 components/shop/spec/dummy/bin/rake create mode 100755 components/shop/spec/dummy/bin/setup create mode 100755 components/shop/spec/dummy/bin/update create mode 100755 components/shop/spec/dummy/bin/yarn create mode 100644 components/shop/spec/dummy/config.ru create mode 100644 components/shop/spec/dummy/config/application.rb create mode 100644 components/shop/spec/dummy/config/boot.rb create mode 100644 components/shop/spec/dummy/config/cable.yml create mode 100644 components/shop/spec/dummy/config/database.yml create mode 100644 components/shop/spec/dummy/config/environment.rb create mode 100644 components/shop/spec/dummy/config/environments/development.rb create mode 100644 components/shop/spec/dummy/config/environments/production.rb create mode 100644 components/shop/spec/dummy/config/environments/test.rb create mode 100644 components/shop/spec/dummy/config/initializers/application_controller_renderer.rb create mode 100644 components/shop/spec/dummy/config/initializers/assets.rb create mode 100644 components/shop/spec/dummy/config/initializers/backtrace_silencers.rb create mode 100644 components/shop/spec/dummy/config/initializers/content_security_policy.rb create mode 100644 components/shop/spec/dummy/config/initializers/cookies_serializer.rb create mode 100644 components/shop/spec/dummy/config/initializers/filter_parameter_logging.rb create mode 100644 components/shop/spec/dummy/config/initializers/inflections.rb create mode 100644 components/shop/spec/dummy/config/initializers/mime_types.rb create mode 100644 components/shop/spec/dummy/config/initializers/wrap_parameters.rb create mode 100644 components/shop/spec/dummy/config/locales/en.yml create mode 100644 components/shop/spec/dummy/config/puma.rb create mode 100644 components/shop/spec/dummy/config/routes.rb create mode 100644 components/shop/spec/dummy/config/spring.rb create mode 100644 components/shop/spec/dummy/config/storage.yml create mode 100644 components/shop/spec/dummy/db/schema.rb create mode 100644 components/shop/spec/dummy/lib/assets/.keep create mode 100644 components/shop/spec/dummy/log/.keep create mode 100644 components/shop/spec/dummy/package.json create mode 100644 components/shop/spec/dummy/public/404.html create mode 100644 components/shop/spec/dummy/public/422.html create mode 100644 components/shop/spec/dummy/public/500.html create mode 100644 components/shop/spec/dummy/public/apple-touch-icon-precomposed.png create mode 100644 components/shop/spec/dummy/public/apple-touch-icon.png create mode 100644 components/shop/spec/dummy/public/favicon.ico create mode 100644 components/shop/spec/fixtures/items.yml create mode 100644 components/shop/spec/fixtures/shop/items.yml create mode 100644 components/shop/spec/integration/navigation_test.rb create mode 100644 components/shop/spec/models/item_test.rb create mode 100644 components/shop/spec/models/shop/item_test.rb create mode 100644 components/shop/spec/shop_test.rb create mode 100644 components/shop/spec/test_helper.rb diff --git a/Gemfile b/Gemfile index 8fd65ce01..d9eb31884 100644 --- a/Gemfile +++ b/Gemfile @@ -23,6 +23,7 @@ gem 'sidekiq-scheduler', '~> 2.1.4' gem 'simple_form' gem 'courses', path: 'components/courses' +gem 'shop', path: 'components/shop' gem 'ez-settings' #=== CONFIG =================================================================== diff --git a/Gemfile.lock b/Gemfile.lock index c0d5e45ca..26c70e20d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -16,6 +16,12 @@ PATH simple_form slim-rails +PATH + remote: components/shop + specs: + shop (0.1.0) + rails (~> 5.2.2, >= 5.2.2.1) + GEM remote: https://rubygems.org/ remote: https://rails-assets.org/ @@ -684,6 +690,7 @@ DEPENDENCIES rubocop-rspec sass-rails (~> 5.0) semantic-ui-sass (~> 2.2) + shop! shoulda-matchers sidekiq sidekiq-scheduler (~> 2.1.4) diff --git a/app/helpers/admin/navigation_helper.rb b/app/helpers/admin/navigation_helper.rb index 4993de88a..e9a8e5803 100644 --- a/app/helpers/admin/navigation_helper.rb +++ b/app/helpers/admin/navigation_helper.rb @@ -52,6 +52,10 @@ def admin_pages_link link_to t('pages.plural'), admin_pages_path, class: class_for(:pages) end + def admin_shop_link + link_to t('shop.singular'), admin_shop_items_path, class: class_for(:shop) + end + private def class_for(item) diff --git a/app/views/layouts/admin/_navigation.slim b/app/views/layouts/admin/_navigation.slim index 075c84094..23557d89d 100644 --- a/app/views/layouts/admin/_navigation.slim +++ b/app/views/layouts/admin/_navigation.slim @@ -9,7 +9,7 @@ = admin_email_templates_link = admin_friends_link = admin_pages_link - += admin_shop_link // TOOD @VS: Move all menu items to registry. Or not ? - Ez::Registry.data(:admin_primary_navigation).each do |menu_item| diff --git a/app/views/layouts/app/_header.slim b/app/views/layouts/app/_header.slim index 4bf9d5d26..fa6c0b955 100644 --- a/app/views/layouts/app/_header.slim +++ b/app/views/layouts/app/_header.slim @@ -18,6 +18,8 @@ header.pk-header class="#{header_classlist.compact.join(' ')}" .pk-header__dropdown-list-wr nav ul.pk-list.pk-header__dropdown-list.js-dropdown-list + li.pk-list__unit.pk-header__li-list-wr + = link_to "shop", '/shop/items' li.pk-list__unit.pk-header__li-list-wr a = "info" ul.pk-header__li-list diff --git a/components/shop/.gitignore b/components/shop/.gitignore new file mode 100644 index 000000000..d9548baa4 --- /dev/null +++ b/components/shop/.gitignore @@ -0,0 +1,10 @@ +.bundle/ +log/*.log +pkg/ +spec/dummy/db/*.sqlite3 +spec/dummy/db/*.sqlite3-journal +spec/dummy/log/*.log +spec/dummy/node_modules/ +spec/dummy/yarn-error.log +spec/dummy/storage/ +spec/dummy/tmp/ diff --git a/components/shop/Gemfile b/components/shop/Gemfile new file mode 100644 index 000000000..a83aa8fde --- /dev/null +++ b/components/shop/Gemfile @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' +git_source(:github) { |repo| "https://github.com/#{repo}.git" } + +# Declare your gem's dependencies in shop.gemspec. +# Bundler will treat runtime dependencies like base dependencies, and +# development dependencies will be added by default to the :development group. +gemspec + +# Declare any dependencies that are still in development here instead of in +# your gemspec. These might include edge Rails or gems from your path or +# Git. Remember to move these dependencies to your gemspec before releasing +# your gem to rubygems.org. + +# To use a debugger +# gem 'byebug', group: [:development, :test] +gem 'pry' diff --git a/components/shop/Gemfile.lock b/components/shop/Gemfile.lock new file mode 100644 index 000000000..615454e3e --- /dev/null +++ b/components/shop/Gemfile.lock @@ -0,0 +1,130 @@ +PATH + remote: . + specs: + shop (0.1.0) + rails (~> 5.2.2, >= 5.2.2.1) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.2.6) + actionpack (= 5.2.6) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (5.2.6) + actionpack (= 5.2.6) + actionview (= 5.2.6) + activejob (= 5.2.6) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.2.6) + actionview (= 5.2.6) + activesupport (= 5.2.6) + rack (~> 2.0, >= 2.0.8) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.2.6) + activesupport (= 5.2.6) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.2.6) + activesupport (= 5.2.6) + globalid (>= 0.3.6) + activemodel (5.2.6) + activesupport (= 5.2.6) + activerecord (5.2.6) + activemodel (= 5.2.6) + activesupport (= 5.2.6) + arel (>= 9.0) + activestorage (5.2.6) + actionpack (= 5.2.6) + activerecord (= 5.2.6) + marcel (~> 1.0.0) + activesupport (5.2.6) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + arel (9.0.0) + builder (3.2.4) + coderay (1.1.3) + concurrent-ruby (1.1.8) + crass (1.0.6) + erubi (1.10.0) + globalid (0.4.2) + activesupport (>= 4.2.0) + i18n (1.8.10) + concurrent-ruby (~> 1.0) + loofah (2.9.1) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.1) + mini_mime (>= 0.1.1) + marcel (1.0.1) + method_source (1.0.0) + mini_mime (1.1.0) + minitest (5.14.4) + nio4r (2.5.7) + nokogiri (1.11.3-x86_64-darwin) + racc (~> 1.4) + pry (0.14.1) + coderay (~> 1.1) + method_source (~> 1.0) + racc (1.5.2) + rack (2.2.3) + rack-test (1.1.0) + rack (>= 1.0, < 3) + rails (5.2.6) + actioncable (= 5.2.6) + actionmailer (= 5.2.6) + actionpack (= 5.2.6) + actionview (= 5.2.6) + activejob (= 5.2.6) + activemodel (= 5.2.6) + activerecord (= 5.2.6) + activestorage (= 5.2.6) + activesupport (= 5.2.6) + bundler (>= 1.3.0) + railties (= 5.2.6) + sprockets-rails (>= 2.0.0) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.3.0) + loofah (~> 2.3) + railties (5.2.6) + actionpack (= 5.2.6) + activesupport (= 5.2.6) + method_source + rake (>= 0.8.7) + thor (>= 0.19.0, < 2.0) + rake (13.0.3) + sprockets (4.0.2) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.2) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + sqlite3 (1.4.2) + thor (1.1.0) + thread_safe (0.3.6) + tzinfo (1.2.9) + thread_safe (~> 0.1) + websocket-driver (0.7.3) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + +PLATFORMS + x86_64-darwin-20 + +DEPENDENCIES + pry + shop! + sqlite3 + +BUNDLED WITH + 2.2.16 diff --git a/components/shop/MIT-LICENSE b/components/shop/MIT-LICENSE new file mode 100644 index 000000000..effd19ad4 --- /dev/null +++ b/components/shop/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright 2021 Vasia Ivanyshak + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/components/shop/README.md b/components/shop/README.md new file mode 100644 index 000000000..7a19083d1 --- /dev/null +++ b/components/shop/README.md @@ -0,0 +1,28 @@ +# Shop +Short description and motivation. + +## Usage +How to use my plugin. + +## Installation +Add this line to your application's Gemfile: + +```ruby +gem 'shop' +``` + +And then execute: +```bash +$ bundle +``` + +Or install it yourself as: +```bash +$ gem install shop +``` + +## Contributing +Contribution directions go here. + +## License +The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). diff --git a/components/shop/Rakefile b/components/shop/Rakefile new file mode 100644 index 000000000..4dafbb4d9 --- /dev/null +++ b/components/shop/Rakefile @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +begin + require 'bundler/setup' +rescue LoadError + puts 'You must `gem install bundler` and `bundle install` to run rake tasks' +end + +require 'rdoc/task' + +RDoc::Task.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'Shop' + rdoc.options << '--line-numbers' + rdoc.rdoc_files.include('README.md') + rdoc.rdoc_files.include('lib/**/*.rb') +end + +APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__) +load 'rails/tasks/engine.rake' + +load 'rails/tasks/statistics.rake' + +require 'bundler/gem_tasks' + +require 'rake/testtask' + +Rake::TestTask.new(:test) do |t| + t.libs << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end + +task default: :test diff --git a/components/shop/app/assets/config/shop_manifest.js b/components/shop/app/assets/config/shop_manifest.js new file mode 100644 index 000000000..1aaab3174 --- /dev/null +++ b/components/shop/app/assets/config/shop_manifest.js @@ -0,0 +1,2 @@ +//= link_directory ../javascripts/shop .js +//= link_directory ../stylesheets/shop .css diff --git a/components/shop/app/assets/images/shop/.keep b/components/shop/app/assets/images/shop/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/app/assets/javascripts/shop/application.js b/components/shop/app/assets/javascripts/shop/application.js new file mode 100644 index 000000000..67ce4675c --- /dev/null +++ b/components/shop/app/assets/javascripts/shop/application.js @@ -0,0 +1,15 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. JavaScript code in this file should be added after the last require_* statement. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require rails-ujs +//= require activestorage +//= require_tree . diff --git a/components/shop/app/assets/stylesheets/scaffold.css b/components/shop/app/assets/stylesheets/scaffold.css new file mode 100644 index 000000000..cd4f3de38 --- /dev/null +++ b/components/shop/app/assets/stylesheets/scaffold.css @@ -0,0 +1,80 @@ +body { + background-color: #fff; + color: #333; + margin: 33px; +} + +body, p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { + color: #000; +} + +a:visited { + color: #666; +} + +a:hover { + color: #fff; + background-color: #000; +} + +th { + padding-bottom: 5px; +} + +td { + padding: 0 5px 7px; +} + +div.field, +div.actions { + margin-bottom: 10px; +} + +#notice { + color: green; +} + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; +} + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px 7px 0; + margin-bottom: 20px; + background-color: #f0f0f0; +} + +#error_explanation h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px -7px 0; + background-color: #c00; + color: #fff; +} + +#error_explanation ul li { + font-size: 12px; + list-style: square; +} + +label { + display: block; +} diff --git a/components/shop/app/assets/stylesheets/shop/application.css b/components/shop/app/assets/stylesheets/shop/application.css new file mode 100644 index 000000000..0ebd7fe82 --- /dev/null +++ b/components/shop/app/assets/stylesheets/shop/application.css @@ -0,0 +1,15 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/components/shop/app/controllers/admin/shop/base_controller.rb b/components/shop/app/controllers/admin/shop/base_controller.rb new file mode 100644 index 000000000..c4897ae23 --- /dev/null +++ b/components/shop/app/controllers/admin/shop/base_controller.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module Admin + module Shop + class BaseController < ::Admin::BaseController + end + end +end diff --git a/components/shop/app/controllers/admin/shop/items_controller.rb b/components/shop/app/controllers/admin/shop/items_controller.rb new file mode 100644 index 000000000..f02c00af7 --- /dev/null +++ b/components/shop/app/controllers/admin/shop/items_controller.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +module Admin + module Shop + class ItemsController < ::Admin::Shop::BaseController + helper_method :item, :items + + def new + @item = ::Shop::Item.new + render_form + end + + def edit + item + render_form + end + + def create + item = ::Shop::Item.new(items_params) + + react_to item.save + end + + def update + react_to item.update(items_params) + end + + def destroy + item.destroy && redirect_to(admin_shop_items_path) + end + + private + + def default_redirect + redirect_to admin_shop_items_path + end + + def item + @item ||= ::Shop::Item.find(params[:id]) + end + + def items + @items ||= ::Shop::Item.all + end + + def items_params + params.require(:item).permit(:name, :description, :price, :available_qty) + end + end + end +end diff --git a/components/shop/app/controllers/shop/base_controller.rb b/components/shop/app/controllers/shop/base_controller.rb new file mode 100644 index 000000000..bc4a29bb8 --- /dev/null +++ b/components/shop/app/controllers/shop/base_controller.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Shop + class BaseController < ApplicationController + before_action :authenticate_user! + + private + + def render_form + render :form + end + + def react_to(action) + if action + flash_success && default_redirect + else + flash_error && render_form + end + end + end +end diff --git a/components/shop/app/controllers/shop/items_controller.rb b/components/shop/app/controllers/shop/items_controller.rb new file mode 100644 index 000000000..484aeaf37 --- /dev/null +++ b/components/shop/app/controllers/shop/items_controller.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Shop + class ItemsController < BaseController + helper_method :items + + private + + def items + @items ||= Shop::Item.all + end + end +end diff --git a/components/shop/app/helpers/admin/shop/item_helper.rb b/components/shop/app/helpers/admin/shop/item_helper.rb new file mode 100644 index 000000000..9c2e7a63e --- /dev/null +++ b/components/shop/app/helpers/admin/shop/item_helper.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Admin + module Shop + module ItemHelper + def item_form_url + params[:action] == 'edit' ? admin_shop_item_path : admin_shop_items_path + end + + def item_form_method + params[:action] == 'edit' ? :put : :post + end + end + end +end diff --git a/components/shop/app/helpers/admin/shop/shop_helper.rb b/components/shop/app/helpers/admin/shop/shop_helper.rb new file mode 100644 index 000000000..165862461 --- /dev/null +++ b/components/shop/app/helpers/admin/shop/shop_helper.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module Admin + module Shop + module ShopHelper + def admin_shop_items_nav + render layout: '/admin/shop/shared/nav' do + yield if block_given? + end + end + + def admin_shop_items_overview + link_to icon(:book, t('courses.overview')), + admin_shop_items_path + end + end + end +end diff --git a/components/shop/app/jobs/shop/application_job.rb b/components/shop/app/jobs/shop/application_job.rb new file mode 100644 index 000000000..062247ce7 --- /dev/null +++ b/components/shop/app/jobs/shop/application_job.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module Shop + class ApplicationJob < ActiveJob::Base + end +end diff --git a/components/shop/app/mailers/shop/application_mailer.rb b/components/shop/app/mailers/shop/application_mailer.rb new file mode 100644 index 000000000..1dfbb2361 --- /dev/null +++ b/components/shop/app/mailers/shop/application_mailer.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module Shop + class ApplicationMailer < ActionMailer::Base + default from: 'from@example.com' + layout 'mailer' + end +end diff --git a/components/shop/app/models/shop/application_record.rb b/components/shop/app/models/shop/application_record.rb new file mode 100644 index 000000000..0a2e3b35c --- /dev/null +++ b/components/shop/app/models/shop/application_record.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Shop + class ApplicationRecord < ::ApplicationRecord + self.abstract_class = true + end +end diff --git a/components/shop/app/models/shop/item.rb b/components/shop/app/models/shop/item.rb new file mode 100644 index 000000000..ce7f1c257 --- /dev/null +++ b/components/shop/app/models/shop/item.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Shop + class Item < ApplicationRecord + self.table_name = 'shop_items' + + validation :name, presence: true + validation :price, presence: true + validation :available_qty, presence: true + end +end diff --git a/components/shop/app/views/admin/shop/items/form.slim b/components/shop/app/views/admin/shop/items/form.slim new file mode 100644 index 000000000..304ce3647 --- /dev/null +++ b/components/shop/app/views/admin/shop/items/form.slim @@ -0,0 +1,16 @@ +- title resource_form_text(item, label: :name) + += admin_shop_items_nav do + = resource_form_header(item, label: :name) + = simple_form_for item, url: item_form_url, method: item_form_method, as: :item do |f| + .fields + .sixteen.wide.field.right-align + = link_to t('words.back'), admin_shop_items_path(item), class: 'ui button grey' + = f.button :submit + + .fields + .five.wide.field = f.input :name + .five.wide.field = f.input :description + .six.wide.field = f.input :price + .six.wide.field = f.input :available_qty + diff --git a/components/shop/app/views/admin/shop/items/index.slim b/components/shop/app/views/admin/shop/items/index.slim new file mode 100644 index 000000000..7b30ae1de --- /dev/null +++ b/components/shop/app/views/admin/shop/items/index.slim @@ -0,0 +1,23 @@ +- title t 'shop_items.plural' + += resource_header :shop_item + +table.ui.very.basic.table + thead + tr + th = t 'shop.items.name' + th = t 'shop.items.description' + th = t 'shop.items.price' + th = t 'shop.items.available_qty' + th + + tbody + - items.each do |item| + tr + td = item.name + td = item.description + td = item.price + td = item.available_qty + td = controls do + = admin_edit_resource_link(item) + = admin_destroy_resource_link(item) diff --git a/components/shop/app/views/admin/shop/items/show.slim b/components/shop/app/views/admin/shop/items/show.slim new file mode 100644 index 000000000..5deb23fc8 --- /dev/null +++ b/components/shop/app/views/admin/shop/items/show.slim @@ -0,0 +1,13 @@ +.ui.grid + .ten.wide.column + b = t 'shop.items.name' + p = item.name + + b = t 'shop.items.description' + p = item.description + + b = t 'shop.items.price' + p = item.price + + b = t 'shop.items.available_qty' + p = item.available_qty diff --git a/components/shop/app/views/admin/shop/shared/_nav.slim b/components/shop/app/views/admin/shop/shared/_nav.slim new file mode 100644 index 000000000..c2c1863ce --- /dev/null +++ b/components/shop/app/views/admin/shop/shared/_nav.slim @@ -0,0 +1,7 @@ +.ui.grid + .three.wide.column + .ui.vertical.fluid.tabular.menu + = admin_shop_items_overview + + .thirteen.wide.column + = yield diff --git a/components/shop/app/views/shop/items/index.slim b/components/shop/app/views/shop/items/index.slim new file mode 100644 index 000000000..d5cadf9d9 --- /dev/null +++ b/components/shop/app/views/shop/items/index.slim @@ -0,0 +1,11 @@ + +.pk-container.pk-default-text-font + h2.main-header Shop + + - items.each do |item| + .card.float-left style=("width: 18rem;") + img.card-img-top alt="..." src="https://homepages.cae.wisc.edu/~ece533/images/airplane.png" / + .card-body + h5.card-title= item.name + p.card-text= item.description + a.btn.btn-primary href="#" Go somewhere \ No newline at end of file diff --git a/components/shop/bin/rails b/components/shop/bin/rails new file mode 100755 index 000000000..c2f820098 --- /dev/null +++ b/components/shop/bin/rails @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# This command will automatically be run when you run "rails" with Rails gems +# installed from the root of your application. + +ENGINE_ROOT = File.expand_path('..', __dir__) +ENGINE_PATH = File.expand_path('../lib/shop/engine', __dir__) +APP_PATH = File.expand_path('../test/dummy/config/application', __dir__) + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) + +require 'rails/all' +require 'rails/engine/commands' diff --git a/components/shop/config/locales/en.shop.yml b/components/shop/config/locales/en.shop.yml new file mode 100644 index 000000000..06005b7e0 --- /dev/null +++ b/components/shop/config/locales/en.shop.yml @@ -0,0 +1,11 @@ +en: + shop_items: + singular: Item + shop: + items: + plural: Shop Items + singular: Shop Item + name: Name + description: Description + price: Price + available_qty: Avaliable quantity diff --git a/components/shop/config/routes.rb b/components/shop/config/routes.rb new file mode 100644 index 000000000..391eabbb3 --- /dev/null +++ b/components/shop/config/routes.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +Rails.application.routes.draw do + namespace :shop do + resources :items + end + + namespace :admin do + namespace :shop do + resources :items + end + end +end diff --git a/components/shop/db/migrate/20210510190241_create_items.rb b/components/shop/db/migrate/20210510190241_create_items.rb new file mode 100644 index 000000000..7d2ea21ce --- /dev/null +++ b/components/shop/db/migrate/20210510190241_create_items.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class CreateItems < ActiveRecord::Migration[5.2] + def change + create_table :shop_items do |t| + t.string :name, null: false + t.text :description + t.decimal :price, null: false + t.integer :available_qty, null: false, default: 0 + + t.timestamps + end + end +end diff --git a/components/shop/db/seeds.rb b/components/shop/db/seeds.rb new file mode 100644 index 000000000..88f1a0fde --- /dev/null +++ b/components/shop/db/seeds.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +#=== Shop Items ========================================================================= + +puts ::Shop::Item.where(name: 'Pivorak Socks').first_or_create!( + description: 'Test description', price: 12, available_qty: 5 +) diff --git a/components/shop/lib/shop.rb b/components/shop/lib/shop.rb new file mode 100644 index 000000000..1ff62f4eb --- /dev/null +++ b/components/shop/lib/shop.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'shop/engine' + +module Shop + # Your code goes here... +end diff --git a/components/shop/lib/shop/engine.rb b/components/shop/lib/shop/engine.rb new file mode 100644 index 000000000..a99c4fd13 --- /dev/null +++ b/components/shop/lib/shop/engine.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Shop + class Engine < ::Rails::Engine + initializer :append_migrations do |app| + unless app.root.to_s.match(root.to_s) + config.paths['db/migrate'].expanded.each do |p| + app.config.paths['db/migrate'] << p + end + end + end + end +end diff --git a/components/shop/lib/shop/version.rb b/components/shop/lib/shop/version.rb new file mode 100644 index 000000000..92bb8b3b5 --- /dev/null +++ b/components/shop/lib/shop/version.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module Shop + VERSION = '0.1.0' +end diff --git a/components/shop/lib/tasks/shop_tasks.rake b/components/shop/lib/tasks/shop_tasks.rake new file mode 100644 index 000000000..1f9796b90 --- /dev/null +++ b/components/shop/lib/tasks/shop_tasks.rake @@ -0,0 +1,5 @@ +# frozen_string_literal: true +# desc "Explaining what the task does" +# task :shop do +# # Task goes here +# end diff --git a/components/shop/shop.gemspec b/components/shop/shop.gemspec new file mode 100644 index 000000000..b766d5114 --- /dev/null +++ b/components/shop/shop.gemspec @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +$LOAD_PATH.push File.expand_path('lib', __dir__) + +# Maintain your gem's version: +require 'shop/version' + +# Describe your gem and declare its dependencies: +Gem::Specification.new do |spec| + spec.name = 'shop' + spec.version = Shop::VERSION + spec.authors = ['Vasia Ivanyshak'] + spec.email = ['ivanyshak.vasia@gmail.com'] + spec.homepage = 'https://pivorak.com/' + spec.summary = 'Shop extenstion' + spec.description = 'Shop extenstion' + spec.license = 'MIT' + spec.required_ruby_version '>= 2.6.5' + + # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' + # to allow pushing to a single host or delete this section to allow pushing to any host. + if spec.respond_to?(:metadata) + spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'" + else + raise 'RubyGems 2.0 or newer is required to protect against ' \ + 'public gem pushes.' + end + + spec.files = Dir['{app,config,db,lib}/**/*', 'MIT-LICENSE', 'Rakefile', 'README.md'] + + spec.add_dependency 'rails', '~> 5.2.2', '>= 5.2.2.1' + + spec.add_development_dependency 'sqlite3' +end diff --git a/components/shop/spec/dummy/.ruby-version b/components/shop/spec/dummy/.ruby-version new file mode 100644 index 000000000..a7b149191 --- /dev/null +++ b/components/shop/spec/dummy/.ruby-version @@ -0,0 +1 @@ +ruby-2.6.5 \ No newline at end of file diff --git a/components/shop/spec/dummy/Rakefile b/components/shop/spec/dummy/Rakefile new file mode 100644 index 000000000..488c551fe --- /dev/null +++ b/components/shop/spec/dummy/Rakefile @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# 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/components/shop/spec/dummy/app/assets/config/manifest.js b/components/shop/spec/dummy/app/assets/config/manifest.js new file mode 100644 index 000000000..7a89f4c98 --- /dev/null +++ b/components/shop/spec/dummy/app/assets/config/manifest.js @@ -0,0 +1,4 @@ +//= link_tree ../images +//= link_directory ../javascripts .js +//= link_directory ../stylesheets .css +//= link shop_manifest.js diff --git a/components/shop/spec/dummy/app/assets/images/.keep b/components/shop/spec/dummy/app/assets/images/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/app/assets/javascripts/application.js b/components/shop/spec/dummy/app/assets/javascripts/application.js new file mode 100644 index 000000000..67ce4675c --- /dev/null +++ b/components/shop/spec/dummy/app/assets/javascripts/application.js @@ -0,0 +1,15 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. JavaScript code in this file should be added after the last require_* statement. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require rails-ujs +//= require activestorage +//= require_tree . diff --git a/components/shop/spec/dummy/app/assets/javascripts/cable.js b/components/shop/spec/dummy/app/assets/javascripts/cable.js new file mode 100644 index 000000000..739aa5f02 --- /dev/null +++ b/components/shop/spec/dummy/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/components/shop/spec/dummy/app/assets/javascripts/channels/.keep b/components/shop/spec/dummy/app/assets/javascripts/channels/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/app/assets/stylesheets/application.css b/components/shop/spec/dummy/app/assets/stylesheets/application.css new file mode 100644 index 000000000..0ebd7fe82 --- /dev/null +++ b/components/shop/spec/dummy/app/assets/stylesheets/application.css @@ -0,0 +1,15 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/components/shop/spec/dummy/app/controllers/application_controller.rb b/components/shop/spec/dummy/app/controllers/application_controller.rb new file mode 100644 index 000000000..7944f9f99 --- /dev/null +++ b/components/shop/spec/dummy/app/controllers/application_controller.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class ApplicationController < ActionController::Base +end diff --git a/components/shop/spec/dummy/app/controllers/concerns/.keep b/components/shop/spec/dummy/app/controllers/concerns/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/app/helpers/application_helper.rb b/components/shop/spec/dummy/app/helpers/application_helper.rb new file mode 100644 index 000000000..1b5aae8ef --- /dev/null +++ b/components/shop/spec/dummy/app/helpers/application_helper.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module ApplicationHelper + def title(*); end + + def resource_header(*); end +end diff --git a/components/shop/spec/dummy/app/jobs/application_job.rb b/components/shop/spec/dummy/app/jobs/application_job.rb new file mode 100644 index 000000000..d92ffddcb --- /dev/null +++ b/components/shop/spec/dummy/app/jobs/application_job.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class ApplicationJob < ActiveJob::Base +end diff --git a/components/shop/spec/dummy/app/mailers/application_mailer.rb b/components/shop/spec/dummy/app/mailers/application_mailer.rb new file mode 100644 index 000000000..d84cb6e71 --- /dev/null +++ b/components/shop/spec/dummy/app/mailers/application_mailer.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class ApplicationMailer < ActionMailer::Base + default from: 'from@example.com' + layout 'mailer' +end diff --git a/components/shop/spec/dummy/app/models/application_record.rb b/components/shop/spec/dummy/app/models/application_record.rb new file mode 100644 index 000000000..71fbba5b3 --- /dev/null +++ b/components/shop/spec/dummy/app/models/application_record.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end diff --git a/components/shop/spec/dummy/app/models/concerns/.keep b/components/shop/spec/dummy/app/models/concerns/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/bin/bundle b/components/shop/spec/dummy/bin/bundle new file mode 100755 index 000000000..2dbb71769 --- /dev/null +++ b/components/shop/spec/dummy/bin/bundle @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +load Gem.bin_path('bundler', 'bundle') diff --git a/components/shop/spec/dummy/bin/rails b/components/shop/spec/dummy/bin/rails new file mode 100755 index 000000000..a31728ab9 --- /dev/null +++ b/components/shop/spec/dummy/bin/rails @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +APP_PATH = File.expand_path('../config/application', __dir__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/components/shop/spec/dummy/bin/rake b/components/shop/spec/dummy/bin/rake new file mode 100755 index 000000000..c19995500 --- /dev/null +++ b/components/shop/spec/dummy/bin/rake @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/components/shop/spec/dummy/bin/setup b/components/shop/spec/dummy/bin/setup new file mode 100755 index 000000000..5068a6b28 --- /dev/null +++ b/components/shop/spec/dummy/bin/setup @@ -0,0 +1,40 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# rubocop:disable Style/MixinUsage +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + # puts "\n== Copying sample files ==" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' + # end + + puts "\n== Preparing database ==" + system! 'bin/rails db:setup' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end +# rubocop:enable Style/MixinUsage diff --git a/components/shop/spec/dummy/bin/update b/components/shop/spec/dummy/bin/update new file mode 100755 index 000000000..4f0680e8d --- /dev/null +++ b/components/shop/spec/dummy/bin/update @@ -0,0 +1,35 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# rubocop:disable Style/MixinUsage +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end +# rubocop:enable Style/MixinUsage diff --git a/components/shop/spec/dummy/bin/yarn b/components/shop/spec/dummy/bin/yarn new file mode 100755 index 000000000..4cac416a1 --- /dev/null +++ b/components/shop/spec/dummy/bin/yarn @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +APP_ROOT = File.expand_path('..', __dir__) +Dir.chdir(APP_ROOT) do + exec 'yarnpkg', *ARGV +rescue Errno::ENOENT + warn 'Yarn executable was not detected in the system.' + warn 'Download Yarn at https://yarnpkg.com/en/docs/install' + exit 1 +end diff --git a/components/shop/spec/dummy/config.ru b/components/shop/spec/dummy/config.ru new file mode 100644 index 000000000..842bccc34 --- /dev/null +++ b/components/shop/spec/dummy/config.ru @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# This file is used by Rack-based servers to start the application. + +require_relative 'config/environment' + +run Rails.application diff --git a/components/shop/spec/dummy/config/application.rb b/components/shop/spec/dummy/config/application.rb new file mode 100644 index 000000000..09a12e02a --- /dev/null +++ b/components/shop/spec/dummy/config/application.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require_relative 'boot' + +require 'rails/all' + +Bundler.require(*Rails.groups) +require 'shop' + +module Dummy + class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 5.2 + + # Settings in config/environments/* take precedence over those specified here. + # Application configuration can go into files in config/initializers + # -- all .rb files in that directory are automatically loaded after loading + # the framework and any gems in your application. + end +end diff --git a/components/shop/spec/dummy/config/boot.rb b/components/shop/spec/dummy/config/boot.rb new file mode 100644 index 000000000..6d2cba07a --- /dev/null +++ b/components/shop/spec/dummy/config/boot.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__) + +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +$LOAD_PATH.unshift File.expand_path('../../../lib', __dir__) diff --git a/components/shop/spec/dummy/config/cable.yml b/components/shop/spec/dummy/config/cable.yml new file mode 100644 index 000000000..1cd0f8363 --- /dev/null +++ b/components/shop/spec/dummy/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: dummy_production diff --git a/components/shop/spec/dummy/config/database.yml b/components/shop/spec/dummy/config/database.yml new file mode 100644 index 000000000..0d02f2498 --- /dev/null +++ b/components/shop/spec/dummy/config/database.yml @@ -0,0 +1,25 @@ +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +# +default: &default + adapter: sqlite3 + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + timeout: 5000 + +development: + <<: *default + database: db/development.sqlite3 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + <<: *default + database: db/test.sqlite3 + +production: + <<: *default + database: db/production.sqlite3 diff --git a/components/shop/spec/dummy/config/environment.rb b/components/shop/spec/dummy/config/environment.rb new file mode 100644 index 000000000..d5abe5580 --- /dev/null +++ b/components/shop/spec/dummy/config/environment.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# Load the Rails application. +require_relative 'application' + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/components/shop/spec/dummy/config/environments/development.rb b/components/shop/spec/dummy/config/environments/development.rb new file mode 100644 index 000000000..da0edff2b --- /dev/null +++ b/components/shop/spec/dummy/config/environments/development.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. + if Rails.root.join('tmp', 'caching-dev.txt').exist? + config.action_controller.perform_caching = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{2.days.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + + # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. + config.assets.debug = true + + # Suppress logger output for asset requests. + config.assets.quiet = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true + + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + # config.file_watcher = ActiveSupport::EventedFileUpdateChecker +end diff --git a/components/shop/spec/dummy/config/environments/production.rb b/components/shop/spec/dummy/config/environments/production.rb new file mode 100644 index 000000000..d8767a110 --- /dev/null +++ b/components/shop/spec/dummy/config/environments/production.rb @@ -0,0 +1,96 @@ +# frozen_string_literal: true + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? + + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false + + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # Mount Action Cable outside main process or domain + # config.action_cable.mount_path = nil + # config.action_cable.url = 'wss://example.com/cable' + # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Use the lowest log level to ensure availability of diagnostic information + # when problems arise. + config.log_level = :debug + + # Prepend all log lines with the following tags. + config.log_tags = [:request_id] + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment) + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "dummy_#{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/components/shop/spec/dummy/config/environments/test.rb b/components/shop/spec/dummy/config/environments/test.rb new file mode 100644 index 000000000..3091ac4b7 --- /dev/null +++ b/components/shop/spec/dummy/config/environments/test.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Do not eager load code on boot. This avoids loading your whole application + # just for the purpose of running a single test. If you are using a tool that + # preloads Rails for running tests, you may have to set it to true. + config.eager_load = false + + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{1.hour.to_i}" + } + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates. + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + + # Store uploaded files on the local file system in a temporary directory + config.active_storage.service = :test + + config.action_mailer.perform_caching = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/components/shop/spec/dummy/config/initializers/application_controller_renderer.rb b/components/shop/spec/dummy/config/initializers/application_controller_renderer.rb new file mode 100644 index 000000000..f4556db39 --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/application_controller_renderer.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true +# 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/components/shop/spec/dummy/config/initializers/assets.rb b/components/shop/spec/dummy/config/initializers/assets.rb new file mode 100644 index 000000000..a9b0d0f10 --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/assets.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +# 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/components/shop/spec/dummy/config/initializers/backtrace_silencers.rb b/components/shop/spec/dummy/config/initializers/backtrace_silencers.rb new file mode 100644 index 000000000..d0f0d3b5d --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/backtrace_silencers.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true +# 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/components/shop/spec/dummy/config/initializers/content_security_policy.rb b/components/shop/spec/dummy/config/initializers/content_security_policy.rb new file mode 100644 index 000000000..497f5667c --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/content_security_policy.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy +# For further information see the following documentation +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + +# Rails.application.config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https + +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end + +# If you are using UJS then enable automatic nonce generation +# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } + +# Report CSP violations to a specified URI +# For further information see the following documentation: +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only +# Rails.application.config.content_security_policy_report_only = true diff --git a/components/shop/spec/dummy/config/initializers/cookies_serializer.rb b/components/shop/spec/dummy/config/initializers/cookies_serializer.rb new file mode 100644 index 000000000..ee8dff9c9 --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/cookies_serializer.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# 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/components/shop/spec/dummy/config/initializers/filter_parameter_logging.rb b/components/shop/spec/dummy/config/initializers/filter_parameter_logging.rb new file mode 100644 index 000000000..7a4f47b4c --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +# 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/components/shop/spec/dummy/config/initializers/inflections.rb b/components/shop/spec/dummy/config/initializers/inflections.rb new file mode 100644 index 000000000..aa7435fbc --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/inflections.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true +# 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/components/shop/spec/dummy/config/initializers/mime_types.rb b/components/shop/spec/dummy/config/initializers/mime_types.rb new file mode 100644 index 000000000..6e1d16f02 --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/mime_types.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true +# 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/components/shop/spec/dummy/config/initializers/wrap_parameters.rb b/components/shop/spec/dummy/config/initializers/wrap_parameters.rb new file mode 100644 index 000000000..2f3c0db47 --- /dev/null +++ b/components/shop/spec/dummy/config/initializers/wrap_parameters.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +# 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/components/shop/spec/dummy/config/locales/en.yml b/components/shop/spec/dummy/config/locales/en.yml new file mode 100644 index 000000000..decc5a857 --- /dev/null +++ b/components/shop/spec/dummy/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/components/shop/spec/dummy/config/puma.rb b/components/shop/spec/dummy/config/puma.rb new file mode 100644 index 000000000..d9a94f35d --- /dev/null +++ b/components/shop/spec/dummy/config/puma.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +threads_count = ENV.fetch('RAILS_MAX_THREADS', 5) +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch('PORT', 3000) + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch('RAILS_ENV', 'development') + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. +# +# preload_app! + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/components/shop/spec/dummy/config/routes.rb b/components/shop/spec/dummy/config/routes.rb new file mode 100644 index 000000000..2ee2cef51 --- /dev/null +++ b/components/shop/spec/dummy/config/routes.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +Rails.application.routes.draw do + mount Shop::Engine => '/shop' +end diff --git a/components/shop/spec/dummy/config/spring.rb b/components/shop/spec/dummy/config/spring.rb new file mode 100644 index 000000000..c5933e491 --- /dev/null +++ b/components/shop/spec/dummy/config/spring.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +%w[ + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +].each { |path| Spring.watch(path) } diff --git a/components/shop/spec/dummy/config/storage.yml b/components/shop/spec/dummy/config/storage.yml new file mode 100644 index 000000000..d32f76e8f --- /dev/null +++ b/components/shop/spec/dummy/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket + +# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/components/shop/spec/dummy/db/schema.rb b/components/shop/spec/dummy/db/schema.rb new file mode 100644 index 000000000..2f45cd510 --- /dev/null +++ b/components/shop/spec/dummy/db/schema.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# 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: 20_210_510_190_241) do + create_table 'items', force: :cascade do |t| + t.string 'name' + t.text 'description' + t.decimal 'price' + t.integer 'available_qty' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + end +end diff --git a/components/shop/spec/dummy/lib/assets/.keep b/components/shop/spec/dummy/lib/assets/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/log/.keep b/components/shop/spec/dummy/log/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/package.json b/components/shop/spec/dummy/package.json new file mode 100644 index 000000000..caa2d7bb3 --- /dev/null +++ b/components/shop/spec/dummy/package.json @@ -0,0 +1,5 @@ +{ + "name": "dummy", + "private": true, + "dependencies": {} +} diff --git a/components/shop/spec/dummy/public/404.html b/components/shop/spec/dummy/public/404.html new file mode 100644 index 000000000..2be3af26f --- /dev/null +++ b/components/shop/spec/dummy/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/components/shop/spec/dummy/public/422.html b/components/shop/spec/dummy/public/422.html new file mode 100644 index 000000000..c08eac0d1 --- /dev/null +++ b/components/shop/spec/dummy/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/components/shop/spec/dummy/public/500.html b/components/shop/spec/dummy/public/500.html new file mode 100644 index 000000000..78a030af2 --- /dev/null +++ b/components/shop/spec/dummy/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/components/shop/spec/dummy/public/apple-touch-icon-precomposed.png b/components/shop/spec/dummy/public/apple-touch-icon-precomposed.png new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/public/apple-touch-icon.png b/components/shop/spec/dummy/public/apple-touch-icon.png new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/dummy/public/favicon.ico b/components/shop/spec/dummy/public/favicon.ico new file mode 100644 index 000000000..e69de29bb diff --git a/components/shop/spec/fixtures/items.yml b/components/shop/spec/fixtures/items.yml new file mode 100644 index 000000000..a33d0e06b --- /dev/null +++ b/components/shop/spec/fixtures/items.yml @@ -0,0 +1,13 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + description: MyText + price: 9.99 + available_qty: 1 + +two: + name: MyString + description: MyText + price: 9.99 + available_qty: 1 diff --git a/components/shop/spec/fixtures/shop/items.yml b/components/shop/spec/fixtures/shop/items.yml new file mode 100644 index 000000000..a33d0e06b --- /dev/null +++ b/components/shop/spec/fixtures/shop/items.yml @@ -0,0 +1,13 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + description: MyText + price: 9.99 + available_qty: 1 + +two: + name: MyString + description: MyText + price: 9.99 + available_qty: 1 diff --git a/components/shop/spec/integration/navigation_test.rb b/components/shop/spec/integration/navigation_test.rb new file mode 100644 index 000000000..91d920fb6 --- /dev/null +++ b/components/shop/spec/integration/navigation_test.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'test_helper' + +class NavigationTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/components/shop/spec/models/item_test.rb b/components/shop/spec/models/item_test.rb new file mode 100644 index 000000000..2a464381b --- /dev/null +++ b/components/shop/spec/models/item_test.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'test_helper' + +class ItemTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/components/shop/spec/models/shop/item_test.rb b/components/shop/spec/models/shop/item_test.rb new file mode 100644 index 000000000..973102e2a --- /dev/null +++ b/components/shop/spec/models/shop/item_test.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'test_helper' + +module Shop + class ItemTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end + end +end diff --git a/components/shop/spec/shop_test.rb b/components/shop/spec/shop_test.rb new file mode 100644 index 000000000..7e06e60dc --- /dev/null +++ b/components/shop/spec/shop_test.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'test_helper' + +module Shop + class Test < ActiveSupport::TestCase + test 'truth' do + assert_kind_of Module, Shop + end + end +end diff --git a/components/shop/spec/test_helper.rb b/components/shop/spec/test_helper.rb new file mode 100644 index 000000000..ea8ed4b61 --- /dev/null +++ b/components/shop/spec/test_helper.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +# Configure Rails Environment +ENV['RAILS_ENV'] = 'test' + +require_relative '../test/dummy/config/environment' +ActiveRecord::Migrator.migrations_paths = [File.expand_path('../test/dummy/db/migrate', __dir__)] +ActiveRecord::Migrator.migrations_paths << File.expand_path('../db/migrate', __dir__) +require 'rails/test_help' + +# Filter out Minitest backtrace while allowing backtrace from other libraries +# to be shown. +Minitest.backtrace_filter = Minitest::BacktraceFilter.new + +# Load fixtures from the engine +if ActiveSupport::TestCase.respond_to?(:fixture_path=) + ActiveSupport::TestCase.fixture_path = File.expand_path('fixtures', __dir__) + ActionDispatch::IntegrationTest.fixture_path = ActiveSupport::TestCase.fixture_path + ActiveSupport::TestCase.file_fixture_path = "#{ActiveSupport::TestCase.fixture_path}/files" + ActiveSupport::TestCase.fixtures :all +end diff --git a/db/migrate/20180918142725_seed_new_visit_request_attendance_confirmed_email.rb b/db/migrate/20180918142725_seed_new_visit_request_attendance_confirmed_email.rb index de3a577a4..203fa78f1 100644 --- a/db/migrate/20180918142725_seed_new_visit_request_attendance_confirmed_email.rb +++ b/db/migrate/20180918142725_seed_new_visit_request_attendance_confirmed_email.rb @@ -5,7 +5,6 @@ def up EmailTemplate.create!( title: 'VisitRequestMailer#attendance_confirmed', subject: 'Thanks for confirming your visit', - note: 'Will be sent when attendee answers YES in the final confirmation message', body: File.read('db/seed/email_templates/attendance_confirmed.md') ) end diff --git a/db/schema.rb b/db/schema.rb index 99735d843..788180e9f 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: 2020_03_30_085332) do +ActiveRecord::Schema.define(version: 2021_05_10_190241) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -234,6 +234,15 @@ t.index ["user_id"], name: "index_season_mentors_on_user_id" end + create_table "shop_items", force: :cascade do |t| + t.string "name", null: false + t.text "description" + t.decimal "price", null: false + t.integer "available_qty", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "taggings", id: :serial, force: :cascade do |t| t.integer "tag_id" t.string "taggable_type" diff --git a/db/seeds.rb b/db/seeds.rb index 82c0c6187..ce397a2f3 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -84,3 +84,5 @@ puts '==== Courses seeds ====' Courses::Engine.load_seed + +Shop::Engine.load_seed From 19e323ef22090e711a83bfb8dbeecfd4cf963c98 Mon Sep 17 00:00:00 2001 From: Volodya Sveredyuk Date: Wed, 12 May 2021 18:27:30 +0300 Subject: [PATCH 2/4] Rmove shop gemspec ruby version specification --- components/shop/shop.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/components/shop/shop.gemspec b/components/shop/shop.gemspec index b766d5114..8f5c894bc 100644 --- a/components/shop/shop.gemspec +++ b/components/shop/shop.gemspec @@ -15,7 +15,6 @@ Gem::Specification.new do |spec| spec.summary = 'Shop extenstion' spec.description = 'Shop extenstion' spec.license = 'MIT' - spec.required_ruby_version '>= 2.6.5' # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' # to allow pushing to a single host or delete this section to allow pushing to any host. From 911cd8e2ca3a9b494926b641ddd2d25b19def685 Mon Sep 17 00:00:00 2001 From: Volodya Sveredyuk Date: Wed, 12 May 2021 18:46:05 +0300 Subject: [PATCH 3/4] Refactor view templates. Fix some typos --- .../admin/shop/items_controller.rb | 4 --- .../app/helpers/admin/shop/shop_helper.rb | 10 ------- components/shop/app/models/shop/item.rb | 6 ++--- .../shop/app/views/admin/shop/items/form.slim | 26 +++++++++---------- .../shop/app/views/admin/shop/items/show.slim | 13 ---------- .../app/views/admin/shop/shared/_nav.slim | 7 ----- components/shop/config/locales/en.shop.yml | 2 ++ 7 files changed, 18 insertions(+), 50 deletions(-) delete mode 100644 components/shop/app/views/admin/shop/items/show.slim delete mode 100644 components/shop/app/views/admin/shop/shared/_nav.slim diff --git a/components/shop/app/controllers/admin/shop/items_controller.rb b/components/shop/app/controllers/admin/shop/items_controller.rb index f02c00af7..42f4950cf 100644 --- a/components/shop/app/controllers/admin/shop/items_controller.rb +++ b/components/shop/app/controllers/admin/shop/items_controller.rb @@ -25,10 +25,6 @@ def update react_to item.update(items_params) end - def destroy - item.destroy && redirect_to(admin_shop_items_path) - end - private def default_redirect diff --git a/components/shop/app/helpers/admin/shop/shop_helper.rb b/components/shop/app/helpers/admin/shop/shop_helper.rb index 165862461..8ef75dbe7 100644 --- a/components/shop/app/helpers/admin/shop/shop_helper.rb +++ b/components/shop/app/helpers/admin/shop/shop_helper.rb @@ -3,16 +3,6 @@ module Admin module Shop module ShopHelper - def admin_shop_items_nav - render layout: '/admin/shop/shared/nav' do - yield if block_given? - end - end - - def admin_shop_items_overview - link_to icon(:book, t('courses.overview')), - admin_shop_items_path - end end end end diff --git a/components/shop/app/models/shop/item.rb b/components/shop/app/models/shop/item.rb index ce7f1c257..0ebbe3feb 100644 --- a/components/shop/app/models/shop/item.rb +++ b/components/shop/app/models/shop/item.rb @@ -4,8 +4,8 @@ module Shop class Item < ApplicationRecord self.table_name = 'shop_items' - validation :name, presence: true - validation :price, presence: true - validation :available_qty, presence: true + validates :name, presence: true + validates :price, presence: true + validates :available_qty, presence: true end end diff --git a/components/shop/app/views/admin/shop/items/form.slim b/components/shop/app/views/admin/shop/items/form.slim index 304ce3647..ec959aa91 100644 --- a/components/shop/app/views/admin/shop/items/form.slim +++ b/components/shop/app/views/admin/shop/items/form.slim @@ -1,16 +1,16 @@ - title resource_form_text(item, label: :name) -= admin_shop_items_nav do - = resource_form_header(item, label: :name) - = simple_form_for item, url: item_form_url, method: item_form_method, as: :item do |f| - .fields - .sixteen.wide.field.right-align - = link_to t('words.back'), admin_shop_items_path(item), class: 'ui button grey' - = f.button :submit - - .fields - .five.wide.field = f.input :name - .five.wide.field = f.input :description - .six.wide.field = f.input :price - .six.wide.field = f.input :available_qty += resource_form_header(item, label: :name) += simple_form_for item, url: item_form_url, method: item_form_method, as: :item do |f| + .ui.grid + .sixteen.wide.field.right-align + = link_to t('words.back'), admin_shop_items_path(item), class: 'ui button grey' + = f.button :submit + .ui.grid + .sixteen.wide.field = f.input :name + .ui.grid + .sixteen.wide.field = f.input :description + .ui.grid + .six.wide.field = f.input :price + .six.wide.field = f.input :available_qty diff --git a/components/shop/app/views/admin/shop/items/show.slim b/components/shop/app/views/admin/shop/items/show.slim deleted file mode 100644 index 5deb23fc8..000000000 --- a/components/shop/app/views/admin/shop/items/show.slim +++ /dev/null @@ -1,13 +0,0 @@ -.ui.grid - .ten.wide.column - b = t 'shop.items.name' - p = item.name - - b = t 'shop.items.description' - p = item.description - - b = t 'shop.items.price' - p = item.price - - b = t 'shop.items.available_qty' - p = item.available_qty diff --git a/components/shop/app/views/admin/shop/shared/_nav.slim b/components/shop/app/views/admin/shop/shared/_nav.slim deleted file mode 100644 index c2c1863ce..000000000 --- a/components/shop/app/views/admin/shop/shared/_nav.slim +++ /dev/null @@ -1,7 +0,0 @@ -.ui.grid - .three.wide.column - .ui.vertical.fluid.tabular.menu - = admin_shop_items_overview - - .thirteen.wide.column - = yield diff --git a/components/shop/config/locales/en.shop.yml b/components/shop/config/locales/en.shop.yml index 06005b7e0..8b7ab9536 100644 --- a/components/shop/config/locales/en.shop.yml +++ b/components/shop/config/locales/en.shop.yml @@ -1,4 +1,6 @@ en: + shop: + singular: Shop shop_items: singular: Item shop: From 9e877b688e20ef0aa01a8f8e2c8918770cd52fed Mon Sep 17 00:00:00 2001 From: Volodya Sveredyuk Date: Thu, 10 Jun 2021 11:02:11 +0300 Subject: [PATCH 4/4] Shop Item implementation (#960) Co-authored-by: Vasia Ivanyshak --- Gemfile | 6 +- Gemfile.lock | 13 +- app/assets/stylesheets/app/application.scss | 2 + .../stylesheets/app/pages/shop/_items.scss | 89 ++++++++++++ app/uploaders/default_image_uploader.rb | 14 +- app/uploaders/item_image_uploader.rb | 4 + components/courses/Gemfile.lock | 50 +++---- components/courses/courses.gemspec | 2 +- components/shop/Gemfile | 1 - components/shop/Gemfile.lock | 131 +++++++++++++++++- components/shop/Guardfile | 76 ++++++++++ components/shop/Rakefile | 2 +- .../admin/shop/items_controller.rb | 3 +- .../app/controllers/shop/items_controller.rb | 2 +- components/shop/app/models/shop/item.rb | 5 + components/shop/app/models/shop/item_image.rb | 10 ++ .../shop/app/uploaders/item_image_uploader.rb | 2 + .../shop/app/views/admin/shop/items/form.slim | 6 + .../app/views/admin/shop/items/index.slim | 6 +- .../shop/app/views/shop/items/index.slim | 21 +-- components/shop/bin/rails | 2 +- components/shop/config/locales/en.shop.yml | 5 +- components/shop/config/routes.rb | 4 +- .../db/migrate/20210510190241_create_items.rb | 1 + .../20210514113103_create_item_images.rb | 12 ++ components/shop/lib/shop/engine.rb | 10 ++ components/shop/shop.gemspec | 15 ++ .../app/controllers/admin/base_controller.rb | 72 ++++++++++ .../app/controllers/application_controller.rb | 15 ++ .../dummy/app/helpers/application_helper.rb | 15 ++ .../spec/dummy/config/environments/test.rb | 3 + components/shop/spec/dummy/config/routes.rb | 1 - components/shop/spec/dummy/db/schema.rb | 19 ++- .../shop/spec/factories/item_factory.rb | 9 ++ .../features/admin/shop/items/create_spec.rb | 50 +++++++ .../features/admin/shop/items/list_spec.rb | 13 ++ .../features/admin/shop/items/update_spec.rb | 29 ++++ .../spec/features/shop/add_to_cart_spec.rb | 2 + .../shop/spec/features/shop/checkout_spec.rb | 6 + .../shop/spec/features/shop/home_page_spec.rb | 17 +++ .../spec/features/shop/shopping_cart_spec.rb | 1 + components/shop/spec/models/shop/item_spec.rb | 42 ++++++ components/shop/spec/rails_helper.rb | 30 ++++ components/shop/spec/spec_helper.rb | 19 +++ .../shop/spec/support/features_helpers.rb | 49 +++++++ db/schema.rb | 11 +- 46 files changed, 839 insertions(+), 58 deletions(-) create mode 100644 app/assets/stylesheets/app/pages/shop/_items.scss create mode 100644 app/uploaders/item_image_uploader.rb create mode 100644 components/shop/Guardfile create mode 100644 components/shop/app/models/shop/item_image.rb create mode 100644 components/shop/app/uploaders/item_image_uploader.rb create mode 100644 components/shop/db/migrate/20210514113103_create_item_images.rb create mode 100644 components/shop/spec/dummy/app/controllers/admin/base_controller.rb create mode 100644 components/shop/spec/factories/item_factory.rb create mode 100644 components/shop/spec/features/admin/shop/items/create_spec.rb create mode 100644 components/shop/spec/features/admin/shop/items/list_spec.rb create mode 100644 components/shop/spec/features/admin/shop/items/update_spec.rb create mode 100644 components/shop/spec/features/shop/add_to_cart_spec.rb create mode 100644 components/shop/spec/features/shop/checkout_spec.rb create mode 100644 components/shop/spec/features/shop/home_page_spec.rb create mode 100644 components/shop/spec/features/shop/shopping_cart_spec.rb create mode 100644 components/shop/spec/models/shop/item_spec.rb create mode 100644 components/shop/spec/rails_helper.rb create mode 100644 components/shop/spec/spec_helper.rb create mode 100644 components/shop/spec/support/features_helpers.rb diff --git a/Gemfile b/Gemfile index d9eb31884..8bd4dbb4f 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,8 @@ ruby File.open('.ruby-version').readline.chomp #=== CORE ===================================================================== gem 'acts-as-taggable-on', git: 'https://github.com/Fodoj/acts-as-taggable-on', ref: 'rails-5.2' gem 'carrierwave', '~> 1.2' +gem "mini_magick" +gem 'rmagick' gem 'devise', '~> 4.7.1' gem 'friendly_id', '~> 5.1' gem 'kaminari' @@ -39,8 +41,8 @@ gem 'autoprefixer-rails', '~> 7.1.6' gem 'coffee-rails', '~> 4.2.1' gem 'jquery-rails', '~> 4.2.2' gem 'premailer-rails' # email inline styling -gem 'rails-assets-semantic-ui-calendar', source: 'https://rails-assets.org' -gem 'rails-assets-svgxuse', source: 'https://rails-assets.org' +gem 'rails-assets-semantic-ui-calendar', source: 'http://insecure.rails-assets.org' +gem 'rails-assets-svgxuse', source: 'http://insecure.rails-assets.org' gem 'sass-rails', '~> 5.0' gem 'semantic-ui-sass', '~> 2.2' gem 'slim-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 26c70e20d..703e125f2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -12,7 +12,7 @@ PATH courses (0.1.0) friendly_id kaminari - rails + rails (~> 5.2.2, >= 5.2.2.1) simple_form slim-rails @@ -20,11 +20,16 @@ PATH remote: components/shop specs: shop (0.1.0) + carrierwave (~> 1.2) + friendly_id + kaminari rails (~> 5.2.2, >= 5.2.2.1) + simple_form + slim-rails GEM remote: https://rubygems.org/ - remote: https://rails-assets.org/ + remote: http://insecure.rails-assets.org/ specs: Ascii85 (1.0.3) actioncable (5.2.5) @@ -308,6 +313,7 @@ GEM mime-types (3.3.1) mime-types-data (~> 3.2015) mime-types-data (3.2019.1009) + mini_magick (4.11.0) mini_mime (1.1.0) mini_portile2 (2.5.1) minitest (5.14.4) @@ -455,6 +461,7 @@ GEM mime-types (>= 1.16, < 4.0) netrc (~> 0.8) rexml (3.2.4) + rmagick (4.2.2) rollbar (2.19.4) multi_json rqrcode (1.1.2) @@ -657,6 +664,7 @@ DEPENDENCIES letter_opener listen meta_request + mini_magick newrelic_rpm (~> 5.4) oj (~> 3.7.11) omniauth-facebook (~> 5.0) @@ -679,6 +687,7 @@ DEPENDENCIES recaptcha redcarpet (~> 3.4.0) redis (~> 3.2) + rmagick rollbar (~> 2.19.3) rspec rspec-activemodel-mocks diff --git a/app/assets/stylesheets/app/application.scss b/app/assets/stylesheets/app/application.scss index 1c90b1ecf..784c887b6 100644 --- a/app/assets/stylesheets/app/application.scss +++ b/app/assets/stylesheets/app/application.scss @@ -54,6 +54,8 @@ @import "pages/courses/form"; @import "pages/courses/seasons"; +@import "pages/shop/items"; + @import "pages/donate/form"; @import "pages/agenda/agenda"; diff --git a/app/assets/stylesheets/app/pages/shop/_items.scss b/app/assets/stylesheets/app/pages/shop/_items.scss new file mode 100644 index 000000000..87804ddab --- /dev/null +++ b/app/assets/stylesheets/app/pages/shop/_items.scss @@ -0,0 +1,89 @@ +.main{ + max-width: 1200px; + margin: 0 auto; +} + +h1 { + font-size: 24px; + font-weight: 400; + text-align: center; +} + +img { + height: auto; + max-width: 100%; + vertical-align: middle; +} + +.btn { + color: #ffffff; + padding: 0.8rem; + font-size: 14px; + text-transform: uppercase; + border-radius: 4px; + font-weight: 400; + display: block; + width: 100%; + cursor: pointer; + border: 1px solid rgba(255, 255, 255, 0.2); + background: transparent; +} + +.btn:hover { + background-color: rgba(255, 255, 255, 0.12); +} + +.cards { + display: flex; + flex-wrap: wrap; + list-style: none; + margin: 0; +} + +.cards_item { + display: flex; + padding: 1rem; +} + +@media (min-width: 40rem) { + .cards_item { + width: 50%; + } +} + +@media (min-width: 56rem) { + .cards_item { + width: 33.3333%; + } +} + +.card { + background-color: white; + border-radius: 0.25rem; + box-shadow: 0 20px 40px -14px rgba(0, 0, 0, 0.25); + display: flex; + flex-direction: column; + overflow: hidden; +} + +.card_content { + padding: 1rem; + background: linear-gradient(to bottom left, #ce5739 40%, #FFC39E 100%); +} + +.card_title { + color: #ffffff; + font-size: 1.1rem; + font-weight: 700; + letter-spacing: 1px; + text-transform: capitalize; + margin: 0px; +} + +.card_text { + color: #ffffff; + font-size: 0.875rem; + line-height: 1.5; + margin-bottom: 1.25rem; + font-weight: 400; +} diff --git a/app/uploaders/default_image_uploader.rb b/app/uploaders/default_image_uploader.rb index c9bc16230..e5f3a5661 100644 --- a/app/uploaders/default_image_uploader.rb +++ b/app/uploaders/default_image_uploader.rb @@ -3,7 +3,19 @@ class DefaultImageUploader < CarrierWave::Uploader::Base # Include RMagick or MiniMagick support: # include CarrierWave::RMagick - # include CarrierWave::MiniMagick + include CarrierWave::MiniMagick + + version :small do + process resize_to_fill: [60, 60] + end + + version :middle do + process resize_to_fill: [295, 295] + end + + version :large do + process resize_to_fill: [1200, 1200] + end # Choose what kind of storage to use for this uploader: storage :file diff --git a/app/uploaders/item_image_uploader.rb b/app/uploaders/item_image_uploader.rb new file mode 100644 index 000000000..a7d6f1322 --- /dev/null +++ b/app/uploaders/item_image_uploader.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class ItemImageUploader < DefaultImageUploader +end diff --git a/components/courses/Gemfile.lock b/components/courses/Gemfile.lock index 258b447e1..72aa33c7d 100644 --- a/components/courses/Gemfile.lock +++ b/components/courses/Gemfile.lock @@ -4,7 +4,7 @@ PATH courses (0.1.0) friendly_id kaminari - rails + rails (~> 5.2.2, >= 5.2.2.1) simple_form slim-rails @@ -79,7 +79,7 @@ GEM i18n (>= 0.7) ffi (1.10.0) formatador (0.2.5) - friendly_id (5.2.5) + friendly_id (5.4.2) activerecord (>= 4.0.0) globalid (0.4.2) activesupport (>= 4.2.0) @@ -100,18 +100,18 @@ GEM i18n (1.6.0) concurrent-ruby (~> 1.0) json (2.2.0) - kaminari (1.1.1) + kaminari (1.2.1) activesupport (>= 4.1.0) - kaminari-actionview (= 1.1.1) - kaminari-activerecord (= 1.1.1) - kaminari-core (= 1.1.1) - kaminari-actionview (1.1.1) + kaminari-actionview (= 1.2.1) + kaminari-activerecord (= 1.2.1) + kaminari-core (= 1.2.1) + kaminari-actionview (1.2.1) actionview - kaminari-core (= 1.1.1) - kaminari-activerecord (1.1.1) + kaminari-core (= 1.2.1) + kaminari-activerecord (1.2.1) activerecord - kaminari-core (= 1.1.1) - kaminari-core (1.1.1) + kaminari-core (= 1.2.1) + kaminari-core (1.2.1) launchy (2.4.3) addressable (~> 2.3) listen (3.1.5) @@ -127,12 +127,14 @@ GEM marcel (0.3.3) mimemagic (~> 0.3.2) method_source (0.9.2) - mimemagic (0.3.3) + mimemagic (0.3.10) + nokogiri (~> 1) + rake mini_mime (1.0.1) mini_portile2 (2.4.0) minitest (5.11.3) nenv (0.3.0) - nio4r (2.3.1) + nio4r (2.5.7) nokogiri (1.10.1) mini_portile2 (~> 2.4.0) notiffany (0.1.1) @@ -199,38 +201,38 @@ GEM rspec-support (3.8.0) ruby_dep (1.5.0) shellany (0.0.1) - simple_form (4.1.0) - actionpack (>= 5.0) - activemodel (>= 5.0) + simple_form (5.1.0) + actionpack (>= 5.2) + activemodel (>= 5.2) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) - slim (4.0.1) + slim (4.1.0) temple (>= 0.7.6, < 0.9) tilt (>= 2.0.6, < 2.1) slim-rails (3.2.0) actionpack (>= 3.1) railties (>= 3.1) slim (>= 3.0, < 5.0) - sprockets (3.7.2) + sprockets (4.0.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.2.1) + sprockets-rails (3.2.2) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) sqlite3 (1.3.13) - temple (0.8.1) + temple (0.8.2) thor (0.20.3) thread_safe (0.3.6) - tilt (2.0.9) + tilt (2.0.10) tzinfo (1.2.5) thread_safe (~> 0.1) - websocket-driver (0.7.0) + websocket-driver (0.7.3) websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.3) + websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) @@ -250,4 +252,4 @@ DEPENDENCIES sqlite3 (~> 1.3.6) BUNDLED WITH - 1.16.1 + 1.17.2 diff --git a/components/courses/courses.gemspec b/components/courses/courses.gemspec index 09b48dce8..cd79592c7 100644 --- a/components/courses/courses.gemspec +++ b/components/courses/courses.gemspec @@ -19,7 +19,7 @@ Gem::Specification.new do |s| s.add_dependency 'friendly_id' s.add_dependency 'kaminari' - s.add_dependency 'rails' + s.add_dependency 'rails', '~> 5.2.2', '>= 5.2.2.1' s.add_dependency 'simple_form' s.add_dependency 'slim-rails' diff --git a/components/shop/Gemfile b/components/shop/Gemfile index a83aa8fde..173ba3af4 100644 --- a/components/shop/Gemfile +++ b/components/shop/Gemfile @@ -15,4 +15,3 @@ gemspec # To use a debugger # gem 'byebug', group: [:development, :test] -gem 'pry' diff --git a/components/shop/Gemfile.lock b/components/shop/Gemfile.lock index 615454e3e..08a0af1a7 100644 --- a/components/shop/Gemfile.lock +++ b/components/shop/Gemfile.lock @@ -2,7 +2,12 @@ PATH remote: . specs: shop (0.1.0) + carrierwave (~> 1.2) + friendly_id + kaminari rails (~> 5.2.2, >= 5.2.2.1) + simple_form + slim-rails GEM remote: https://rubygems.org/ @@ -48,31 +53,101 @@ GEM i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) arel (9.0.0) builder (3.2.4) + capybara (3.35.3) + addressable + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + carrierwave (1.3.2) + activemodel (>= 4.0.0) + activesupport (>= 4.0.0) + mime-types (>= 1.16) + ssrf_filter (~> 1.0) coderay (1.1.3) concurrent-ruby (1.1.8) crass (1.0.6) + diff-lcs (1.4.4) + docile (1.4.0) erubi (1.10.0) + factory_bot (6.2.0) + activesupport (>= 5.0.0) + factory_bot_rails (6.2.0) + factory_bot (~> 6.2.0) + railties (>= 5.0.0) + faker (2.18.0) + i18n (>= 1.6, < 2) + ffi (1.15.0) + formatador (0.2.5) + friendly_id (5.4.2) + activerecord (>= 4.0.0) globalid (0.4.2) activesupport (>= 4.2.0) + guard (2.17.0) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (>= 1.0.12, < 2.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.9.12) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-compat (1.2.1) + guard-rspec (4.7.3) + guard (~> 2.1) + guard-compat (~> 1.1) + rspec (>= 2.99.0, < 4.0) i18n (1.8.10) concurrent-ruby (~> 1.0) + kaminari (1.2.1) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.2.1) + kaminari-activerecord (= 1.2.1) + kaminari-core (= 1.2.1) + kaminari-actionview (1.2.1) + actionview + kaminari-core (= 1.2.1) + kaminari-activerecord (1.2.1) + activerecord + kaminari-core (= 1.2.1) + kaminari-core (1.2.1) + launchy (2.5.0) + addressable (~> 2.7) + listen (3.5.1) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) loofah (2.9.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) + lumberjack (1.2.8) mail (2.7.1) mini_mime (>= 0.1.1) marcel (1.0.1) method_source (1.0.0) + mime-types (3.3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2021.0225) mini_mime (1.1.0) minitest (5.14.4) + nenv (0.3.0) nio4r (2.5.7) nokogiri (1.11.3-x86_64-darwin) racc (~> 1.4) + notiffany (0.1.3) + nenv (~> 0.1) + shellany (~> 0.0) pry (0.14.1) coderay (~> 1.1) method_source (~> 1.0) + pry-rails (0.3.9) + pry (>= 0.10.4) + public_suffix (4.0.6) racc (1.5.2) rack (2.2.3) rack-test (1.1.0) @@ -102,6 +177,48 @@ GEM rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) rake (13.0.3) + rb-fsevent (0.11.0) + rb-inotify (0.10.1) + ffi (~> 1.0) + regexp_parser (2.1.1) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-rails (5.0.1) + actionpack (>= 5.2) + activesupport (>= 5.2) + railties (>= 5.2) + rspec-core (~> 3.10) + rspec-expectations (~> 3.10) + rspec-mocks (~> 3.10) + rspec-support (~> 3.10) + rspec-support (3.10.2) + shellany (0.0.1) + simple_form (5.1.0) + actionpack (>= 5.2) + activemodel (>= 5.2) + simplecov (0.21.2) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov_json_formatter (0.1.3) + slim (4.1.0) + temple (>= 0.7.6, < 0.9) + tilt (>= 2.0.6, < 2.1) + slim-rails (3.2.0) + actionpack (>= 3.1) + railties (>= 3.1) + slim (>= 3.0, < 5.0) sprockets (4.0.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -110,20 +227,32 @@ GEM activesupport (>= 4.0) sprockets (>= 3.0.0) sqlite3 (1.4.2) + ssrf_filter (1.0.7) + temple (0.8.2) thor (1.1.0) thread_safe (0.3.6) + tilt (2.0.10) tzinfo (1.2.9) thread_safe (~> 0.1) websocket-driver (0.7.3) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) PLATFORMS x86_64-darwin-20 DEPENDENCIES - pry + capybara + factory_bot_rails + faker + guard-rspec + launchy + pry-rails + rspec-rails shop! + simplecov sqlite3 BUNDLED WITH diff --git a/components/shop/Guardfile b/components/shop/Guardfile new file mode 100644 index 000000000..f682475b1 --- /dev/null +++ b/components/shop/Guardfile @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +# rubocop:disable Metrics/BlockLength + +# A sample Guardfile +# More info at https://github.com/guard/guard#readme + +## Uncomment and set this to only include directories you want to watch +# directories %w(app lib config test spec features) \ +# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")} + +## Note: if you are using the `directories` clause above and you are not +## watching the project directory ('.'), then you will want to move +## the Guardfile to a watched dir and symlink it back, e.g. +# +# $ mkdir config +# $ mv Guardfile config/ +# $ ln -s config/Guardfile . +# +# and, you'll have to watch "config/Guardfile" instead of "Guardfile" + +# NOTE: The cmd option is now required due to the increasing number of ways +# rspec may be run, below are examples of the most common uses. +# * bundler: 'bundle exec rspec' +# * bundler binstubs: 'bin/rspec' +# * spring: 'bin/rspec' (This will use spring if running and you have +# installed the spring binstubs per the docs) +# * zeus: 'zeus rspec' (requires the server to be started separately) +# * 'just' rspec: 'rspec' + +guard :rspec, cmd: 'bundle exec rspec' do + require 'guard/rspec/dsl' + dsl = Guard::RSpec::Dsl.new(self) + + # Feel free to open issues for suggestions and improvements + + # RSpec files + rspec = dsl.rspec + watch(rspec.spec_helper) { rspec.spec_dir } + watch(rspec.spec_support) { rspec.spec_dir } + watch(rspec.spec_files) + + # Ruby files + ruby = dsl.ruby + dsl.watch_spec_files_for(ruby.lib_files) + + # Rails files + rails = dsl.rails(view_extensions: %w[erb haml slim]) + dsl.watch_spec_files_for(rails.app_files) + dsl.watch_spec_files_for(rails.views) + + watch(rails.controllers) do |m| + [ + rspec.spec.call("routing/#{m[1]}_routing"), + rspec.spec.call("controllers/#{m[1]}_controller"), + rspec.spec.call("acceptance/#{m[1]}") + ] + end + + # Rails config changes + watch(rails.spec_helper) { rspec.spec_dir } + watch(rails.routes) { "#{rspec.spec_dir}/routing" } + watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" } + + # Capybara features specs + watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") } + watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") } + + # Turnip features and steps + watch(%r{^spec/acceptance/(.+)\.feature$}) + watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m| + Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' + end +end + +# rubocop:enable Metrics/BlockLength diff --git a/components/shop/Rakefile b/components/shop/Rakefile index 4dafbb4d9..b81a9b0cd 100644 --- a/components/shop/Rakefile +++ b/components/shop/Rakefile @@ -16,7 +16,7 @@ RDoc::Task.new(:rdoc) do |rdoc| rdoc.rdoc_files.include('lib/**/*.rb') end -APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__) +APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__) load 'rails/tasks/engine.rake' load 'rails/tasks/statistics.rake' diff --git a/components/shop/app/controllers/admin/shop/items_controller.rb b/components/shop/app/controllers/admin/shop/items_controller.rb index 42f4950cf..8d5c1771d 100644 --- a/components/shop/app/controllers/admin/shop/items_controller.rb +++ b/components/shop/app/controllers/admin/shop/items_controller.rb @@ -40,7 +40,8 @@ def items end def items_params - params.require(:item).permit(:name, :description, :price, :available_qty) + params.require(:item).permit(:name, :description, :price, :available_qty, :published, + item_images_attributes: [:image]) end end end diff --git a/components/shop/app/controllers/shop/items_controller.rb b/components/shop/app/controllers/shop/items_controller.rb index 484aeaf37..a3dfaa367 100644 --- a/components/shop/app/controllers/shop/items_controller.rb +++ b/components/shop/app/controllers/shop/items_controller.rb @@ -7,7 +7,7 @@ class ItemsController < BaseController private def items - @items ||= Shop::Item.all + @items ||= Shop::Item.active end end end diff --git a/components/shop/app/models/shop/item.rb b/components/shop/app/models/shop/item.rb index 0ebbe3feb..daa6bdf13 100644 --- a/components/shop/app/models/shop/item.rb +++ b/components/shop/app/models/shop/item.rb @@ -4,6 +4,11 @@ module Shop class Item < ApplicationRecord self.table_name = 'shop_items' + has_many :item_images + accepts_nested_attributes_for :item_images + + scope :active, -> { where(published: true) } + validates :name, presence: true validates :price, presence: true validates :available_qty, presence: true diff --git a/components/shop/app/models/shop/item_image.rb b/components/shop/app/models/shop/item_image.rb new file mode 100644 index 000000000..9d8435b51 --- /dev/null +++ b/components/shop/app/models/shop/item_image.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Shop + class ItemImage < ApplicationRecord + self.table_name = 'shop_item_images' + + belongs_to :item + mount_uploader :image, ItemImageUploader + end +end diff --git a/components/shop/app/uploaders/item_image_uploader.rb b/components/shop/app/uploaders/item_image_uploader.rb new file mode 100644 index 000000000..9e3f8f8ae --- /dev/null +++ b/components/shop/app/uploaders/item_image_uploader.rb @@ -0,0 +1,2 @@ +class ItemImageUploader < CarrierWave::Uploader::Base +end \ No newline at end of file diff --git a/components/shop/app/views/admin/shop/items/form.slim b/components/shop/app/views/admin/shop/items/form.slim index ec959aa91..4f0c907ff 100644 --- a/components/shop/app/views/admin/shop/items/form.slim +++ b/components/shop/app/views/admin/shop/items/form.slim @@ -14,3 +14,9 @@ .ui.grid .six.wide.field = f.input :price .six.wide.field = f.input :available_qty + .four.wide.field = f.input :published + + = f.simple_fields_for :item_images, Shop::ItemImage.new do |ff| + .fields + .sixteen.wide.field + = ff.input :image, as: :file diff --git a/components/shop/app/views/admin/shop/items/index.slim b/components/shop/app/views/admin/shop/items/index.slim index 7b30ae1de..a72eb6b0e 100644 --- a/components/shop/app/views/admin/shop/items/index.slim +++ b/components/shop/app/views/admin/shop/items/index.slim @@ -9,6 +9,8 @@ table.ui.very.basic.table th = t 'shop.items.description' th = t 'shop.items.price' th = t 'shop.items.available_qty' + th = t 'shop.items.published' + th = t 'shop.items.img' th tbody @@ -18,6 +20,8 @@ table.ui.very.basic.table td = item.description td = item.price td = item.available_qty + td = item.published + td + = image_tag item.item_images.first.image_url(:small).to_s if item.item_images.first.try(:image_url) td = controls do = admin_edit_resource_link(item) - = admin_destroy_resource_link(item) diff --git a/components/shop/app/views/shop/items/index.slim b/components/shop/app/views/shop/items/index.slim index d5cadf9d9..d69d3fb48 100644 --- a/components/shop/app/views/shop/items/index.slim +++ b/components/shop/app/views/shop/items/index.slim @@ -1,11 +1,12 @@ +h2.main-header Shop -.pk-container.pk-default-text-font - h2.main-header Shop - - - items.each do |item| - .card.float-left style=("width: 18rem;") - img.card-img-top alt="..." src="https://homepages.cae.wisc.edu/~ece533/images/airplane.png" / - .card-body - h5.card-title= item.name - p.card-text= item.description - a.btn.btn-primary href="#" Go somewhere \ No newline at end of file +.main + ul.cards + - items.each do |item| + li.cards_item + .card + = image_tag item.item_images.first.image_url(:middle).to_s, class: 'card_image' if item.item_images.first.try(:image_url) + .card_content + h2.card_title = item.name + p.card_text = item.description + button.btn.card_btn Add to cart diff --git a/components/shop/bin/rails b/components/shop/bin/rails index c2f820098..69462ff26 100755 --- a/components/shop/bin/rails +++ b/components/shop/bin/rails @@ -6,7 +6,7 @@ ENGINE_ROOT = File.expand_path('..', __dir__) ENGINE_PATH = File.expand_path('../lib/shop/engine', __dir__) -APP_PATH = File.expand_path('../test/dummy/config/application', __dir__) +APP_PATH = File.expand_path('../spec/dummy/config/application', __dir__) # Set up gems listed in the Gemfile. ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) diff --git a/components/shop/config/locales/en.shop.yml b/components/shop/config/locales/en.shop.yml index 8b7ab9536..c3ea722a6 100644 --- a/components/shop/config/locales/en.shop.yml +++ b/components/shop/config/locales/en.shop.yml @@ -1,9 +1,8 @@ en: - shop: - singular: Shop shop_items: singular: Item shop: + singular: Shop items: plural: Shop Items singular: Shop Item @@ -11,3 +10,5 @@ en: description: Description price: Price available_qty: Avaliable quantity + published: Published + img: Image diff --git a/components/shop/config/routes.rb b/components/shop/config/routes.rb index 391eabbb3..1a826fb9d 100644 --- a/components/shop/config/routes.rb +++ b/components/shop/config/routes.rb @@ -2,12 +2,12 @@ Rails.application.routes.draw do namespace :shop do - resources :items + resources :items, only: %i[index] end namespace :admin do namespace :shop do - resources :items + resources :items, only: %i[index show new edit create update] end end end diff --git a/components/shop/db/migrate/20210510190241_create_items.rb b/components/shop/db/migrate/20210510190241_create_items.rb index 7d2ea21ce..7cb015c60 100644 --- a/components/shop/db/migrate/20210510190241_create_items.rb +++ b/components/shop/db/migrate/20210510190241_create_items.rb @@ -7,6 +7,7 @@ def change t.text :description t.decimal :price, null: false t.integer :available_qty, null: false, default: 0 + t.boolean :published, default: false t.timestamps end diff --git a/components/shop/db/migrate/20210514113103_create_item_images.rb b/components/shop/db/migrate/20210514113103_create_item_images.rb new file mode 100644 index 000000000..c3a24fa2f --- /dev/null +++ b/components/shop/db/migrate/20210514113103_create_item_images.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class CreateItemImages < ActiveRecord::Migration[5.2] + def change + create_table :shop_item_images do |t| + t.string :image + t.references :item + + t.timestamps + end + end +end diff --git a/components/shop/lib/shop/engine.rb b/components/shop/lib/shop/engine.rb index a99c4fd13..770c783fa 100644 --- a/components/shop/lib/shop/engine.rb +++ b/components/shop/lib/shop/engine.rb @@ -1,5 +1,11 @@ # frozen_string_literal: true +require 'slim-rails' +require 'kaminari' +require 'simple_form' +require 'friendly_id' +require 'carrierwave' + module Shop class Engine < ::Rails::Engine initializer :append_migrations do |app| @@ -9,5 +15,9 @@ class Engine < ::Rails::Engine end end end + + initializer 'sample_engine.factories', after: 'factory_bot.set_factory_paths' do + FactoryBot.definition_file_paths << File.expand_path('../../spec/factories', __dir__) if defined?(FactoryBot) + end end end diff --git a/components/shop/shop.gemspec b/components/shop/shop.gemspec index 8f5c894bc..8f747a731 100644 --- a/components/shop/shop.gemspec +++ b/components/shop/shop.gemspec @@ -29,5 +29,20 @@ Gem::Specification.new do |spec| spec.add_dependency 'rails', '~> 5.2.2', '>= 5.2.2.1' + spec.add_dependency 'friendly_id' + spec.add_dependency 'kaminari' + spec.add_dependency 'simple_form' + spec.add_dependency 'slim-rails' + spec.add_dependency 'carrierwave', '~> 1.2' + + spec.add_development_dependency 'capybara' + spec.add_development_dependency 'faker' + spec.add_development_dependency 'guard-rspec' + spec.add_development_dependency 'launchy' + spec.add_development_dependency 'pry-rails' + spec.add_development_dependency 'rspec-rails' + spec.add_development_dependency 'simplecov' + + spec.add_development_dependency 'factory_bot_rails' spec.add_development_dependency 'sqlite3' end diff --git a/components/shop/spec/dummy/app/controllers/admin/base_controller.rb b/components/shop/spec/dummy/app/controllers/admin/base_controller.rb new file mode 100644 index 000000000..8d1ea4223 --- /dev/null +++ b/components/shop/spec/dummy/app/controllers/admin/base_controller.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +# Mock of original controller +module Admin + class BaseController < ApplicationController + helper_method :current_user, :line_chart + + def self.add_breadcrumb(*); end + + def line_chart(*); end + + def edit + render_form + end + + def current_user + User.find_or_create_by(email: 'test@test.com', first_name: 'Test', last_name: 'User') + end + + private + + def render_form + render :form + end + + def semantic_breadcrumb(*); end + + def add_breadcrumb(resource, label: :title, path: nil) + if resource.instance_of?(String) + semantic_breadcrumb I18n.t(resource), path + else + semantic_breadcrumb resource.send(label), path + end + end + + def add_new_breadcump + add_breadcrumb 'words.new' + end + + def add_edit_breadcump + add_breadcrumb 'words.edit' + end + + def react_to(action) + if action + flash_success && default_redirect + else + flash_error && render_form + end + end + + def flash_success(key = nil) + add_flash(:success, key) + end + + def flash_error(key = nil) + add_flash(:error, key) + end + + def add_flash(type, key = nil) + resource = params[:controller].split('/').last.singularize.capitalize + suffix = params[:action] == 'destroy' ? 'ed' : 'd' + action = "#{params[:action]}#{suffix}" + + flash[type] = t(key || type, scope: :notifications, resource: resource, action: action) + end + + def current_user + @current_user ||= User.where(id: 1).first_or_create(email: 'test@user.com', first_name: 'Test', last_name: 'User') + end + end +end diff --git a/components/shop/spec/dummy/app/controllers/application_controller.rb b/components/shop/spec/dummy/app/controllers/application_controller.rb index 7944f9f99..acc2fbad8 100644 --- a/components/shop/spec/dummy/app/controllers/application_controller.rb +++ b/components/shop/spec/dummy/app/controllers/application_controller.rb @@ -1,4 +1,19 @@ # frozen_string_literal: true class ApplicationController < ActionController::Base + protect_from_forgery with: :exception + + def authenticate_user!; end + + def flash_success + true + end + + def flash_error + true + end + + def current_user + User.find_or_create_by(email: 'test@test.com', first_name: 'Test', last_name: 'User') + end end diff --git a/components/shop/spec/dummy/app/helpers/application_helper.rb b/components/shop/spec/dummy/app/helpers/application_helper.rb index 1b5aae8ef..9f0723975 100644 --- a/components/shop/spec/dummy/app/helpers/application_helper.rb +++ b/components/shop/spec/dummy/app/helpers/application_helper.rb @@ -1,7 +1,22 @@ # frozen_string_literal: true +# Mocks module ApplicationHelper def title(*); end def resource_header(*); end + + def format_timestamp(*); end + + def bool_icon(*); end + + def controls(*); end + + def resource_form_text(*); end + + def resource_form_header(*); end + + def admin_back_link(*); end + + def icon(*); end end diff --git a/components/shop/spec/dummy/config/environments/test.rb b/components/shop/spec/dummy/config/environments/test.rb index 3091ac4b7..53a6653e6 100644 --- a/components/shop/spec/dummy/config/environments/test.rb +++ b/components/shop/spec/dummy/config/environments/test.rb @@ -3,6 +3,9 @@ Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. + # I am very proud of this WORKAROUND! :) + config.paths['db/migrate'] << Shop::Engine.root.join('db', 'migrate').to_s + # 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 diff --git a/components/shop/spec/dummy/config/routes.rb b/components/shop/spec/dummy/config/routes.rb index 2ee2cef51..edf04d2d6 100644 --- a/components/shop/spec/dummy/config/routes.rb +++ b/components/shop/spec/dummy/config/routes.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true Rails.application.routes.draw do - mount Shop::Engine => '/shop' end diff --git a/components/shop/spec/dummy/db/schema.rb b/components/shop/spec/dummy/db/schema.rb index 2f45cd510..285f33b28 100644 --- a/components/shop/spec/dummy/db/schema.rb +++ b/components/shop/spec/dummy/db/schema.rb @@ -12,12 +12,21 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20_210_510_190_241) do - create_table 'items', force: :cascade do |t| - t.string 'name' +ActiveRecord::Schema.define(version: 20_210_514_113_103) do + create_table 'shop_item_images', force: :cascade do |t| + t.string 'image' + t.integer 'item_id' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.index ['item_id'], name: 'index_shop_item_images_on_item_id' + end + + create_table 'shop_items', force: :cascade do |t| + t.string 'name', null: false t.text 'description' - t.decimal 'price' - t.integer 'available_qty' + t.decimal 'price', null: false + t.integer 'available_qty', default: 0, null: false + t.boolean 'published', default: false t.datetime 'created_at', null: false t.datetime 'updated_at', null: false end diff --git a/components/shop/spec/factories/item_factory.rb b/components/shop/spec/factories/item_factory.rb new file mode 100644 index 000000000..4b5194065 --- /dev/null +++ b/components/shop/spec/factories/item_factory.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :item, class: Shop::Item do + name { Faker::Lorem.word } + description { Faker::Lorem.word } + price { 12 } + end +end diff --git a/components/shop/spec/features/admin/shop/items/create_spec.rb b/components/shop/spec/features/admin/shop/items/create_spec.rb new file mode 100644 index 000000000..954a596c3 --- /dev/null +++ b/components/shop/spec/features/admin/shop/items/create_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Shop Item CREATE' do + let!(:shop_item) { create(:item, published: true) } + let(:new_shop_item_path) { '/admin/shop/items/new' } + + before { visit new_shop_item_path } + + describe 'invalid input' do + context 'name is not present' do + it 'validates errors' do + shop_item.name = '' + + expect(shop_item).not_to be_valid + end + end + + context 'price nil' do + it 'validates errors' do + shop_item.price = nil + + expect(shop_item).not_to be_valid + end + end + + context 'available_qty nil' do + it 'validates errors' do + shop_item.available_qty = nil + + expect(shop_item).not_to be_valid + end + end + end + + context 'valid input' do + it 'creates item' do + fill_in 'Name', with: 'Pivorak Socks' + fill_in 'Description', with: 'Very hard interview' + fill_in 'Price', with: 5 + fill_in 'Available qty', with: 10 + check 'Published' + click_button 'Create Item' + + expect(page).to have_current_path '/admin/shop/items' + expect(page).to have_content 'Pivorak Socks' + end + end +end diff --git a/components/shop/spec/features/admin/shop/items/list_spec.rb b/components/shop/spec/features/admin/shop/items/list_spec.rb new file mode 100644 index 000000000..baecfe936 --- /dev/null +++ b/components/shop/spec/features/admin/shop/items/list_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Admin Shop Items LIST' do + let!(:active_item) { create(:item, published: true) } + + scenario 'display items' do + visit '/admin/shop/items' + + expect(page).to have_content active_item.name + end +end diff --git a/components/shop/spec/features/admin/shop/items/update_spec.rb b/components/shop/spec/features/admin/shop/items/update_spec.rb new file mode 100644 index 000000000..9bbbfe566 --- /dev/null +++ b/components/shop/spec/features/admin/shop/items/update_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Shop Item UPDATE' do + let!(:shop_item) { create(:item, published: true) } + let(:edit_shop_item_path) { '/admin/shop/items/1/edit' } + + before { visit edit_shop_item_path } + + context 'invalid input' do + it 'validates errors' do + fill_in 'Name', with: '' + click_button 'Update Item' + + expect_an_error item_name: :blank + end + end + + context 'valid input' do + it 'update season' do + fill_in 'Name', with: 'Best Socks' + click_button 'Update Item' + + expect(page).to have_current_path '/admin/shop/items' + expect(page).to have_content 'Best Socks' + end + end +end diff --git a/components/shop/spec/features/shop/add_to_cart_spec.rb b/components/shop/spec/features/shop/add_to_cart_spec.rb new file mode 100644 index 000000000..5179920ef --- /dev/null +++ b/components/shop/spec/features/shop/add_to_cart_spec.rb @@ -0,0 +1,2 @@ +# frozen_string_literal: true +# TODO diff --git a/components/shop/spec/features/shop/checkout_spec.rb b/components/shop/spec/features/shop/checkout_spec.rb new file mode 100644 index 000000000..daa77a0c8 --- /dev/null +++ b/components/shop/spec/features/shop/checkout_spec.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true +# TODO + +# 1. Shipping +# 2. Payment +# 3. Place order diff --git a/components/shop/spec/features/shop/home_page_spec.rb b/components/shop/spec/features/shop/home_page_spec.rb new file mode 100644 index 000000000..c7ff126f1 --- /dev/null +++ b/components/shop/spec/features/shop/home_page_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe '/shop' do + context 'success' do + let!(:item_a) { create(:item, published: true) } + let!(:item_b) { create(:item, published: false) } + + scenario 'display items' do + visit admin_shop_items_path + + expect(page).to have_content item_a.name + expect(page).to have_content item_b.name + end + end +end diff --git a/components/shop/spec/features/shop/shopping_cart_spec.rb b/components/shop/spec/features/shop/shopping_cart_spec.rb new file mode 100644 index 000000000..464090415 --- /dev/null +++ b/components/shop/spec/features/shop/shopping_cart_spec.rb @@ -0,0 +1 @@ +# TODO diff --git a/components/shop/spec/models/shop/item_spec.rb b/components/shop/spec/models/shop/item_spec.rb new file mode 100644 index 000000000..98eb69fc3 --- /dev/null +++ b/components/shop/spec/models/shop/item_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Shop::Item, type: :model do + describe 'validations' do + context 'when item valid' do + subject { build(:item) } + + it 'is valid with valid attributes' do + expect(subject).to be_valid + end + end + + context 'when name missing' do + subject { build(:item, name: nil) } + + it 'is invalid with valid attributes' do + expect(subject).to_not be_valid + # TODO: expect to have concreter errors + end + end + + context 'when available_qty missing' do + subject { build(:item, available_qty: nil) } + + it 'is invalid with valid attributes' do + expect(subject).to_not be_valid + # TODO: expect to have concreter errors + end + end + + context 'when available_qty price' do + subject { build(:item, price: nil) } + + it 'is invalid with valid attributes' do + expect(subject).to_not be_valid + # TODO: expect to have concreter errors + end + end + end +end diff --git a/components/shop/spec/rails_helper.rb b/components/shop/spec/rails_helper.rb new file mode 100644 index 000000000..c8dd88cbe --- /dev/null +++ b/components/shop/spec/rails_helper.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# This file is copied to spec/ when you run 'rails generate rspec:install' +require 'spec_helper' +ENV['RAILS_ENV'] ||= 'test' + +require File.expand_path('../spec/dummy/config/environment', __dir__) + +abort('The Rails environment is running in production mode!') if Rails.env.production? + +require 'rspec/rails' +require 'pry-rails' +require 'capybara/rails' +require 'factory_bot_rails' +require 'faker' + +Dir[Shop::Engine.root.join('spec/support/*.rb')].sort.each { |f| require f } + +ActiveRecord::Migration.maintain_test_schema! + +Dir['../spec/support/**/*.rb'].sort.each { |f| require f } + +RSpec.configure do |config| + config.use_transactional_fixtures = true + config.infer_spec_type_from_file_location! + config.filter_rails_from_backtrace! + + config.include FactoryBot::Syntax::Methods + config.include Shop::Test::FeaturesHelpers, type: :feature +end diff --git a/components/shop/spec/spec_helper.rb b/components/shop/spec/spec_helper.rb new file mode 100644 index 000000000..c0fc188e4 --- /dev/null +++ b/components/shop/spec/spec_helper.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'pry' +require 'simplecov' +SimpleCov.start 'rails' + +RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + + config.shared_context_metadata_behavior = :apply_to_host_groups + + config.filter_run_when_matching :focus +end diff --git a/components/shop/spec/support/features_helpers.rb b/components/shop/spec/support/features_helpers.rb new file mode 100644 index 000000000..2d087dbf2 --- /dev/null +++ b/components/shop/spec/support/features_helpers.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module Shop + module Test + module FeaturesHelpers + # + # Validation errors + # + def expect_an_error(hash_pair = {}, nope = false) + field = hash_pair.keys.first + value = hash_pair.values.first + error_div = "div.#{field}.field_with_errors" + + msg = case value + when :blank + "can't be blank" + when :has_been_taken + 'has already been taken' + else + value + end + + to_or_not = nope ? :not_to : :to + + expect(page).send(to_or_not, have_css(error_div)) + + return if nope + + expect(find(error_div.to_s)).send(to_or_not, have_content(msg)) + end + + def expect_not_an_error(hash_pair = {}) + expect_an_error(hash_pair, true) + end + + # + # Flash errors + # + def expect_success_flash_message(resource, action) + expect(page).to have_content "#{resource} has been successfully #{action}" + end + + # Error + def expect_error_flash_message(resource, action) + expect(page).to have_content "#{resource} cannot be #{action}. Please check the errors below" + end + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 788180e9f..dd483650b 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: 2021_05_10_190241) do +ActiveRecord::Schema.define(version: 2021_05_14_113103) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -234,11 +234,20 @@ t.index ["user_id"], name: "index_season_mentors_on_user_id" end + create_table "shop_item_images", force: :cascade do |t| + t.string "image" + t.bigint "item_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["item_id"], name: "index_shop_item_images_on_item_id" + end + create_table "shop_items", force: :cascade do |t| t.string "name", null: false t.text "description" t.decimal "price", null: false t.integer "available_qty", default: 0, null: false + t.boolean "published", default: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end