workarea-product_documents 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +20 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
- data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/workflows/ci.yml +57 -0
- data/.gitignore +18 -0
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +16 -0
- data/CODE_OF_CONDUCT.md +3 -0
- data/CONTRIBUTING.md +3 -0
- data/Gemfile +10 -0
- data/LICENSE.md +3 -0
- data/README.md +39 -0
- data/Rakefile +116 -0
- data/app/assets/javascripts/workarea/admin/modules/sort_documents.js +68 -0
- data/app/assets/stylesheets/workarea/storefront/product_documents/components/product_documents.scss +22 -0
- data/app/controllers/workarea/.keep +0 -0
- data/app/controllers/workarea/admin/catalog_product_documents_controller.rb +59 -0
- data/app/models/workarea/catalog/product.decorator +7 -0
- data/app/models/workarea/catalog/product_document.rb +29 -0
- data/app/view_models/workarea/admin/product_view_model.decorator +7 -0
- data/app/view_models/workarea/storefront/product_view_model.decorator +7 -0
- data/app/views/workarea/.keep +0 -0
- data/app/views/workarea/admin/catalog_product_documents/_product_documents.html.haml +14 -0
- data/app/views/workarea/admin/catalog_product_documents/index.html.haml +40 -0
- data/app/views/workarea/admin/catalog_product_documents/new.html.haml +44 -0
- data/app/views/workarea/admin/catalog_products/_documents_card.haml +22 -0
- data/app/views/workarea/storefront/products/_product_documents.html.haml +9 -0
- data/bin/rails +20 -0
- data/config/initializers/appends.rb +21 -0
- data/config/initializers/workarea.rb +0 -0
- data/config/locales/en.yml +34 -0
- data/config/routes.rb +9 -0
- data/lib/workarea/product_documents.rb +11 -0
- data/lib/workarea/product_documents/engine.rb +8 -0
- data/lib/workarea/product_documents/version.rb +5 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/config/manifest.js +4 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/jobs/application_job.rb +2 -0
- data/test/dummy/app/mailers/application_mailer.rb +4 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +34 -0
- data/test/dummy/bin/update +29 -0
- data/test/dummy/config.ru +5 -0
- data/test/dummy/config/application.rb +27 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/cable.yml +9 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +51 -0
- data/test/dummy/config/environments/production.rb +83 -0
- data/test/dummy/config/environments/test.rb +44 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/new_framework_defaults.rb +18 -0
- data/test/dummy/config/initializers/workarea.rb +5 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +9 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/puma.rb +47 -0
- data/test/dummy/config/routes.rb +5 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config/spring.rb +6 -0
- data/test/dummy/db/seeds.rb +2 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/integration/workarea/admin/product_documents_integration_test.rb +85 -0
- data/test/integration/workarea/storefront/product_documents_integration_test.rb +28 -0
- data/test/teaspoon_env.rb +6 -0
- data/test/test_helper.rb +15 -0
- data/test/view_models/workarea/admin/product_view_model_test.decorator +28 -0
- data/workarea-product_documents.gemspec +18 -0
- metadata +144 -0
data/app/assets/stylesheets/workarea/storefront/product_documents/components/product_documents.scss
ADDED
@@ -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,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
|
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
data/test/dummy/Rakefile
ADDED
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
|
+
*/
|