workarea-product_documents 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +20 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  4. data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. data/.github/workflows/ci.yml +57 -0
  7. data/.gitignore +18 -0
  8. data/.rubocop.yml +3 -0
  9. data/CHANGELOG.md +16 -0
  10. data/CODE_OF_CONDUCT.md +3 -0
  11. data/CONTRIBUTING.md +3 -0
  12. data/Gemfile +10 -0
  13. data/LICENSE.md +3 -0
  14. data/README.md +39 -0
  15. data/Rakefile +116 -0
  16. data/app/assets/javascripts/workarea/admin/modules/sort_documents.js +68 -0
  17. data/app/assets/stylesheets/workarea/storefront/product_documents/components/product_documents.scss +22 -0
  18. data/app/controllers/workarea/.keep +0 -0
  19. data/app/controllers/workarea/admin/catalog_product_documents_controller.rb +59 -0
  20. data/app/models/workarea/catalog/product.decorator +7 -0
  21. data/app/models/workarea/catalog/product_document.rb +29 -0
  22. data/app/view_models/workarea/admin/product_view_model.decorator +7 -0
  23. data/app/view_models/workarea/storefront/product_view_model.decorator +7 -0
  24. data/app/views/workarea/.keep +0 -0
  25. data/app/views/workarea/admin/catalog_product_documents/_product_documents.html.haml +14 -0
  26. data/app/views/workarea/admin/catalog_product_documents/index.html.haml +40 -0
  27. data/app/views/workarea/admin/catalog_product_documents/new.html.haml +44 -0
  28. data/app/views/workarea/admin/catalog_products/_documents_card.haml +22 -0
  29. data/app/views/workarea/storefront/products/_product_documents.html.haml +9 -0
  30. data/bin/rails +20 -0
  31. data/config/initializers/appends.rb +21 -0
  32. data/config/initializers/workarea.rb +0 -0
  33. data/config/locales/en.yml +34 -0
  34. data/config/routes.rb +9 -0
  35. data/lib/workarea/product_documents.rb +11 -0
  36. data/lib/workarea/product_documents/engine.rb +8 -0
  37. data/lib/workarea/product_documents/version.rb +5 -0
  38. data/test/dummy/Rakefile +6 -0
  39. data/test/dummy/app/assets/config/manifest.js +4 -0
  40. data/test/dummy/app/assets/images/.keep +0 -0
  41. data/test/dummy/app/assets/javascripts/application.js +13 -0
  42. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  43. data/test/dummy/app/controllers/application_controller.rb +3 -0
  44. data/test/dummy/app/controllers/concerns/.keep +0 -0
  45. data/test/dummy/app/helpers/application_helper.rb +2 -0
  46. data/test/dummy/app/jobs/application_job.rb +2 -0
  47. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  48. data/test/dummy/app/models/concerns/.keep +0 -0
  49. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  50. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  51. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  52. data/test/dummy/bin/bundle +3 -0
  53. data/test/dummy/bin/rails +4 -0
  54. data/test/dummy/bin/rake +4 -0
  55. data/test/dummy/bin/setup +34 -0
  56. data/test/dummy/bin/update +29 -0
  57. data/test/dummy/config.ru +5 -0
  58. data/test/dummy/config/application.rb +27 -0
  59. data/test/dummy/config/boot.rb +5 -0
  60. data/test/dummy/config/cable.yml +9 -0
  61. data/test/dummy/config/environment.rb +5 -0
  62. data/test/dummy/config/environments/development.rb +51 -0
  63. data/test/dummy/config/environments/production.rb +83 -0
  64. data/test/dummy/config/environments/test.rb +44 -0
  65. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  66. data/test/dummy/config/initializers/assets.rb +11 -0
  67. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  68. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  69. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  70. data/test/dummy/config/initializers/inflections.rb +16 -0
  71. data/test/dummy/config/initializers/mime_types.rb +4 -0
  72. data/test/dummy/config/initializers/new_framework_defaults.rb +18 -0
  73. data/test/dummy/config/initializers/workarea.rb +5 -0
  74. data/test/dummy/config/initializers/wrap_parameters.rb +9 -0
  75. data/test/dummy/config/locales/en.yml +23 -0
  76. data/test/dummy/config/puma.rb +47 -0
  77. data/test/dummy/config/routes.rb +5 -0
  78. data/test/dummy/config/secrets.yml +22 -0
  79. data/test/dummy/config/spring.rb +6 -0
  80. data/test/dummy/db/seeds.rb +2 -0
  81. data/test/dummy/lib/assets/.keep +0 -0
  82. data/test/dummy/log/.keep +0 -0
  83. data/test/integration/workarea/admin/product_documents_integration_test.rb +85 -0
  84. data/test/integration/workarea/storefront/product_documents_integration_test.rb +28 -0
  85. data/test/teaspoon_env.rb +6 -0
  86. data/test/test_helper.rb +15 -0
  87. data/test/view_models/workarea/admin/product_view_model_test.decorator +28 -0
  88. data/workarea-product_documents.gemspec +18 -0
  89. metadata +144 -0
@@ -0,0 +1,22 @@
1
+ /*------------------------------------*\
2
+ #PRODUCT-DOCUMENTS
3
+ \*------------------------------------*/
4
+
5
+ .product-documents {}
6
+
7
+ .product-documents__title {}
8
+
9
+ .product-documents__type {
10
+ margin-bottom: 0;
11
+ }
12
+
13
+ .product-documents__display_name {}
14
+
15
+ .product-documents__list {
16
+ @extend %unstyled-list;
17
+ margin-bottom: $margin-bottom;
18
+ }
19
+
20
+ .product-documents__list-item {}
21
+
22
+ .product-documents__link {}
File without changes
@@ -0,0 +1,59 @@
1
+ module Workarea
2
+ class Admin::CatalogProductDocumentsController < Admin::ApplicationController
3
+ required_permissions :catalog
4
+ before_action :find_product
5
+
6
+ def index; end
7
+
8
+ def create
9
+ @document = @product.product_documents.build(params[:document])
10
+
11
+ if @document.save
12
+ flash[:success] = t("workarea.admin.product_documents.flash_messages.create")
13
+ redirect_to catalog_product_documents_path(@product)
14
+ else
15
+ render :index, status: :unprocessable_entity
16
+ end
17
+ end
18
+
19
+ def update
20
+ document = @product.product_documents.find(params[:id])
21
+
22
+ if document.update_attributes(params[:document])
23
+ flash[:success] = t("workarea.admin.product_documents.flash_messages.update")
24
+ redirect_to catalog_product_documents_path(@product)
25
+ else
26
+ render :index, status: :unprocessable_entity
27
+ end
28
+ end
29
+
30
+ def move
31
+ position_data = params.fetch(:positions, {})
32
+
33
+ position_data.each do |document_id, position|
34
+ document = @product.product_documents.find(document_id)
35
+ document.position = position
36
+ end
37
+
38
+ @product.save!
39
+ flash[:success] = t(
40
+ "workarea.admin.product_documents.flash_messages.sorting_saved"
41
+ )
42
+ head :ok
43
+ end
44
+
45
+ def destroy
46
+ @product.product_documents.find(params[:id]).destroy
47
+ flash[:success] = t("workarea.admin.product_documents.flash_messages.delete")
48
+ redirect_to catalog_product_documents_path(@product)
49
+ end
50
+
51
+ private
52
+
53
+ def find_product
54
+ @product = Workarea::Admin::ProductViewModel.wrap(
55
+ Catalog::Product.where(slug: params[:catalog_product_id]).first
56
+ )
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,7 @@
1
+ module Workarea
2
+ decorate Catalog::Product, with: :product_documents do
3
+ decorated do
4
+ embeds_many :product_documents, class_name: 'Workarea::Catalog::ProductDocument'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,29 @@
1
+ module Workarea
2
+ module Catalog
3
+ class ProductDocument
4
+ include ApplicationDocument
5
+ include Ordering
6
+ extend Dragonfly::Model
7
+
8
+ field :type, type: String
9
+ field :document_name, type: String
10
+ field :document_uid, type: String
11
+ field :display_name, type: String
12
+
13
+ embedded_in :product,
14
+ class_name: "Workarea::Catalog::Product",
15
+ inverse_of: :product_documents,
16
+ touch: true
17
+
18
+ dragonfly_accessor :document, app: :workarea
19
+
20
+ def respond_to?(sym, *args)
21
+ super || document.respond_to?(sym)
22
+ end
23
+
24
+ def method_missing(sym, *args, &block)
25
+ document.send(sym, *args, &block) if document.respond_to?(sym)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ module Workarea
2
+ decorate Admin::ProductViewModel, with: :product_documents do
3
+ def documents_by_type
4
+ product_documents.asc(:position).group_by { |doc| doc.display_name }
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Workarea
2
+ decorate Storefront::ProductViewModel, with: :product_documents do
3
+ def documents_by_name
4
+ product_documents.group_by { |doc| doc.display_name }
5
+ end
6
+ end
7
+ end
File without changes
@@ -0,0 +1,14 @@
1
+ .edit-view-documents
2
+ .edit-product__editable
3
+ %h2.heading.heading--5= pluralize(@product.documents.length, 'Document')
4
+ %p.edit-product__editable-action= link_to 'Edit', catalog_product_documents_path(@product), class: 'button button--small', data: { dialog_button: '' }
5
+
6
+ - if @product.documents_by_type.any?
7
+ %ul.edit-product__data-list
8
+ - @product.documents_by_type.each do |type, documents|
9
+ %li
10
+ %span
11
+ - if type.blank?
12
+ #{documents.count} without Type
13
+ - else
14
+ #{documents.count} for #{type.titleize}
@@ -0,0 +1,40 @@
1
+ - @page_title= t('workarea.admin.product_documents.index.page_title', product: @product.name)
2
+
3
+ .view
4
+ .view__header
5
+ .grid
6
+ .grid__cell.grid__cell--25
7
+ .grid__cell.grid__cell--50
8
+ .view__heading
9
+ = link_to_index_for(@product)
10
+ %h1= link_to @product.name, url_for(@product)
11
+ .grid__cell.grid__cell--25
12
+ = render_aux_navigation_for(@product)
13
+
14
+ .view__container
15
+ = render_cards_for(@product, :documents)
16
+
17
+ .section
18
+ %h2.view__heading= t('workarea.admin.product_documents.index.heading')
19
+
20
+ %table
21
+ %thead
22
+ %tr
23
+ %th
24
+ %th= t('workarea.admin.product_documents.index.display_name')
25
+ %th= t('workarea.admin.product_documents.index.file_name')
26
+ %th
27
+ %tbody{ data: { sort_document: '', product_id: @product.to_param } }
28
+ - @product.product_documents.each do |document|
29
+ %tr{ data: { sort_document_id: document.id } }
30
+ %td= inline_svg('workarea/admin/icons/grip.svg', title: t('workarea.admin.product_documents.index.drag_to_rearrange'), class: 'svg-icon svg-icon--small svg-icon--gray')
31
+ %td= document.display_name
32
+ %td= link_to document.document_name, document.url, :target => '_blank'
33
+ %td
34
+ = form_tag catalog_product_document_path(@product, document), method: 'delete', class: 'text-button text-button--destroy' do
35
+ = button_tag value: 'remove_product_document', class: 'text-button text-button--destroy' do
36
+ = inline_svg('workarea/admin/icons/delete.svg', class: 'text-button__icon', title: t('workarea.admin.actions.delete'))
37
+ .workflow-bar
38
+ .grid.grid--auto.grid--right.grid--middle
39
+ .grid__cell
40
+ = link_to t('workarea.admin.product_documents.index.add_new'), new_catalog_product_document_path(@product), class: 'workflow-bar__button workflow-bar__button--create'
@@ -0,0 +1,44 @@
1
+ - @page_title= t('workarea.admin.product_documents.new.page_title', product: @product.name)
2
+
3
+ .product-images.view
4
+ .view__header
5
+ .grid
6
+ .grid__cell.grid__cell--25
7
+ .grid__cell.grid__cell--50
8
+ .view__heading
9
+ = link_to_index_for(@product)
10
+ %h1= link_to @product.name, url_for(@product)
11
+ .grid__cell.grid__cell--25
12
+ = render_aux_navigation_for(@product)
13
+
14
+ .view__container
15
+ = render_cards_for(@product, :documents)
16
+
17
+ .view__container.view__container--narrow
18
+
19
+ .section
20
+ %h2= t('workarea.admin.product_documents.new.new_document')
21
+
22
+ - if @image.present? && @image.errors.present?
23
+ - @image.errors.full_messages.each do |message|
24
+ = render_message 'error', message
25
+
26
+ = form_tag catalog_product_documents_path(@product), method: 'post', multipart: true do
27
+ .property
28
+ = label_tag 'document_document', class: 'property__name' do
29
+ %span.property__text= t('workarea.admin.product_documents.new.document')
30
+ .value= file_field_tag 'document[document]', required: true
31
+ .property
32
+ = label_tag 'document_display_name', class: 'property__name' do
33
+ %span.property__text= t('workarea.admin.product_documents.new.name')
34
+ .value= text_field_tag 'document[display_name]', nil, class: 'text-box'
35
+
36
+ = append_partials('admin.product_document_fields', product: @product)
37
+ .workflow-bar
38
+ .grid.grid--right.grid--middle
39
+ .grid__cell.grid__cell--20
40
+ = link_to t('workarea.admin.form.cancel'), url_for(@product), class: 'workflow-bar__button workflow-bar__button--delete'
41
+
42
+ .grid__cell.grid__cell--80
43
+ .grid.grid--auto.grid--right.grid--middle
44
+ .grid__cell= button_tag t('workarea.admin.product_documents.new.create_document'), value: t('workarea.admin.product_documents.new.create_document'), class: 'workflow-bar__button workflow-bar__button--create'
@@ -0,0 +1,22 @@
1
+ .grid__cell
2
+ .card{ class: card_classes(:documents, local_assigns[:active]) }
3
+ = link_to catalog_product_documents_path(model), class: 'card__header' do
4
+ %span.card__header-text= t('workarea.admin.product_documents.cards.title')
5
+ = inline_svg 'workarea/admin/icons/pages.svg', class: 'card__icon'
6
+
7
+ - if local_assigns[:active].blank?
8
+ .card__body
9
+ - if model.product_documents.empty?
10
+ %p= t('workarea.admin.product_documents.cards.description')
11
+ = link_to new_catalog_product_document_path(model), class: 'card__button' do
12
+ %span.button.button--small= t('workarea.admin.product_documents.cards.add_documents')
13
+ - else
14
+ %ul.list-reset
15
+ - model.product_documents.take(10).each do |document|
16
+ %li
17
+ %strong= document.display_name
18
+ =document.document_name
19
+ - if model.product_documents.size > 10
20
+ %li= t('workarea.admin.cards.more', amount: model.product_documents.size - 10)
21
+ = link_to catalog_product_documents_path(model), class: 'card__button' do
22
+ %span.button.button--small= t('workarea.admin.product_documents.cards.manage_documents')
@@ -0,0 +1,9 @@
1
+ %div.product-documents
2
+ %h3.product-documents__title= t('workarea.storefront.product_documents.show.documents')
3
+ - product.documents_by_name.each do |display_name, documents|
4
+ %p.product-documents__display_name= display_name
5
+
6
+ %ul.product-documents__list
7
+ - documents.each do |document|
8
+ %li.product-documents__list-item
9
+ = link_to document.document_name, document.url, :target => '_blank', class: "product-documents__link"
data/bin/rails ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ ENGINE_ROOT = File.expand_path("../..", __FILE__)
6
+ ENGINE_PATH = File.expand_path("../../lib/workarea/product_documents/engine", __FILE__)
7
+ APP_PATH = File.expand_path("../../test/dummy/config/application", __FILE__)
8
+
9
+ # Set up gems listed in the Gemfile.
10
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
11
+ require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
12
+
13
+ require "action_controller/railtie"
14
+ require "action_view/railtie"
15
+ require "action_mailer/railtie"
16
+ require "rails/test_unit/railtie"
17
+ require "sprockets/railtie"
18
+ require "teaspoon-mocha"
19
+
20
+ require "rails/engine/commands"
@@ -0,0 +1,21 @@
1
+ module Workarea
2
+ Plugin.append_partials(
3
+ "storefront.product_show",
4
+ "workarea/storefront/products/product_documents"
5
+ )
6
+
7
+ Plugin.append_partials(
8
+ "admin.catalog_product_cards",
9
+ "workarea/admin/catalog_products/documents_card"
10
+ )
11
+
12
+ Plugin.append_javascripts(
13
+ "admin.modules",
14
+ "workarea/admin/modules/sort_documents"
15
+ )
16
+
17
+ Plugin.append_stylesheets(
18
+ "store_front.components",
19
+ "workarea/storefront/product_documents/components/product_documents"
20
+ )
21
+ end
File without changes
@@ -0,0 +1,34 @@
1
+ en:
2
+ workarea:
3
+ storefront:
4
+ product_documents:
5
+ show:
6
+ documents: Documents
7
+ admin:
8
+ product_documents:
9
+ new:
10
+ create_document: Create Document
11
+ document: Document
12
+ heading: Documents for %{product}
13
+ name: Display Name
14
+ new_document: New Document
15
+ page_title: Documents for %{product}
16
+ type: Type
17
+ index:
18
+ add_new: Add New Document
19
+ delete: Delete
20
+ display_name: Display Name
21
+ drag_to_rearrange: Drag to rearrange
22
+ file_name: File Name
23
+ heading: Documents
24
+ page_title: Documents for %{product}
25
+ cards:
26
+ title: Documents
27
+ add_documents: Add Documents
28
+ description: Add downloadable documents to show on the product detail page.
29
+ manage_documents: Manage Documents
30
+ flash_messages:
31
+ delete: Your document has been removed.
32
+ create: Your document has been created.
33
+ update: Your document has been updated.
34
+ sorting_saved: The sort has been updated.
data/config/routes.rb ADDED
@@ -0,0 +1,9 @@
1
+ Workarea::Admin::Engine.routes.draw do
2
+ resources :catalog_products, only: [] do
3
+ resources :documents, only: [:index, :create, :update, :destroy, :new ], controller: "catalog_product_documents" do
4
+ collection do
5
+ post :move
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ require "workarea"
2
+ require "workarea/storefront"
3
+ require "workarea/admin"
4
+
5
+ require "workarea/product_documents/engine"
6
+ require "workarea/product_documents/version"
7
+
8
+ module Workarea
9
+ module ProductDocuments
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ module Workarea
2
+ module ProductDocuments
3
+ class Engine < ::Rails::Engine
4
+ include Workarea::Plugin
5
+ isolate_namespace Workarea::ProductDocuments
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module Workarea
2
+ module ProductDocuments
3
+ VERSION = "1.0.0".freeze
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require_relative 'config/application'
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,4 @@
1
+
2
+ //= link_tree ../images
3
+ //= link_directory ../javascripts .js
4
+ //= link_directory ../stylesheets .css
File without changes
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file. JavaScript code in this file should be added after the last require_* statement.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */