mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Compare commits
1 Commits
v5.3.9
...
test/13521
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7cab04553a |
56
.codeclimate.yml
Normal file
56
.codeclimate.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
version: "2"
|
||||
plugins:
|
||||
rubocop:
|
||||
enabled: true
|
||||
channel: "rubocop-1-12"
|
||||
config:
|
||||
file: ".rubocop.yml"
|
||||
scss-lint:
|
||||
enabled: true
|
||||
checks:
|
||||
ImportantRule:
|
||||
enabled: false
|
||||
VendorPrefix:
|
||||
enabled: false
|
||||
LeadingZero:
|
||||
enabled: false
|
||||
PropertySortOrder:
|
||||
enabled: false
|
||||
StringQuotes:
|
||||
enabled: false
|
||||
DeclarationOrder:
|
||||
enabled: false
|
||||
NestingDepth:
|
||||
enabled: false
|
||||
|
||||
duplication:
|
||||
enabled: true
|
||||
exclude_patterns:
|
||||
- "db/**"
|
||||
- "config/initializers/active_record_postgresql_referential_integrity_patch.rb"
|
||||
checks:
|
||||
argument-count:
|
||||
enabled: false
|
||||
complex-logic:
|
||||
enabled: false
|
||||
file-lines:
|
||||
enabled: false
|
||||
method-complexity:
|
||||
enabled: false
|
||||
method-count:
|
||||
enabled: false
|
||||
method-lines:
|
||||
enabled: false
|
||||
nested-control-flow:
|
||||
enabled: false
|
||||
return-statements:
|
||||
enabled: false
|
||||
similar-code:
|
||||
enabled: false
|
||||
identical-code:
|
||||
enabled: false
|
||||
exclude_patterns:
|
||||
- "spec/**/*"
|
||||
- "vendor/**/*"
|
||||
- "app/assets/javascripts/shared/*"
|
||||
- "app/assets/javascripts/jquery-migrate-1.0.0.js"
|
||||
@@ -20,6 +20,7 @@ STRIPE_INSTANCE_SECRET_KEY="bogus_key"
|
||||
STRIPE_CUSTOMER="bogus_customer"
|
||||
STRIPE_ACCOUNT="bogus_account"
|
||||
STRIPE_CLIENT_ID="bogus_client_id"
|
||||
STRIPE_PUBLIC_TEST_API_KEY="bogus_stripe_publishable_key"
|
||||
|
||||
SITE_URL="test.host"
|
||||
|
||||
|
||||
25
.github/dependabot.yml
vendored
25
.github/dependabot.yml
vendored
@@ -4,28 +4,7 @@
|
||||
# Most of the configuration here is not used for security updates though.
|
||||
|
||||
version: 2
|
||||
|
||||
multi-ecosystem-groups:
|
||||
turbo_power:
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
updates:
|
||||
- package-ecosystem: "bundler"
|
||||
directory: "/"
|
||||
patterns: ["turbo_power"]
|
||||
multi-ecosystem-group: "turbo_power"
|
||||
|
||||
# Only specific requirements are specified in Gemfile, so don't touch it.
|
||||
versioning-strategy: lockfile-only
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
patterns: ["turbo_power"]
|
||||
multi-ecosystem-group: "turbo_power"
|
||||
|
||||
# Only specific requirements are specified in package.json, so don't touch it.
|
||||
versioning-strategy: lockfile-only
|
||||
|
||||
- package-ecosystem: "bundler"
|
||||
directory: "/"
|
||||
@@ -40,5 +19,5 @@ updates:
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
# Only specific requirements are specified in package.json, so don't touch it.
|
||||
versioning-strategy: lockfile-only
|
||||
# All versions are specified in package.json, so please update them.
|
||||
versioning-strategy: increase
|
||||
|
||||
13
.github/pull_request.json
vendored
Normal file
13
.github/pull_request.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"pull_request": {
|
||||
"number": 13490,
|
||||
"title": "Bump rails from 7.0.4 to 7.0.8",
|
||||
"id": 99999999,
|
||||
"user": { "login": "dependabot[bot]" }
|
||||
},
|
||||
"repository": {
|
||||
"owner": { "login": "openfoodnetwork" },
|
||||
"name": "openfoodnetwork"
|
||||
},
|
||||
"sender": { "login": "dependabot[bot]" }
|
||||
}
|
||||
15
.github/test-events/dependabot-pr.json
vendored
15
.github/test-events/dependabot-pr.json
vendored
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"pull_request": {
|
||||
"number": 13545,
|
||||
"title": "Bump test from 7.0.4 to 7.0.8",
|
||||
"user": {
|
||||
"login": "dependabot[bot]"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"owner": {
|
||||
"login": "openfoodfoundation"
|
||||
},
|
||||
"name": "openfoodnetwork"
|
||||
}
|
||||
}
|
||||
25
.github/workflows/linters.yml
vendored
25
.github/workflows/linters.yml
vendored
@@ -1,10 +1,10 @@
|
||||
name: Linters
|
||||
on: [pull_request]
|
||||
on: [push, pull_request]
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
jobs:
|
||||
lint:
|
||||
name: reviewdog
|
||||
name: prettier and rubocop
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -21,10 +21,21 @@ jobs:
|
||||
|
||||
- run: git show --no-patch # the commit being tested (which is often a merge due to actions/checkout@v3)
|
||||
|
||||
- uses: reviewdog/action-setup@v1
|
||||
- name: prettier
|
||||
uses: EPMatt/reviewdog-action-prettier@v1
|
||||
with:
|
||||
reviewdog_version: v0.21.0
|
||||
github_token: ${{ secrets.github_token }}
|
||||
reporter: github-pr-check
|
||||
level: error
|
||||
fail_on_error: true
|
||||
|
||||
- run: ./script/reviewdog.sh
|
||||
env:
|
||||
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.github_token }}
|
||||
- name: rubocop
|
||||
uses: reviewdog/action-rubocop@v2
|
||||
with:
|
||||
rubocop_version: gemfile
|
||||
rubocop_extensions: rubocop-rails:gemfile rubocop-rspec:gemfile
|
||||
reporter: github-pr-check
|
||||
level: error
|
||||
filter_mode: nofilter
|
||||
use_bundler: true
|
||||
fail_level: any
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
name: Auto-move Dependabot PRs to Code Review
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
pull_request:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
@@ -12,24 +9,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.user.login == 'dependabot[bot]' || startsWith(github.event.pull_request.title, 'Bump')
|
||||
steps:
|
||||
- name: Generate GitHub App Token
|
||||
id: app-token
|
||||
uses: tibdex/github-app-token@v2
|
||||
with:
|
||||
app_id: ${{ secrets.DEPENDABOT_PR_APP_ID }}
|
||||
private_key: ${{ secrets.DEPENDABOT_PR_APP_PRIVATE_KEY }}
|
||||
installation_retrieval_mode: id
|
||||
installation_retrieval_payload: ${{ secrets.DEPENDABOT_PR_APP_INSTALLATION_ID }}
|
||||
|
||||
- name: Move PR to Code Review in Project v2
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ steps.app-token.outputs.token }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const projectNumber = 8; // for "OFN Delivery board"
|
||||
const org = "openfoodfoundation";
|
||||
const repo = context.repo.repo;
|
||||
const prNumber = context.payload.pull_request.number;
|
||||
const org = context.repo.owner;
|
||||
const repo = context.repo.repo;
|
||||
const prNumber = context.payload.pull_request.number;
|
||||
const statusFieldName = "Status";
|
||||
const statusValue = "Code review 🔎";
|
||||
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -59,4 +59,3 @@ yarn-debug.log*
|
||||
|
||||
/config/credentials.yml.enc
|
||||
/config/master.key
|
||||
.secrets
|
||||
|
||||
@@ -2,12 +2,19 @@
|
||||
# frameworks such as Jekyll/Middleman
|
||||
skip_frontmatter: false
|
||||
|
||||
inherits_from: .haml-lint_todo.yml
|
||||
|
||||
linters:
|
||||
AltText:
|
||||
enabled: false
|
||||
|
||||
ClassAttributeWithStaticValue:
|
||||
enabled: true
|
||||
|
||||
ClassesBeforeIds:
|
||||
enabled: true
|
||||
|
||||
ConsecutiveComments:
|
||||
enabled: true
|
||||
|
||||
ConsecutiveSilentScripts:
|
||||
enabled: true
|
||||
max_consecutive: 2
|
||||
@@ -25,6 +32,7 @@ linters:
|
||||
enabled: true
|
||||
|
||||
LineLength:
|
||||
enabled: true
|
||||
max: 80
|
||||
|
||||
MultilinePipe:
|
||||
@@ -39,11 +47,24 @@ linters:
|
||||
RuboCop:
|
||||
enabled: false
|
||||
|
||||
RubyComments:
|
||||
enabled: true
|
||||
|
||||
SpaceBeforeScript:
|
||||
enabled: true
|
||||
|
||||
SpaceInsideHashAttributes:
|
||||
enabled: true
|
||||
style: no_space
|
||||
|
||||
TagName:
|
||||
enabled: true
|
||||
|
||||
TrailingWhitespace:
|
||||
enabled: true
|
||||
|
||||
UnnecessaryInterpolation:
|
||||
enabled: true
|
||||
|
||||
UnnecessaryStringOutput:
|
||||
enabled: true
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
# This configuration was generated by
|
||||
# `haml-lint --auto-gen-config`
|
||||
# on 2025-10-30 09:19:50 +0100 using Haml-Lint version 0.66.0.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the lints are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of Haml-Lint, may require this file to be generated again.
|
||||
|
||||
linters:
|
||||
|
||||
# Offense count: 35
|
||||
ClassAttributeWithStaticValue:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 77
|
||||
ClassesBeforeIds:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 18
|
||||
ConsecutiveComments:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 22
|
||||
ConsecutiveSilentScripts:
|
||||
exclude:
|
||||
- "app/views/admin/contents/_fieldset.html.haml"
|
||||
- "app/views/admin/enterprises/form/_tag_rules.html.haml"
|
||||
- "app/views/admin/order_cycles/edit.html.haml"
|
||||
- "app/views/admin/products_v3/product_preview.turbo_stream.haml"
|
||||
- "app/views/admin/reports/_date_range_form.html.haml"
|
||||
- "app/views/checkout/_details.html.haml"
|
||||
- "app/views/checkout/_payment.html.haml"
|
||||
- "app/views/spree/admin/adjustments/_adjustments_table.html.haml"
|
||||
- "app/views/spree/admin/orders/customer_details/_address_form.html.haml"
|
||||
- "app/views/spree/admin/tax_categories/index.html.haml"
|
||||
- "app/views/spree/admin/users/index.html.haml"
|
||||
|
||||
# Offense count: 14
|
||||
FinalNewline:
|
||||
exclude:
|
||||
- "app/assets/javascripts/templates/shared/question_mark_with_tooltip.html.haml"
|
||||
- "app/views/admin/enterprises/form/_social.html.haml"
|
||||
- "app/views/admin/json/_injection_ams.html.haml"
|
||||
- "app/views/admin/order_cycles/_date_time_warning_modal_content.html.haml"
|
||||
- "app/views/admin/order_cycles/edit.html.haml"
|
||||
- "app/views/admin/product_import/_ams_data.html.haml"
|
||||
- "app/views/admin/reports/_row_group.haml"
|
||||
- "app/views/admin/reports/filters/_enterprise_fee_summary.html.haml"
|
||||
- "app/views/admin/reports/filters/_users_and_enterprises.html.haml"
|
||||
- "app/views/shop/_blocked_cookies.html.haml"
|
||||
- "app/views/spree/admin/orders/_invoice/_order_note.html.haml"
|
||||
- "app/views/spree/admin/orders/invoice4.html.haml"
|
||||
- "app/views/spree/admin/taxons/destroy_taxon.turbo_stream.haml"
|
||||
- "app/views/spree/admin/users/_email_confirmation.html.haml"
|
||||
|
||||
# Offense count: 130
|
||||
IdNames:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 5
|
||||
Indentation:
|
||||
exclude:
|
||||
- "app/views/admin/products_v3/clone.turbo_stream.haml"
|
||||
- "app/views/admin/products_v3/destroy_product_variant.turbo_stream.haml"
|
||||
- "app/views/spree/admin/taxons/destroy_taxon.turbo_stream.haml"
|
||||
|
||||
# Offense count: 191
|
||||
InlineStyles:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 589
|
||||
InstanceVariables:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 2
|
||||
LeadingCommentSpace:
|
||||
exclude:
|
||||
- "app/views/admin/reports/_row_group.haml"
|
||||
|
||||
# Offense count: 2331
|
||||
LineLength:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 1
|
||||
MultilinePipe:
|
||||
exclude:
|
||||
- "app/views/admin/reports/_rendering_options.html.haml"
|
||||
|
||||
# Offense count: 2
|
||||
MultilineScript:
|
||||
exclude:
|
||||
- "app/views/admin/products_v3/product_preview.turbo_stream.haml"
|
||||
- "app/views/checkout/_voucher_section.html.haml"
|
||||
|
||||
# Offense count: 2
|
||||
RepeatedId:
|
||||
exclude:
|
||||
- "app/assets/javascripts/templates/admin/save_bar.html.haml"
|
||||
|
||||
# Offense count: 24
|
||||
RubyComments:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 104
|
||||
SpaceBeforeScript:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 3345
|
||||
SpaceInsideHashAttributes:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 22
|
||||
TrailingEmptyLines:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 73
|
||||
TrailingWhitespace:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 13
|
||||
UnnecessaryInterpolation:
|
||||
exclude:
|
||||
- "app/components/example_component/example_component.html.haml"
|
||||
- "app/views/admin/product_import/_entries_table.html.haml"
|
||||
- "app/views/admin/product_import/import.html.haml"
|
||||
- "app/views/admin/variant_overrides/_filters.html.haml"
|
||||
- "app/views/registration/steps/_introduction.html.haml"
|
||||
- "app/views/spree/order_mailer/_shipping.html.haml"
|
||||
- "app/views/spree/order_mailer/invoice_email.html.haml"
|
||||
- "app/views/spree/shared/_shipment_delivery_details.html.haml"
|
||||
- "app/views/spree/shared/_shipment_pickup_details.html.haml"
|
||||
|
||||
# Offense count: 68
|
||||
UnnecessaryStringOutput:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 14
|
||||
ViewLength:
|
||||
exclude:
|
||||
- "app/assets/javascripts/templates/admin/panels/enterprise_package.html.haml"
|
||||
- "app/views/admin/customers/index.html.haml"
|
||||
- "app/views/admin/enterprises/_new_form.html.haml"
|
||||
- "app/views/admin/enterprises/form/_shop_preferences.html.haml"
|
||||
- "app/views/admin/product_import/_import_review.html.haml"
|
||||
- "app/views/admin/products_v3/product_preview.turbo_stream.haml"
|
||||
- "app/views/checkout/_details.html.haml"
|
||||
- "app/views/groups/show.html.haml"
|
||||
- "app/views/producer_mailer/order_cycle_report.html.haml"
|
||||
- "app/views/shared/_footer.html.haml"
|
||||
- "app/views/spree/admin/orders/bulk_management.html.haml"
|
||||
- "app/views/spree/admin/orders/invoice4.html.haml"
|
||||
- "app/views/spree/admin/products/new.html.haml"
|
||||
- "app/views/spree/admin/variants/_form.html.haml"
|
||||
6
.hound.yml
Normal file
6
.hound.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
rubocop:
|
||||
config_file: .rubocop_styleguide.yml
|
||||
scss:
|
||||
config_file: .scss-lint.yml
|
||||
haml:
|
||||
config_file: .haml-lint.yml
|
||||
@@ -1 +1 @@
|
||||
24.10.0
|
||||
17.9.1
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
# The configuration is split into three files. Look into those files for more details.
|
||||
#
|
||||
plugins:
|
||||
require:
|
||||
- rubocop-capybara
|
||||
- rubocop-factory_bot
|
||||
- rubocop-rails
|
||||
|
||||
@@ -94,7 +94,7 @@ Metrics/PerceivedComplexity:
|
||||
Enabled: true
|
||||
Max: 14 # default 8
|
||||
|
||||
Naming/PredicatePrefix:
|
||||
Naming/PredicateName:
|
||||
Enabled: false
|
||||
|
||||
Naming/VariableNumber:
|
||||
|
||||
@@ -1,44 +1,11 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 1400 --no-auto-gen-timestamp`
|
||||
# using RuboCop version 1.81.7.
|
||||
# using RuboCop version 1.64.1.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of RuboCop, may require this file to be generated again.
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: RequireParenthesesForMethodChains.
|
||||
Lint/AmbiguousRange:
|
||||
Exclude:
|
||||
- 'app/models/concerns/permalink_generator.rb'
|
||||
|
||||
# Offense count: 6
|
||||
Lint/CopDirectiveSyntax:
|
||||
Exclude:
|
||||
- 'app/services/orders/bulk_cancel_service.rb'
|
||||
- 'lib/tasks/simplecov.rake'
|
||||
- 'spec/models/database_spec.rb'
|
||||
- 'spec/system/admin/bulk_order_management_spec.rb'
|
||||
- 'spec/system/admin/enterprise_relationships_spec.rb'
|
||||
|
||||
# Offense count: 2
|
||||
Lint/DuplicateMethods:
|
||||
Exclude:
|
||||
- 'app/models/spree/order.rb'
|
||||
- 'engines/order_management/app/services/order_management/subscriptions/form.rb'
|
||||
|
||||
# Offense count: 3
|
||||
Lint/UselessConstantScoping:
|
||||
Exclude:
|
||||
- 'app/services/weights_and_measures.rb'
|
||||
- 'lib/reporting/report_metadata_builder.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Lint/UselessOr:
|
||||
Exclude:
|
||||
- 'app/models/product_import/entry_validator.rb'
|
||||
|
||||
# Offense count: 24
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
||||
Metrics/AbcSize:
|
||||
@@ -75,12 +42,12 @@ Metrics/BlockLength:
|
||||
- 'lib/tasks/data.rake'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: CountBlocks, CountModifierForms, Max.
|
||||
# Configuration parameters: CountBlocks, Max.
|
||||
Metrics/BlockNesting:
|
||||
Exclude:
|
||||
- 'app/models/spree/payment/processing.rb'
|
||||
|
||||
# Offense count: 49
|
||||
# Offense count: 47
|
||||
# Configuration parameters: CountComments, Max, CountAsOne.
|
||||
Metrics/ClassLength:
|
||||
Exclude:
|
||||
@@ -121,8 +88,6 @@ Metrics/ClassLength:
|
||||
- 'app/services/cart_service.rb'
|
||||
- 'app/services/order_cycles/form_service.rb'
|
||||
- 'app/services/orders/sync_service.rb'
|
||||
- 'app/services/permissions/order.rb'
|
||||
- 'app/services/products_renderer.rb'
|
||||
- 'app/services/sets/product_set.rb'
|
||||
- 'engines/order_management/app/services/order_management/order/updater.rb'
|
||||
- 'lib/open_food_network/enterprise_fee_calculator.rb'
|
||||
@@ -133,8 +98,9 @@ Metrics/ClassLength:
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_producer.rb'
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
|
||||
- 'lib/reporting/reports/xero_invoices/base.rb'
|
||||
- 'app/services/permissions/order.rb'
|
||||
|
||||
# Offense count: 37
|
||||
# Offense count: 30
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
||||
Metrics/CyclomaticComplexity:
|
||||
Exclude:
|
||||
@@ -157,24 +123,20 @@ Metrics/CyclomaticComplexity:
|
||||
- 'app/models/spree/tax_rate.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
- 'lib/open_food_network/enterprise_issue_validator.rb'
|
||||
- 'lib/reporting/reports/orders_and_fulfillment/order_cycle_customer_totals.rb'
|
||||
- 'lib/reporting/reports/orders_and_fulfillment/order_cycle_supplier_totals.rb'
|
||||
- 'lib/reporting/reports/payments/itemised_payment_totals.rb'
|
||||
- 'lib/reporting/reports/payments/payment_totals.rb'
|
||||
- 'lib/reporting/reports/sales_tax/sales_tax_totals_by_producer.rb'
|
||||
- 'lib/reporting/reports/xero_invoices/base.rb'
|
||||
- 'lib/spree/core/controller_helpers/order.rb'
|
||||
- 'lib/spree/core/controller_helpers/respond_with.rb'
|
||||
- 'lib/spree/localized_number.rb'
|
||||
- 'spec/models/product_importer_spec.rb'
|
||||
|
||||
# Offense count: 22
|
||||
# Offense count: 23
|
||||
# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
|
||||
Metrics/MethodLength:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/enterprises_controller.rb'
|
||||
- 'app/controllers/payment_gateways/paypal_controller.rb'
|
||||
- 'app/controllers/spree/orders_controller.rb'
|
||||
- 'app/helpers/spree/admin/navigation_helper.rb'
|
||||
- 'app/models/spree/ability.rb'
|
||||
- 'app/models/spree/gateway/pay_pal_express.rb'
|
||||
- 'app/models/spree/order/checkout.rb'
|
||||
@@ -187,7 +149,7 @@ Metrics/MethodLength:
|
||||
- 'lib/spree/localized_number.rb'
|
||||
- 'lib/tasks/sample_data/product_factory.rb'
|
||||
|
||||
# Offense count: 10
|
||||
# Offense count: 47
|
||||
# Configuration parameters: CountComments, Max, CountAsOne.
|
||||
Metrics/ModuleLength:
|
||||
Exclude:
|
||||
@@ -212,7 +174,7 @@ Metrics/ParameterLists:
|
||||
- 'spec/support/controller_requests_helper.rb'
|
||||
- 'spec/system/admin/reports_spec.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# Offense count: 3
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
||||
Metrics/PerceivedComplexity:
|
||||
Exclude:
|
||||
@@ -220,165 +182,16 @@ Metrics/PerceivedComplexity:
|
||||
- 'app/models/spree/ability.rb'
|
||||
- 'app/models/spree/order/checkout.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: EnforcedStyle, AllowedPatterns, ForbiddenIdentifiers, ForbiddenPatterns.
|
||||
# SupportedStyles: snake_case, camelCase
|
||||
# ForbiddenIdentifiers: __id__, __send__
|
||||
Naming/MethodName:
|
||||
Exclude:
|
||||
- 'engines/dfc_provider/lib/dfc_provider/catalog_item.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
||||
# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
|
||||
Naming/MethodParameterName:
|
||||
Exclude:
|
||||
- 'engines/dfc_provider/lib/dfc_provider/catalog_item.rb'
|
||||
|
||||
# Offense count: 60
|
||||
# Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
|
||||
# AllowedMethods: call
|
||||
# WaywardPredicates: nonzero?
|
||||
Naming/PredicateMethod:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/product_import_controller.rb'
|
||||
- 'app/controllers/api/v0/order_cycles_controller.rb'
|
||||
- 'app/controllers/spree/admin/overview_controller.rb'
|
||||
- 'app/controllers/spree/admin/payments_controller.rb'
|
||||
- 'app/controllers/voucher_adjustments_controller.rb'
|
||||
- 'app/forms/enterprise_fees_bulk_update.rb'
|
||||
- 'app/forms/schedule_form.rb'
|
||||
- 'app/helpers/spree/orders_helper.rb'
|
||||
- 'app/models/concerns/variant_stock.rb'
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/enterprise_fee.rb'
|
||||
- 'app/models/invoice/data_presenter.rb'
|
||||
- 'app/models/order_cycle.rb'
|
||||
- 'app/models/product_import/entry_processor.rb'
|
||||
- 'app/models/product_import/entry_validator.rb'
|
||||
- 'app/models/spree/order.rb'
|
||||
- 'app/models/spree/order_contents.rb'
|
||||
- 'app/models/spree/payment.rb'
|
||||
- 'app/models/spree/payment/processing.rb'
|
||||
- 'app/models/spree/state_change.rb'
|
||||
- 'app/models/spree/user.rb'
|
||||
- 'app/reflexes/admin/orders_reflex.rb'
|
||||
- 'app/serializers/api/admin/for_order_cycle/enterprise_serializer.rb'
|
||||
- 'app/serializers/api/admin/index_enterprise_serializer.rb'
|
||||
- 'app/serializers/api/admin/index_order_cycle_serializer.rb'
|
||||
- 'app/serializers/api/admin/order_cycle_serializer.rb'
|
||||
- 'app/serializers/api/admin/order_serializer.rb'
|
||||
- 'app/serializers/api/admin/schedule_serializer.rb'
|
||||
- 'app/serializers/api/admin/subscription_line_item_serializer.rb'
|
||||
- 'app/serializers/api/admin/user_serializer.rb'
|
||||
- 'app/serializers/api/admin/variant_serializer.rb'
|
||||
- 'app/serializers/api/enterprise_shopfront_serializer.rb'
|
||||
- 'app/serializers/api/enterprise_thin_serializer.rb'
|
||||
- 'app/serializers/api/order_serializer.rb'
|
||||
- 'app/serializers/api/uncached_enterprise_serializer.rb'
|
||||
- 'app/services/cart_service.rb'
|
||||
- 'app/services/orders/fetch_adjustments_service.rb'
|
||||
- 'app/services/orders/workflow_service.rb'
|
||||
- 'app/services/sets/model_set.rb'
|
||||
- 'app/services/sets/order_cycle_set.rb'
|
||||
- 'app/services/sets/product_set.rb'
|
||||
- 'engines/dfc_provider/app/controllers/dfc_provider/addresses_controller.rb'
|
||||
- 'lib/open_food_network/order_cycle_form_applicator.rb'
|
||||
- 'lib/open_food_network/order_cycle_permissions.rb'
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_order.rb'
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_producer.rb'
|
||||
- 'lib/tasks/data/check_invalid_address_used.rake'
|
||||
|
||||
# Offense count: 3
|
||||
# Configuration parameters: EnforcedStyle, AllowedIdentifiers, AllowedPatterns, ForbiddenIdentifiers, ForbiddenPatterns.
|
||||
# SupportedStyles: snake_case, camelCase
|
||||
Naming/VariableName:
|
||||
Exclude:
|
||||
- 'engines/dfc_provider/lib/dfc_provider/catalog_item.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/FindByOrAssignmentMemoization:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/customers_controller.rb'
|
||||
- 'app/controllers/admin/resource_controller.rb'
|
||||
- 'app/controllers/api/v0/enterprise_fees_controller.rb'
|
||||
- 'app/controllers/api/v0/order_cycles_controller.rb'
|
||||
- 'lib/stripe/account_connector.rb'
|
||||
|
||||
# Offense count: 32
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/OrderArguments:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/enterprise_fees_controller.rb'
|
||||
- 'app/controllers/admin/enterprises_controller.rb'
|
||||
- 'app/controllers/admin/order_cycles_controller.rb'
|
||||
- 'app/controllers/admin/product_import_controller.rb'
|
||||
- 'app/controllers/api/v0/states_controller.rb'
|
||||
- 'app/controllers/spree/admin/overview_controller.rb'
|
||||
- 'app/controllers/spree/admin/products_controller.rb'
|
||||
- 'app/helpers/enterprises_helper.rb'
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/enterprise_group.rb'
|
||||
- 'app/models/enterprise_relationship_permission.rb'
|
||||
- 'app/models/order_cycle.rb'
|
||||
- 'app/models/product_import/product_importer.rb'
|
||||
- 'app/models/schedule.rb'
|
||||
- 'app/models/spree/country.rb'
|
||||
- 'app/models/spree/order.rb'
|
||||
- 'app/models/spree/shipping_rate.rb'
|
||||
- 'app/models/spree/user.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
- 'app/models/subscription_line_item.rb'
|
||||
- 'app/models/tag_rule.rb'
|
||||
- 'app/models/variant_override.rb'
|
||||
- 'lib/open_food_network/address_finder.rb'
|
||||
- 'spec/services/orders/generate_invoice_service_spec.rb'
|
||||
- 'spec/system/admin/order_cycles/simple_spec.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Rails/Presence:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/enterprises_controller.rb'
|
||||
- 'app/models/spree/product.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: Severity.
|
||||
Rails/RedirectBackOrTo:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/order_cycles_controller.rb'
|
||||
- 'app/controllers/locales_controller.rb'
|
||||
- 'app/controllers/spree/admin/invoices_controller.rb'
|
||||
- 'app/controllers/spree/admin/orders_controller.rb'
|
||||
- 'app/controllers/spree/admin/return_authorizations_controller.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: TransactionMethods.
|
||||
Rails/TransactionExitStatement:
|
||||
Exclude:
|
||||
- 'app/services/place_proxy_order.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/ArrayIntersect:
|
||||
Exclude:
|
||||
- 'app/models/spree/ability.rb'
|
||||
- 'app/models/spree/variant.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/BitwisePredicate:
|
||||
Exclude:
|
||||
- 'app/helpers/admin/enterprises_helper.rb'
|
||||
|
||||
# Offense count: 23
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: EnforcedStyle, EnforcedStyleForClasses, EnforcedStyleForModules.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: nested, compact
|
||||
# SupportedStylesForClasses: ~, nested, compact
|
||||
# SupportedStylesForModules: ~, nested, compact
|
||||
Style/ClassAndModuleChildren:
|
||||
Exclude:
|
||||
- 'app/models/calculator/flat_percent_per_item.rb'
|
||||
@@ -404,33 +217,13 @@ Style/ClassAndModuleChildren:
|
||||
- 'lib/open_food_network/locking.rb'
|
||||
- 'spec/models/spree/payment_method_spec.rb'
|
||||
|
||||
# Offense count: 14
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/CollectionQuerying:
|
||||
Exclude:
|
||||
- 'app/controllers/spree/credit_cards_controller.rb'
|
||||
- 'app/models/product_import/product_importer.rb'
|
||||
- 'app/models/product_import/spreadsheet_entry.rb'
|
||||
- 'app/models/spree/order.rb'
|
||||
- 'app/models/spree/order_inventory.rb'
|
||||
- 'app/models/spree/payment_method.rb'
|
||||
- 'app/models/spree/user.rb'
|
||||
- 'app/models/stripe_account.rb'
|
||||
- 'app/services/order_cycles/warning_service.rb'
|
||||
- 'lib/reporting/report_renderer.rb'
|
||||
- 'lib/tasks/sample_data.rake'
|
||||
|
||||
# Offense count: 2
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/HashSlice:
|
||||
Exclude:
|
||||
- 'app/services/product_filters.rb'
|
||||
- 'lib/reporting/report_row_builder.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Offense count: 4
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/MapToHash:
|
||||
Exclude:
|
||||
- 'lib/reporting/report_query_template.rb'
|
||||
- 'lib/reporting/report_row_builder.rb'
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/fee_summary.rb'
|
||||
- 'lib/tasks/sample_data/user_factory.rb'
|
||||
|
||||
# Offense count: 38
|
||||
@@ -461,22 +254,3 @@ Style/OptionalBooleanParameter:
|
||||
- 'engines/order_management/app/services/order_management/stock/estimator.rb'
|
||||
- 'lib/spree/core/controller_helpers/order.rb'
|
||||
- 'spec/support/request/web_helper.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/RedundantFormat:
|
||||
Exclude:
|
||||
- 'spec/models/product_importer_spec.rb'
|
||||
- 'spec/requests/checkout/stripe_sca_spec.rb'
|
||||
- 'spec/system/consumer/account/cards_spec.rb'
|
||||
|
||||
# Offense count: 8
|
||||
# Configuration parameters: Max.
|
||||
Style/SafeNavigationChainLength:
|
||||
Exclude:
|
||||
- 'app/controllers/concerns/extra_fields.rb'
|
||||
- 'app/services/customer_syncer.rb'
|
||||
- 'app/services/fdc_offer_broker.rb'
|
||||
- 'engines/dfc_provider/app/services/dfc_catalog.rb'
|
||||
- 'engines/dfc_provider/app/services/image_builder.rb'
|
||||
- 'engines/dfc_provider/app/services/quantitative_value_builder.rb'
|
||||
|
||||
@@ -1 +1 @@
|
||||
3.2.9
|
||||
3.1.4
|
||||
|
||||
19
.scss-lint.yml
Normal file
19
.scss-lint.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
scss_files: 'app/assets/stylesheets/**/*.css.scss'
|
||||
|
||||
exclude: 'app/assets/stylesheets/shared/**'
|
||||
|
||||
linters:
|
||||
ImportantRule:
|
||||
enabled: false
|
||||
VendorPrefix:
|
||||
enabled: false
|
||||
LeadingZero:
|
||||
enabled: false
|
||||
PropertySortOrder:
|
||||
enabled: false
|
||||
StringQuotes:
|
||||
enabled: false
|
||||
DeclarationOrder:
|
||||
enabled: false
|
||||
NestingDepth:
|
||||
enabled: false
|
||||
@@ -1,4 +0,0 @@
|
||||
# .secrets file define github secrets value locally
|
||||
DEPENDABOT_PR_APP_ID=123456
|
||||
DEPENDABOT_PR_APP_INSTALLATION_ID=123456
|
||||
DEPENDABOT_PR_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n....\n-----END RSA PRIVATE KEY-----"
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM ruby:3.2.9-alpine3.19 AS base
|
||||
FROM ruby:3.1.4-alpine3.19 AS base
|
||||
ENV LANG=C.UTF-8 \
|
||||
LC_ALL=C.UTF-8 \
|
||||
TZ=Europe/London \
|
||||
|
||||
@@ -73,7 +73,7 @@ To login as the default user, use:
|
||||
email: ofn@example.com
|
||||
password: ofn123
|
||||
|
||||
See [Locale and sample data] about loading data.
|
||||
Seee [Locale and sample data] about loading data.
|
||||
|
||||
### Testing
|
||||
|
||||
|
||||
22
Gemfile
22
Gemfile
@@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
source 'https://gem.coop'
|
||||
source 'https://rubygems.org'
|
||||
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
|
||||
|
||||
ruby File.read('.ruby-version').chomp
|
||||
@@ -14,19 +14,16 @@ gem "active_storage_validations"
|
||||
gem "aws-sdk-s3", require: false
|
||||
gem "image_processing"
|
||||
|
||||
gem 'activemerchant'
|
||||
gem 'angular-rails-templates'
|
||||
gem 'activemerchant', '>= 1.78.0'
|
||||
gem 'angular-rails-templates', '>= 0.3.0'
|
||||
gem 'ransack', '~> 4.1.0'
|
||||
gem 'responders'
|
||||
gem 'webpacker', '~> 5'
|
||||
|
||||
# Indirect dependency but we access it directly in JS specs.
|
||||
# It turns out to be hard to upgrade but please do if you can.
|
||||
gem 'sprockets', '~> 3.7'
|
||||
|
||||
gem 'i18n'
|
||||
gem 'i18n-js', '~> 3.9.0'
|
||||
gem 'rails-i18n'
|
||||
gem 'rails_safe_tasks', '~> 1.0'
|
||||
|
||||
gem "activerecord-import"
|
||||
gem "db2fog", github: "openfoodfoundation/db2fog", branch: "rails-7"
|
||||
@@ -43,7 +40,7 @@ gem 'web', path: './engines/web'
|
||||
|
||||
gem "activerecord-postgresql-adapter"
|
||||
gem "arel-helpers", "~> 2.12"
|
||||
gem "pg"
|
||||
gem "pg", "~> 1.2.3"
|
||||
|
||||
gem 'acts_as_list', '1.0.4'
|
||||
gem 'cancancan', '~> 1.15.0'
|
||||
@@ -57,7 +54,7 @@ gem 'state_machines-activerecord'
|
||||
gem 'stringex', '~> 2.8.5', require: false
|
||||
|
||||
gem 'paypal-sdk-merchant', '1.117.2'
|
||||
gem 'stripe', '~> 13'
|
||||
gem 'stripe'
|
||||
|
||||
gem 'devise'
|
||||
gem 'devise-encryptable'
|
||||
@@ -185,19 +182,16 @@ group :test do
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem 'debugger-linecache'
|
||||
gem 'foreman'
|
||||
gem 'haml_lint', require: false
|
||||
gem 'i18n-tasks'
|
||||
gem 'listen'
|
||||
gem 'pry'
|
||||
gem 'pry', '~> 0.13.0'
|
||||
gem 'query_count'
|
||||
gem 'rails-erd'
|
||||
gem 'rubocop'
|
||||
gem 'rubocop-capybara'
|
||||
gem 'rubocop-factory_bot'
|
||||
gem 'rubocop-rails'
|
||||
gem 'rubocop-rspec'
|
||||
gem 'rubocop-rspec_rails'
|
||||
gem 'spring'
|
||||
gem 'spring-commands-rspec'
|
||||
gem 'spring-commands-rubocop'
|
||||
|
||||
616
Gemfile.lock
616
Gemfile.lock
File diff suppressed because it is too large
Load Diff
@@ -11,9 +11,6 @@ angular.module("admin.customers").controller "customersCtrl", ($scope, $q, $filt
|
||||
$scope.confirmRefresh = (event) ->
|
||||
event.preventDefault() unless pendingChanges.unsavedCount() == 0 || confirm(t("unsaved_changes_warning"))
|
||||
|
||||
$scope.hasUnsavedChanges = ->
|
||||
pendingChanges.yes()
|
||||
|
||||
$scope.$watch "shop_id", ->
|
||||
if $scope.shop_id?
|
||||
CurrentShop.shop = $filter('filter')($scope.shops, {id: parseInt($scope.shop_id)}, true)[0]
|
||||
|
||||
@@ -6,6 +6,7 @@ angular.module("admin.enterprises", [
|
||||
"admin.side_menu",
|
||||
"admin.taxons",
|
||||
'admin.indexUtils',
|
||||
'admin.tagRules',
|
||||
'admin.dropdown',
|
||||
'ngSanitize']
|
||||
)
|
||||
|
||||
@@ -4,16 +4,15 @@ angular.module("admin.indexUtils").directive "objForUpdate", (switchClass, pendi
|
||||
type: "@objForUpdate"
|
||||
attr: "@attrForUpdate"
|
||||
link: (scope, element, attrs) ->
|
||||
scope.savedValue = scope.object()[scope.attr] || ""
|
||||
scope.savedValue = scope.object()[scope.attr]
|
||||
|
||||
scope.$watch "object().#{scope.attr}", (value) ->
|
||||
strValue = value || ""
|
||||
if strValue == scope.savedValue
|
||||
if value == scope.savedValue
|
||||
pendingChanges.remove(scope.object().id, scope.attr)
|
||||
scope.clear()
|
||||
else
|
||||
scope.pending()
|
||||
addPendingChange(scope.attr, strValue)
|
||||
addPendingChange(scope.attr, value ? "")
|
||||
|
||||
scope.reset = (value) ->
|
||||
scope.savedValue = value
|
||||
|
||||
@@ -16,10 +16,7 @@ angular.module("admin.indexUtils").factory "pendingChanges", ($q, resources, Sta
|
||||
remove: (id, attr) =>
|
||||
if @pendingChanges.hasOwnProperty("#{id}")
|
||||
delete @pendingChanges["#{id}"]["#{attr}"]
|
||||
|
||||
if @changeCount( @pendingChanges["#{id}"] ) < 1
|
||||
delete @pendingChanges["#{id}"]
|
||||
StatusMessage.clear()
|
||||
delete @pendingChanges["#{id}"] if @changeCount( @pendingChanges["#{id}"] ) < 1
|
||||
|
||||
submitAll: (form=null) =>
|
||||
all = []
|
||||
@@ -50,8 +47,5 @@ angular.module("admin.indexUtils").factory "pendingChanges", ($q, resources, Sta
|
||||
unsavedCount: ->
|
||||
Object.keys(@pendingChanges).length
|
||||
|
||||
yes: ->
|
||||
@unsavedCount() > 0
|
||||
|
||||
changeCount: (objectChanges) ->
|
||||
Object.keys(objectChanges).length
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("admin.indexUtils").factory "switchClass", ($timeout, StatusMessage) ->
|
||||
angular.module("admin.indexUtils").factory "switchClass", ($timeout) ->
|
||||
return (element, classToAdd, removeClasses, timeout) ->
|
||||
$timeout.cancel element.timeout if element.timeout
|
||||
element.removeClass className for className in removeClasses
|
||||
@@ -7,6 +7,4 @@ angular.module("admin.indexUtils").factory "switchClass", ($timeout, StatusMessa
|
||||
if timeout && intRegex.test(timeout)
|
||||
element.timeout = $timeout(->
|
||||
element.removeClass classToAdd
|
||||
StatusMessage.clear()
|
||||
, timeout, true)
|
||||
element
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
angular.module("admin.tagRules").controller "TagRulesCtrl", ($scope, $http, $filter, enterprise) ->
|
||||
$scope.tagGroups = enterprise.tag_groups
|
||||
$scope.defaultTagGroup = enterprise.default_tag_group
|
||||
|
||||
$scope.visibilityOptions = [ { id: "visible", name: t('js.tag_rules.visible') }, { id: "hidden", name: t('js.tag_rules.not_visible') } ]
|
||||
|
||||
$scope.updateRuleCounts = ->
|
||||
index = $scope.defaultTagGroup.rules.length
|
||||
for tagGroup in $filter('orderBy')($scope.tagGroups, 'position')
|
||||
tagGroup.startIndex = index
|
||||
index = index + tagGroup.rules.length
|
||||
|
||||
$scope.updateRuleCounts()
|
||||
|
||||
$scope.updateTagsRulesFor = (tagGroup) ->
|
||||
for tagRule in tagGroup.rules
|
||||
tagRule.preferred_customer_tags = (tag.text for tag in tagGroup.tags).join(",")
|
||||
|
||||
$scope.addNewRuleTo = (tagGroup, ruleType) ->
|
||||
newRule =
|
||||
id: null
|
||||
is_default: tagGroup == $scope.defaultTagGroup
|
||||
preferred_customer_tags: (tag.text for tag in tagGroup.tags).join(",")
|
||||
type: "TagRule::#{ruleType}"
|
||||
switch ruleType
|
||||
when "FilterShippingMethods"
|
||||
newRule.peferred_shipping_method_tags = []
|
||||
newRule.preferred_matched_shipping_methods_visibility = "visible"
|
||||
when "FilterPaymentMethods"
|
||||
newRule.peferred_payment_method_tags = []
|
||||
newRule.preferred_matched_payment_methods_visibility = "visible"
|
||||
when "FilterProducts"
|
||||
newRule.peferred_variant_tags = []
|
||||
newRule.preferred_matched_variants_visibility = "visible"
|
||||
when "FilterOrderCycles"
|
||||
newRule.peferred_exchange_tags = []
|
||||
newRule.preferred_matched_order_cycles_visibility = "visible"
|
||||
tagGroup.rules.push(newRule)
|
||||
$scope.updateRuleCounts()
|
||||
|
||||
$scope.addNewTag = ->
|
||||
$scope.tagGroups.push { tags: [], rules: [], position: $scope.tagGroups.length + 1 }
|
||||
|
||||
$scope.deleteTagRule = (tagGroup, tagRule) ->
|
||||
index = tagGroup.rules.indexOf(tagRule)
|
||||
return unless index >= 0
|
||||
if tagRule.id is null
|
||||
tagGroup.rules.splice(index, 1)
|
||||
$scope.updateRuleCounts()
|
||||
else
|
||||
if confirm("Are you sure?")
|
||||
$http
|
||||
method: "DELETE"
|
||||
url: "/admin/enterprises/#{enterprise.id}/tag_rules/#{tagRule.id}.json"
|
||||
.then ->
|
||||
tagGroup.rules.splice(index, 1)
|
||||
$scope.updateRuleCounts()
|
||||
$scope.enterprise_form.$setDirty()
|
||||
@@ -0,0 +1,11 @@
|
||||
angular.module("admin.tagRules").directive "invertNumber", ->
|
||||
restrict: "A"
|
||||
require: "ngModel"
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
ngModel.$parsers.push (viewValue) ->
|
||||
return -parseInt(viewValue) unless isNaN(parseInt(viewValue))
|
||||
viewValue
|
||||
|
||||
ngModel.$formatters.push (modelValue) ->
|
||||
return -parseInt(modelValue) unless isNaN(parseInt(modelValue))
|
||||
modelValue
|
||||
@@ -0,0 +1,26 @@
|
||||
angular.module("admin.tagRules").directive 'newTagRuleDialog', ($rootScope, $compile, $templateCache, DialogDefaults, ruleTypes) ->
|
||||
restrict: 'A'
|
||||
scope:
|
||||
tagGroup: '='
|
||||
addNewRuleTo: '='
|
||||
link: (scope, element, attr) ->
|
||||
# Compile modal template
|
||||
template = $compile($templateCache.get('admin/new_tag_rule_dialog.html'))(scope)
|
||||
|
||||
scope.ruleTypes = ruleTypes
|
||||
|
||||
scope.ruleType = scope.ruleTypes[0].id
|
||||
|
||||
# Set Dialog options
|
||||
template.dialog(DialogDefaults)
|
||||
|
||||
# Link opening of dialog to click event on element
|
||||
element.bind 'click', (e) ->
|
||||
template.dialog('open')
|
||||
$rootScope.$evalAsync()
|
||||
|
||||
scope.addRule = (tagGroup, ruleType) ->
|
||||
scope.addNewRuleTo(tagGroup, ruleType)
|
||||
template.dialog('close')
|
||||
$rootScope.$evalAsync()
|
||||
return
|
||||
@@ -0,0 +1,41 @@
|
||||
angular.module("admin.tagRules").directive "tagRule", ->
|
||||
restrict: "C"
|
||||
templateUrl: "admin/tag_rules/tag_rule.html"
|
||||
link: (scope, element, attrs) ->
|
||||
scope.opt =
|
||||
"TagRule::FilterShippingMethods":
|
||||
textTop: t('js.admin.tag_rules.shipping_method_tagged_top')
|
||||
textBottom: t('js.admin.tag_rules.shipping_method_tagged_bottom')
|
||||
taggable: "shipping_method"
|
||||
tagsAttr: "shipping_method_tags"
|
||||
tagListAttr: "preferred_shipping_method_tags"
|
||||
inputTemplate: "admin/tag_rules/filter_shipping_methods_input.html"
|
||||
tagListFor: (rule) ->
|
||||
rule.preferred_shipping_method_tags
|
||||
"TagRule::FilterPaymentMethods":
|
||||
textTop: t('js.admin.tag_rules.payment_method_tagged_top')
|
||||
textBottom: t('js.admin.tag_rules.payment_method_tagged_bottom')
|
||||
taggable: "payment_method"
|
||||
tagsAttr: "payment_method_tags"
|
||||
tagListAttr: "preferred_payment_method_tags"
|
||||
inputTemplate: "admin/tag_rules/filter_payment_methods_input.html"
|
||||
tagListFor: (rule) ->
|
||||
rule.preferred_payment_method_tags
|
||||
"TagRule::FilterOrderCycles":
|
||||
textTop: t('js.admin.tag_rules.order_cycle_tagged_top')
|
||||
textBottom: t('js.admin.tag_rules.order_cycle_tagged_bottom')
|
||||
taggable: "exchange"
|
||||
tagsAttr: "exchange_tags"
|
||||
tagListAttr: "preferred_exchange_tags"
|
||||
inputTemplate: "admin/tag_rules/filter_order_cycles_input.html"
|
||||
tagListFor: (rule) ->
|
||||
rule.preferred_exchange_tags
|
||||
"TagRule::FilterProducts":
|
||||
textTop: t('js.admin.tag_rules.inventory_tagged_top')
|
||||
textBottom: t('js.admin.tag_rules.inventory_tagged_bottom')
|
||||
taggable: "variant"
|
||||
tagsAttr: "variant_tags"
|
||||
tagListAttr: "preferred_variant_tags"
|
||||
inputTemplate: "admin/tag_rules/filter_products_input.html"
|
||||
tagListFor: (rule) ->
|
||||
rule.preferred_variant_tags
|
||||
@@ -1,6 +1,6 @@
|
||||
angular.module('Darkswarm').directive "activeTableHubLink", (CurrentHub, CurrentOrder) ->
|
||||
# Change the text of the hub link based on CurrentHub
|
||||
# To be used with ofnChangeHub
|
||||
# To be used with ofnEmptiesCart
|
||||
# Takes "change" and "shop" as text string attributes
|
||||
restrict: "A"
|
||||
scope:
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
angular.module('Darkswarm').directive "darkerBackground", ->
|
||||
restrict: "A"
|
||||
link: (scope, elm, attr)->
|
||||
toggleClass = (value) ->
|
||||
elm.closest('.page-view').toggleClass("with-darker-background", value)
|
||||
|
||||
toggleClass(true)
|
||||
|
||||
# if an OrderCycle is selected, disable darker background
|
||||
scope.$watch 'order_cycle.order_cycle_id', (newvalue, oldvalue) ->
|
||||
toggleClass(false) if newvalue
|
||||
@@ -0,0 +1,14 @@
|
||||
# Allows disabling of link buttons via disabled attribute.
|
||||
# This is normally ignored, ie the link appears disabled but is still clickable.
|
||||
|
||||
angular.module('Darkswarm').directive "disableDynamically", ->
|
||||
restrict: 'A'
|
||||
|
||||
link: (scope, element, attrs) ->
|
||||
element.on 'click', (e) ->
|
||||
if attrs.disabled
|
||||
e.preventDefault()
|
||||
return
|
||||
|
||||
scope.$on "$destroy", ->
|
||||
element.off("click")
|
||||
@@ -0,0 +1,7 @@
|
||||
angular.module('Darkswarm').directive "ofnInlineAlert", ->
|
||||
restrict: 'A'
|
||||
scope: true
|
||||
link: (scope, elem, attrs) ->
|
||||
scope.visible = true
|
||||
scope.close = ->
|
||||
scope.visible = false
|
||||
@@ -0,0 +1,21 @@
|
||||
angular.module('Darkswarm').directive "ofnPageAlert", ($timeout) ->
|
||||
restrict: 'A'
|
||||
scope: true
|
||||
link: (scope, elem, attrs) ->
|
||||
moveSelectors = [".off-canvas-wrap .inner-wrap",
|
||||
".off-canvas-wrap .inner-wrap .fixed",
|
||||
".off-canvas-fixed .top-bar",
|
||||
".off-canvas-fixed ofn-flash",
|
||||
".off-canvas-fixed nav.tab-bar",
|
||||
".off-canvas-fixed .page-alert"]
|
||||
|
||||
container_elems = $(moveSelectors.join(", "))
|
||||
|
||||
# Wait a moment after page load before showing the alert. Otherwise we often miss the
|
||||
# start of the animation.
|
||||
$timeout ->
|
||||
container_elems.addClass("move-up")
|
||||
, 1000
|
||||
|
||||
scope.close = ->
|
||||
container_elems.removeClass("move-up")
|
||||
@@ -0,0 +1,10 @@
|
||||
#new-tag-rule-dialog
|
||||
.text-normal.margin-bottom-30.text-center
|
||||
{{ 'js.admin.new_tag_rule_dialog.select_rule_type' | t }}
|
||||
|
||||
.text-center.margin-bottom-30
|
||||
-# %select.fullwidth{ 'select2-min-search' => 5, 'ng-model' => 'newRuleType', 'ng-options' => 'ruleType.id as ruleType.name for ruleType in availableRuleTypes' }
|
||||
%input.ofn-select2.fullwidth{ id: 'rule_type_selector', data: "ruleTypes", "min-search": "5", "ng-model": "ruleType" }
|
||||
|
||||
.text-center
|
||||
%input.button.red.icon-plus{ type: 'button', value: "{{ 'js.admin.new_tag_rule_dialog.add_rule' | t }}", "ng-click": 'addRule(tagGroup, ruleType)' }
|
||||
@@ -3,4 +3,4 @@
|
||||
%span.text-normal
|
||||
{{ 'admin.tags' | t }}
|
||||
%br
|
||||
%tags-with-translation.fullwidth{ object: 'object', form: 'order_cycle_form', id: 'tags_with_translation'}
|
||||
%tags-with-translation.fullwidth{ object: 'object' }
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
%div
|
||||
%input{ type: "number", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_calculator_attributes_preferred_flat_percent", min: -100, max: 100, "invert-number": true, "ng-model": "rule.calculator.preferred_flat_percent" }
|
||||
%span.text-normal %
|
||||
@@ -0,0 +1,5 @@
|
||||
%div
|
||||
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_order_cycles_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_order_cycles_visibility]", data: 'visibilityOptions', "min-search": 5, "ng-model": "rule.preferred_matched_order_cycles_visibility", "ng-if": "!rule.is_default" }
|
||||
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_order_cycles_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_order_cycles_visibility]", "ng-value": "'hidden'", "ng-if": "rule.is_default" }
|
||||
%span.text-normal{ "ng-if": "rule.is_default" }
|
||||
=t(:not_visible)
|
||||
@@ -0,0 +1,5 @@
|
||||
%div
|
||||
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_payment_methods_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_payment_methods_visibility]", data: 'visibilityOptions', "min-search": 5, "ng-model": "rule.preferred_matched_payment_methods_visibility", "ng-if": "!rule.is_default" }
|
||||
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_payment_methods_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_payment_methods_visibility]", "ng-value": "'hidden'", "ng-if": "rule.is_default" }
|
||||
%span.text-normal{ "ng-if": "rule.is_default" }
|
||||
= t(:not_visible)
|
||||
@@ -0,0 +1,5 @@
|
||||
%div
|
||||
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_variants_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_variants_visibility]", data: 'visibilityOptions', "min-search": 5, "ng-model": "rule.preferred_matched_variants_visibility", "ng-if": "!rule.is_default" }
|
||||
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_variants_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_variants_visibility]", "ng-value": "'hidden'", "ng-if": "rule.is_default" }
|
||||
%span.text-normal{ "ng-if": "rule.is_default" }
|
||||
= t(:not_visible)
|
||||
@@ -0,0 +1,6 @@
|
||||
%div
|
||||
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_shipping_methods_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_shipping_methods_visibility]", data: 'visibilityOptions', "min-search": 5, "ng-model": "rule.preferred_matched_shipping_methods_visibility", "ng-if": "!rule.is_default" }
|
||||
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_shipping_methods_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_shipping_methods_visibility]", "ng-value": "'hidden'", "ng-if": "rule.is_default" }
|
||||
%span.text-normal{ "ng-if": "rule.is_default" }
|
||||
= t(:not_visible)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
%div{ id: "tr_{{tagGroup.startIndex + $index}}" }
|
||||
%table
|
||||
%colgroup
|
||||
%col.text{ width: "35%" }
|
||||
%col.inputs{ width: "55%" }
|
||||
%col.actions{ width: "10%" }
|
||||
%tr
|
||||
%td
|
||||
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_id", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][id]", "ng-value": "rule.id" }
|
||||
|
||||
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_type", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][type]", "ng-value": "rule.type" }
|
||||
|
||||
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_priority", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][priority]", "ng-value": "tagGroup.startIndex + $index" }
|
||||
|
||||
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_is_default", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][is_default]", "ng-value": "rule.is_default" }
|
||||
|
||||
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_customer_tags", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_customer_tags]", "ng-value": "rule.preferred_customer_tags" }
|
||||
|
||||
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_{{opt[rule.type].taggable}}_tags", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_{{opt[rule.type].taggable}}_tags]", "ng-value": "opt[rule.type].tagListFor(rule)" }
|
||||
|
||||
%span.text-normal {{ opt[rule.type].textTop }}
|
||||
%td
|
||||
%tags-with-translation{ object: "rule", max: 1, "tags-attr" => "{{opt[rule.type].tagsAttr}}", "tag-list-attr" => "{{opt[rule.type].tagListAttr}}" }
|
||||
%td.actions{ rowspan: 2 }
|
||||
%a{ class: "delete-tag-rule icon-trash no-text", "ng-click": "deleteTagRule(tagGroup || defaultTagGroup, rule)" }
|
||||
%tr
|
||||
%td
|
||||
%span.text-normal {{ opt[rule.type].textBottom }}
|
||||
%td
|
||||
%div{ "ng-include": "opt[rule.type].inputTemplate" }
|
||||
|
||||
%hr
|
||||
@@ -12,7 +12,7 @@
|
||||
.row
|
||||
.columns.small-12
|
||||
%a.cta-hub{"ng-repeat" => "hub in enterprise.hubs | filter:{id: '!'+enterprise.id} | orderBy:'-active'",
|
||||
"ng-href" => "{{::hub.path}}#/shop_panel",
|
||||
"ng-href" => "{{::hub.path}}#/shop_panel", "ofn-empties-cart" => "hub",
|
||||
"ng-class" => "::{primary: hub.active, secondary: !hub.active}",
|
||||
"ng-click" => "$close()",
|
||||
"ofn-change-hub" => "hub"}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AddTagRuleModalComponent < ModalComponent
|
||||
def initialize(id:, tag_rule_types:, current_index:, div_id:, is_default: false,
|
||||
customer_tag: "", hidden_field_customer_tag_options: {} )
|
||||
super
|
||||
|
||||
@close_button = false
|
||||
@modal_class = "tiny"
|
||||
|
||||
@tag_rule_types = tag_rule_types
|
||||
@current_index = current_index
|
||||
@div_id = div_id
|
||||
@is_default = is_default
|
||||
@customer_tag = customer_tag
|
||||
@hidden_field_customer_tag_options = hidden_field_customer_tag_options
|
||||
end
|
||||
|
||||
attr_reader :tag_rule_types, :current_index, :div_id, :is_default, :customer_tag,
|
||||
:hidden_field_customer_tag_options
|
||||
end
|
||||
@@ -1,32 +0,0 @@
|
||||
-# as far as I can tell we can't pass content to the parent template while rendering ie: something like :
|
||||
-# = render_parent do
|
||||
-# .something
|
||||
-# my content
|
||||
-# Workarount is to copy the ModalComponent template
|
||||
%div{ id: @id, "data-controller": @data_controller, "data-action": @data_action, "data-modal-instant-value": @instant, **@options }
|
||||
.reveal-modal-bg.fade{ "data-modal-target": "background", "data-action": "click->modal#close" }
|
||||
.reveal-modal.fade.modal-component{ "data-modal-target": "modal", class: @modal_class }
|
||||
#new-tag-rule-dialog{ "data-controller": "add-tag-rule-modal",
|
||||
"data-add-tag-rule-modal-index-value": current_index }
|
||||
|
||||
-# Ideally we would use event to communicate the update of customer tag, but we would need
|
||||
-# the element with "data-controller": "add-tag-rule-modal"
|
||||
-# to be parent of the element with "data-controller": "tag-rule-group-form"
|
||||
-# so it could respond to event generated by "tag-rule-group-form".
|
||||
-# Here we are in the opposite situation so we use a hidden field to store the value of
|
||||
-# the customer tag, so it can be updated by "tag-rule-group-form"
|
||||
= hidden_field_tag "customer_tag", customer_tag, { "data-add-tag-rule-modal-target": "ruleCustomerTag" }.merge(hidden_field_customer_tag_options)
|
||||
.text-normal.margin-bottom-30.text-center
|
||||
= t('components.add_tag_rule_modal.select_rule_type')
|
||||
.text-center.margin-bottom-30
|
||||
= select_tag :rule_type_selector, options_for_select(tag_rule_types), { "data-controller": "tom-select", "data-add-tag-rule-modal-target": "rule", class: "primary no-search" }
|
||||
.text-center
|
||||
%input.button.red.icon-plus{ type: 'button',
|
||||
value: "#{t('components.add_tag_rule_modal.add_rule')}",
|
||||
"data-action": "click->add-tag-rule-modal#add click->modal#close",
|
||||
"data-add-tag-rule-modal-div-id-param": div_id,
|
||||
"data-add-tag-rule-modal-is-default-param": "#{is_default}"}
|
||||
|
||||
- if close_button?
|
||||
.text-center
|
||||
%input{ class: "button icon-plus #{close_button_class}", type: 'button', value: t('js.admin.modals.close'), "data-action": "click->modal#close" }
|
||||
@@ -1,46 +0,0 @@
|
||||
import { Controller } from "stimulus";
|
||||
import showHttpError from "../../webpacker/js/services/show_http_error";
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["rule", "ruleCustomerTag"];
|
||||
static values = { index: Number };
|
||||
|
||||
add({ params }) {
|
||||
const rule_type = this.ruleTarget.value;
|
||||
const index = this.indexValue;
|
||||
const divId = params["divId"];
|
||||
const isDefault = params["isDefault"];
|
||||
const customerTags = this.hasRuleCustomerTagTarget
|
||||
? this.ruleCustomerTagTarget.value
|
||||
: undefined;
|
||||
|
||||
const urlParams = new URLSearchParams();
|
||||
urlParams.append("rule_type", rule_type);
|
||||
urlParams.append("index", index);
|
||||
urlParams.append("div_id", divId);
|
||||
urlParams.append("is_default", isDefault);
|
||||
if (customerTags != undefined) {
|
||||
urlParams.append("customer_tags", customerTags);
|
||||
}
|
||||
|
||||
// fetch from backend
|
||||
fetch(`tag_rules/new?${urlParams}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Accept: "text/vnd.turbo-stream.html",
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
showHttpError(response.status);
|
||||
throw response;
|
||||
}
|
||||
return response.text();
|
||||
})
|
||||
.then((html) => {
|
||||
Turbo.renderStreamMessage(html);
|
||||
this.indexValue = parseInt(index) + 1;
|
||||
})
|
||||
.catch((error) => console.error(error));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
// This controller will be called "example", ie "js-file-name" minus the "_controller.js"
|
||||
// see controller/index.js for more info
|
||||
// This controller will be called "example-component--example", ie "component-subdirectory--js-file-name"
|
||||
import { Controller } from "stimulus";
|
||||
|
||||
export default class extends Controller {}
|
||||
|
||||
@@ -30,7 +30,7 @@ class SearchableDropdownComponent < ViewComponent::Base
|
||||
:aria_label, :other_attrs
|
||||
|
||||
def classes
|
||||
"fullwidth #{'no-input' if remove_search_plugin?}"
|
||||
"fullwidth #{remove_search_plugin? ? 'no-input' : ''}"
|
||||
end
|
||||
|
||||
def data
|
||||
|
||||
@@ -1,29 +1,16 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class TagListInputComponent < ViewComponent::Base
|
||||
def initialize(name:, tags:,
|
||||
# method in a "hidden_field" form helper and is the method used to get a list of tag on the model
|
||||
def initialize(form:, method:, tags:,
|
||||
placeholder: I18n.t("components.tag_list_input.default_placeholder"),
|
||||
only_one: false,
|
||||
aria_label: nil,
|
||||
hidden_field_data_options: {},
|
||||
autocomplete_url: "")
|
||||
@name = name
|
||||
aria_label: nil)
|
||||
@f = form
|
||||
@method = method
|
||||
@tags = tags
|
||||
@placeholder = placeholder
|
||||
@only_one = only_one
|
||||
@aria_label_option = aria_label ? { 'aria-label': aria_label } : {}
|
||||
@hidden_field_data_options = hidden_field_data_options
|
||||
@autocomplete_url = autocomplete_url
|
||||
end
|
||||
|
||||
attr_reader :name, :tags, :placeholder, :only_one, :aria_label_option,
|
||||
:hidden_field_data_options, :autocomplete_url
|
||||
|
||||
private
|
||||
|
||||
def display
|
||||
return "none" if tags.length >= 1 && only_one == true
|
||||
|
||||
"block"
|
||||
end
|
||||
attr_reader :f, :method, :tags, :placeholder, :aria_label_option
|
||||
end
|
||||
|
||||
@@ -1,27 +1,19 @@
|
||||
%div{ "data-controller": "tag-list-input", "data-tag-list-input-only-one-value": "#{only_one}", "data-tag-list-input-url-value": autocomplete_url, "data-action": "autocomplete.change->tag-list-input#addTag" }
|
||||
%div{ "data-controller": "tag-list-input-component--tag-list-input" }
|
||||
.tags-input
|
||||
.tags
|
||||
- # We use display:none instead of hidden field, so changes to the value can be picked up by the bulkFormController
|
||||
= text_field_tag name, tags.join(","), {"data-tag-list-input-target": "tagList", "style": "display: none"}.merge(hidden_field_data_options)
|
||||
%ul.tag-list{"data-tag-list-input-target": "list"}
|
||||
%template{"data-tag-list-input-target": "template"}
|
||||
= f.text_field method.to_sym, value: tags.join(","), "data-tag-list-input-component--tag-list-input-target": "tagList", "style": "display: none"
|
||||
%ul.tag-list{"data-tag-list-input-component--tag-list-input-target": "list"}
|
||||
%template{"data-tag-list-input-component--tag-list-input-target": "template"}
|
||||
%li.tag-item
|
||||
.tag-template
|
||||
%span
|
||||
%a.remove-button{ "data-action": "click->tag-list-input#removeTag" }
|
||||
%a.remove-button{ "data-action": "click->tag-list-input-component--tag-list-input#removeTag" }
|
||||
×
|
||||
- tags.each do |tag|
|
||||
%li.tag-item
|
||||
.tag-template
|
||||
%span=tag
|
||||
%a.remove-button{ "data-action": "click->tag-list-input#removeTag" }
|
||||
%a.remove-button{ "data-action": "click->tag-list-input-component--tag-list-input#removeTag" }
|
||||
×
|
||||
= text_field_tag("variant_add_tag",
|
||||
nil,
|
||||
{ class: "input",
|
||||
placeholder: placeholder,
|
||||
"data-action": "keydown.enter->tag-list-input#keyboardAddTag keyup->tag-list-input#filterInput blur->tag-list-input#onBlur focus->tag-list-input#onInputChange",
|
||||
"data-tag-list-input-target": "input",
|
||||
**aria_label_option,
|
||||
style: "display: #{display};"})
|
||||
%ul.suggestion-list{ "data-tag-list-input-target": "results" , hidden: true }
|
||||
= text_field_tag "variant_add_tag_#{f.object.id}".to_sym, nil, class: "input", placeholder: placeholder, "data-action": "keydown.enter->tag-list-input-component--tag-list-input#addTag keyup->tag-list-input-component--tag-list-input#filterInput", "data-tag-list-input-component--tag-list-input-target": "newTag", **aria_label_option
|
||||
|
||||
@@ -67,35 +67,4 @@
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
ul.suggestion-list {
|
||||
margin-top: 5px;
|
||||
padding: 5px 0;
|
||||
z-index: $tag-drop-down-z-index;
|
||||
width: fit-content;
|
||||
background-color: #fff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
box-shadow: $shadow-dropdown;
|
||||
list-style-type: none;
|
||||
max-height: 280px;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
|
||||
li.suggestion-item {
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
width: stretch;
|
||||
|
||||
&.active,
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background-color: $color-link-visited;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,28 @@
|
||||
import { Autocomplete } from "stimulus-autocomplete";
|
||||
import { Controller } from "stimulus";
|
||||
|
||||
// Extend the stimulus-autocomplete controller, so we can load tag with existing rules
|
||||
// The autocomplete functionality is only loaded if the url value is set
|
||||
// For more informatioon on "stimulus-autocomplete", see:
|
||||
// https://github.com/afcapel/stimulus-autocomplete/tree/main
|
||||
//
|
||||
export default class extends Autocomplete {
|
||||
static targets = ["tagList", "input", "template", "list"];
|
||||
static values = { onlyOne: Boolean };
|
||||
|
||||
connect() {
|
||||
// Don't start autocomplete controller if we don't have an url
|
||||
if (this.urlValue.length == 0) return;
|
||||
|
||||
super.connect();
|
||||
}
|
||||
export default class extends Controller {
|
||||
static targets = ["tagList", "newTag", "template", "list"];
|
||||
|
||||
addTag(event) {
|
||||
const newTagName = this.inputTarget.value.trim().replaceAll(" ", "-");
|
||||
// prevent hotkey form submitting the form (default action for "enter" key)
|
||||
event.preventDefault();
|
||||
|
||||
// Check if tag already exist
|
||||
const newTagName = this.newTagTarget.value.trim();
|
||||
if (newTagName.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if tag already exist
|
||||
const tags = this.tagListTarget.value.split(",");
|
||||
const index = tags.indexOf(newTagName);
|
||||
if (index != -1) {
|
||||
// highlight the value in red
|
||||
this.inputTarget.classList.add("tag-error");
|
||||
this.newTagTarget.classList.add("tag-error");
|
||||
return;
|
||||
}
|
||||
|
||||
// add to tagList
|
||||
if (this.tagListTarget.value == "") {
|
||||
this.tagListTarget.value = newTagName;
|
||||
} else {
|
||||
this.tagListTarget.value = this.tagListTarget.value.concat(`,${newTagName}`);
|
||||
}
|
||||
// manualy dispatch an Input event so the change can get picked up by other controllers
|
||||
this.tagListTarget.dispatchEvent(new InputEvent("input"));
|
||||
this.tagListTarget.value = this.tagListTarget.value.concat(`,${newTagName}`);
|
||||
|
||||
// Create new li component with value
|
||||
const newTagElement = this.templateTarget.content.cloneNode(true);
|
||||
@@ -47,21 +31,7 @@ export default class extends Autocomplete {
|
||||
this.listTarget.appendChild(newTagElement);
|
||||
|
||||
// Clear new tag value
|
||||
this.inputTarget.value = "";
|
||||
|
||||
// hide tag input if limited to one tag
|
||||
if (this.tagListTarget.value.split(",").length == 1 && this.onlyOneValue == true) {
|
||||
this.inputTarget.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
keyboardAddTag(event) {
|
||||
// prevent hotkey form submitting the form (default action for "enter" key)
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
this.addTag();
|
||||
this.newTagTarget.value = "";
|
||||
}
|
||||
|
||||
removeTag(event) {
|
||||
@@ -70,24 +40,19 @@ export default class extends Autocomplete {
|
||||
|
||||
// Remove tag from list
|
||||
const tags = this.tagListTarget.value.split(",");
|
||||
this.tagListTarget.value = tags.filter((tag) => tag != tagName).join(",");
|
||||
this.tagListTarget.value = tags.filter(tag => tag != tagName).join(",");
|
||||
|
||||
// manualy dispatch an Input event so the change gets picked up by the bulk form controller
|
||||
this.tagListTarget.dispatchEvent(new InputEvent("input"));
|
||||
|
||||
// Remove HTML element from the list
|
||||
event.srcElement.parentElement.parentElement.remove();
|
||||
|
||||
// Make sure the tag input is displayed
|
||||
if (this.tagListTarget.value.length == 0) {
|
||||
this.inputTarget.style.display = "block";
|
||||
}
|
||||
}
|
||||
|
||||
filterInput(event) {
|
||||
// clear error class if key is not enter
|
||||
if (event.key !== "Enter") {
|
||||
this.inputTarget.classList.remove("tag-error");
|
||||
this.newTagTarget.classList.remove("tag-error");
|
||||
}
|
||||
|
||||
// Strip comma from tag name
|
||||
@@ -95,53 +60,4 @@ export default class extends Autocomplete {
|
||||
event.srcElement.value = event.srcElement.value.replace(",", "");
|
||||
}
|
||||
}
|
||||
|
||||
// Add tag if we don't have an autocomplete list open
|
||||
onBlur() {
|
||||
// check if we have any autocomplete results
|
||||
if (this.resultsTarget.childElementCount == 0) this.addTag();
|
||||
}
|
||||
|
||||
// Override original to add tag filtering
|
||||
replaceResults(html) {
|
||||
const filteredHtml = this.#filterResults(html);
|
||||
|
||||
// Don't show result if we don't have anything to show
|
||||
if (filteredHtml.length == 0) return;
|
||||
|
||||
super.replaceResults(filteredHtml);
|
||||
}
|
||||
|
||||
// Override original to all empty query, which will return all existing tags
|
||||
onInputChange = () => {
|
||||
if (this.urlValue.length == 0) return;
|
||||
|
||||
if (this.hasHiddenTarget) this.hiddenTarget.value = "";
|
||||
|
||||
const query = this.inputTarget.value.trim();
|
||||
if (query.length >= this.minLengthValue) {
|
||||
this.fetchResults(query);
|
||||
} else {
|
||||
this.hideAndRemoveOptions();
|
||||
}
|
||||
};
|
||||
|
||||
//private
|
||||
|
||||
#filterResults(html) {
|
||||
const existingTags = this.tagListTarget.value.split(",");
|
||||
// Parse the HTML
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(html, "text/html");
|
||||
const lis = doc.getElementsByTagName("li");
|
||||
// Filter
|
||||
let filteredHtml = "";
|
||||
for (let li of lis) {
|
||||
if (!existingTags.includes(li.dataset.autocompleteValue)) {
|
||||
filteredHtml += li.outerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
return filteredHtml;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class TagRuleFormComponent < ViewComponent::Base
|
||||
def initialize(rule:, index:, customer_tags: "",
|
||||
hidden_field_customer_tag_options: {})
|
||||
@rule = rule
|
||||
@index = index
|
||||
@customer_tags = customer_tags
|
||||
@hidden_field_customer_tag_options = hidden_field_customer_tag_options
|
||||
end
|
||||
|
||||
attr_reader :rule, :index, :customer_tags, :hidden_field_customer_tag_options
|
||||
|
||||
private
|
||||
|
||||
def element_name(name)
|
||||
"enterprise[tag_rules_attributes][#{index}][#{name}]"
|
||||
end
|
||||
|
||||
def rule_data # rubocop:disable Metrics/MethodLength
|
||||
case rule.type
|
||||
when "TagRule::FilterShippingMethods"
|
||||
{
|
||||
text_top: t('components.tag_rule_form.tag_rules.shipping_method_tagged_top'),
|
||||
text_bottom: t('components.tag_rule_form.tag_rules.shipping_method_tagged_bottom'),
|
||||
taggable: "shipping_method",
|
||||
visibility_field: "preferred_matched_shipping_methods_visibility",
|
||||
}
|
||||
when "TagRule::FilterPaymentMethods"
|
||||
{
|
||||
text_top: t('components.tag_rule_form.tag_rules.payment_method_tagged_top'),
|
||||
text_bottom: t('components.tag_rule_form.tag_rules.payment_method_tagged_bottom'),
|
||||
taggable: "payment_method",
|
||||
visibility_field: "preferred_matched_payment_methods_visibility",
|
||||
}
|
||||
when "TagRule::FilterOrderCycles"
|
||||
{
|
||||
text_top: t('components.tag_rule_form.tag_rules.order_cycle_tagged_top'),
|
||||
text_bottom: t('components.tag_rule_form.tag_rules.order_cycle_tagged_bottom'),
|
||||
taggable: "exchange",
|
||||
visibility_field: "preferred_matched_order_cycles_visibility",
|
||||
}
|
||||
when "TagRule::FilterProducts"
|
||||
{
|
||||
text_top: t('components.tag_rule_form.tag_rules.inventory_tagged_top'),
|
||||
text_bottom: t('components.tag_rule_form.tag_rules.inventory_tagged_bottom'),
|
||||
taggable: "variant",
|
||||
visibility_field: "preferred_matched_variants_visibility",
|
||||
}
|
||||
when "TagRule::FilterVariants"
|
||||
{
|
||||
text_top: t('components.tag_rule_form.tag_rules.variant_tagged_top'),
|
||||
text_bottom: t('components.tag_rule_form.tag_rules.variant_tagged_bottom'),
|
||||
taggable: "variant",
|
||||
visibility_field: "preferred_matched_variants_visibility",
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def visibility_options
|
||||
[
|
||||
[t('components.tag_rule_form.tag_rules.visible'), "visible"],
|
||||
[t('components.tag_rule_form.tag_rules.not_visible'), "hidden"]
|
||||
]
|
||||
end
|
||||
end
|
||||
@@ -1,35 +0,0 @@
|
||||
%div{ id: "tr_#{index}" }
|
||||
%table
|
||||
%colgroup
|
||||
%col.text{ width: "35%" }
|
||||
%col.inputs{ width: "55%" }
|
||||
%col.actions{ width: "10%" }
|
||||
%tr
|
||||
%td
|
||||
= hidden_field_tag element_name("id"), rule.id
|
||||
= hidden_field_tag element_name("type"), rule.type
|
||||
= hidden_field_tag element_name("priority"), index
|
||||
= hidden_field_tag element_name("is_default"), rule.is_default
|
||||
= hidden_field_tag element_name("preferred_customer_tags"), customer_tags, hidden_field_customer_tag_options
|
||||
%span.text-normal
|
||||
= rule_data[:text_top]
|
||||
%td
|
||||
= render TagListInputComponent.new(name: element_name("preferred_#{rule_data[:taggable]}_tags"), tags: rule.tags.split(","), only_one: true)
|
||||
%td.actions{ rowspan: 2 , "data-controller": "delete-tag-rule", "data-delete-tag-rule-index-value": index }
|
||||
- if rule.new_record?
|
||||
= link_to("", "#", { "data-action": "click->delete-tag-rule#delete" ,class: "delete-tag-rule icon-trash no-text"})
|
||||
- else
|
||||
= link_to("", "#{admin_enterprise_tag_rule_url(rule.enterprise_id, rule.id)}?index=#{index}", { "data-turbo-method": "delete", "data-turbo-confirm": t("admin.tag_rules.confirm_delete"), class: "delete-tag-rule icon-trash no-text" })
|
||||
%tr
|
||||
%td
|
||||
%span.text-normal
|
||||
= rule_data[:text_bottom]
|
||||
%td
|
||||
%div
|
||||
%div
|
||||
- if rule.is_default
|
||||
= hidden_field_tag "enterprise[tag_rules_attributes][#{index}][#{rule_data[:visibility_field]}]", "hidden"
|
||||
%span.text-normal
|
||||
= t(:not_visible)
|
||||
- else
|
||||
= select_tag "enterprise[tag_rules_attributes][#{index}][#{rule_data[:visibility_field]}]", options_for_select(visibility_options, rule.public_send(rule_data[:visibility_field].to_sym) ), { "data-controller": "tom-select", class: "primary no-search" }
|
||||
@@ -1,26 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class TagRuleGroupFormComponent < ViewComponent::Base
|
||||
def initialize(group:, index:, customer_rule_index:, tag_rule_types:)
|
||||
@group = group
|
||||
@index = index
|
||||
@customer_rule_index = customer_rule_index
|
||||
@tag_rule_types = tag_rule_types
|
||||
end
|
||||
|
||||
attr_reader :group, :index, :customer_rule_index, :tag_rule_types
|
||||
|
||||
private
|
||||
|
||||
def form_id
|
||||
"tg_#{index}"
|
||||
end
|
||||
|
||||
def customer_tag_rule_div_id
|
||||
"new-customer-tag-rule-#{index}"
|
||||
end
|
||||
|
||||
def tag_list_input_name
|
||||
"group[#{index}][preferred_customer_tags]"
|
||||
end
|
||||
end
|
||||
@@ -1,39 +0,0 @@
|
||||
%div{ id: form_id, "data-controller": "tag-rule-group-form" }
|
||||
- rule_index = customer_rule_index
|
||||
.customer_tag
|
||||
.header
|
||||
%table
|
||||
%colgroup
|
||||
%col{width: '35%'}
|
||||
%col{width: '65%'}
|
||||
%tr
|
||||
%td
|
||||
%h5
|
||||
= t('components.tag_rule_group_form.for_customers_tagged')
|
||||
%td
|
||||
= render(TagListInputComponent.new(name: tag_list_input_name,
|
||||
tags: group[:tags],
|
||||
only_one: true,
|
||||
hidden_field_data_options: { "data-action": "input->tag-rule-group-form#updatePreferredCustomerTag", "data-tag-rule-group-form-target": "customerTag" }))
|
||||
%div{ id: customer_tag_rule_div_id }
|
||||
- if group[:rules].empty?
|
||||
.no_rules
|
||||
= t('components.tag_rule_group_form.no_rules_yet')
|
||||
- else
|
||||
- group[:rules].each do |rule|
|
||||
- rule_index += 1
|
||||
= render(TagRuleFormComponent.new(rule: rule,
|
||||
index: rule_index,
|
||||
customer_tags: group[:tags],
|
||||
hidden_field_customer_tag_options: { "data-tag-rule-group-form-target": "ruleCustomerTag" }))
|
||||
|
||||
%hr
|
||||
.add_rule.text-center
|
||||
%input.button{ type: 'button', value: t('components.tag_rule_group_form.add_new_rule'), "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "tag_rule_add_new_rule_#{index}" }
|
||||
|
||||
= render AddTagRuleModalComponent.new(id: "tag_rule_add_new_rule_#{index}",
|
||||
tag_rule_types: tag_rule_types,
|
||||
current_index: (rule_index + 1),
|
||||
div_id: customer_tag_rule_div_id,
|
||||
customer_tag: group[:tags],
|
||||
hidden_field_customer_tag_options: { "data-tag-rule-group-form-target": "ruleCustomerTag" })
|
||||
@@ -1,11 +0,0 @@
|
||||
import { Controller } from "stimulus";
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["customerTag", "ruleCustomerTag"];
|
||||
|
||||
updatePreferredCustomerTag() {
|
||||
const customerTag = this.customerTagTarget.value;
|
||||
|
||||
this.ruleCustomerTagTargets.forEach((element) => (element.value = customerTag));
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
.vertical-ellipsis-menu{ "data-controller": "vertical-ellipsis-menu" }
|
||||
%i.fa.fa-ellipsis-v{ "data-action": "click->vertical-ellipsis-menu#toggle" }
|
||||
.vertical-ellipsis-menu-content{ "data-vertical-ellipsis-menu-target": "content" }
|
||||
.vertical-ellipsis-menu{ "data-controller": "vertical-ellipsis-menu--component" }
|
||||
%i.fa.fa-ellipsis-v{ "data-action": "click->vertical-ellipsis-menu--component#toggle" }
|
||||
.vertical-ellipsis-menu-content{ "data-vertical-ellipsis-menu--component-target": "content" }
|
||||
= content
|
||||
6
app/components/vertical_ellipsis_menu/component.rb
Normal file
6
app/components/vertical_ellipsis_menu/component.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module VerticalEllipsisMenu
|
||||
class Component < ViewComponent::Base
|
||||
end
|
||||
end
|
||||
@@ -1,4 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class VerticalEllipsisMenuComponent < ViewComponent::Base
|
||||
end
|
||||
@@ -3,7 +3,6 @@
|
||||
module Admin
|
||||
class BulkLineItemsController < Spree::Admin::BaseController
|
||||
include PaginationData
|
||||
|
||||
# GET /admin/bulk_line_items.json
|
||||
#
|
||||
def index
|
||||
|
||||
@@ -51,18 +51,6 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
# copy of Admin::ResourceController without flash notice
|
||||
def update
|
||||
if @object.update(permitted_resource_params)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to location_after_save }
|
||||
format.js { render layout: false }
|
||||
end
|
||||
else
|
||||
respond_with(@object)
|
||||
end
|
||||
end
|
||||
|
||||
# copy of Admin::ResourceController without flash notice
|
||||
def destroy
|
||||
if @object.destroy
|
||||
|
||||
@@ -15,8 +15,8 @@ module Admin
|
||||
def index
|
||||
# Fetch DFC catalog JSON for preview
|
||||
@catalog_url = params.require(:catalog_url).strip
|
||||
@catalog_data = api.call(@catalog_url)
|
||||
catalog = DfcCatalog.from_json(@catalog_data)
|
||||
@catalog_json = api.call(@catalog_url)
|
||||
catalog = DfcCatalog.from_json(@catalog_json)
|
||||
|
||||
# Render table and let user decide which ones to import.
|
||||
@items = list_products(catalog)
|
||||
|
||||
@@ -51,7 +51,6 @@ module Admin
|
||||
|
||||
load_tag_rule_types
|
||||
|
||||
load_tag_rules
|
||||
return unless params[:stimulus]
|
||||
|
||||
@enterprise.is_primary_producer = params[:is_primary_producer]
|
||||
@@ -84,8 +83,6 @@ module Admin
|
||||
format.turbo_stream
|
||||
end
|
||||
else
|
||||
load_tag_rule_types
|
||||
load_tag_rules
|
||||
respond_with(@object) do |format|
|
||||
format.json {
|
||||
render json: { errors: @object.errors.messages }, status: :unprocessable_entity
|
||||
@@ -150,18 +147,6 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
def new_tag_rule_group
|
||||
load_tag_rule_types
|
||||
|
||||
@index = params[:index]
|
||||
@customer_rule_index = params[:customer_rule_index].to_i
|
||||
@group = { tags: [], rules: [] }
|
||||
|
||||
respond_to do |format|
|
||||
format.turbo_stream
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def delete_custom_tab
|
||||
@@ -394,32 +379,16 @@ module Admin
|
||||
end
|
||||
|
||||
def load_tag_rule_types
|
||||
# Load rule types
|
||||
@tag_rule_types = [
|
||||
[t(".form.tag_rules.show_hide_shipping"), "FilterShippingMethods"],
|
||||
[t(".form.tag_rules.show_hide_payment"), "FilterPaymentMethods"],
|
||||
[t(".form.tag_rules.show_hide_order_cycles"), "FilterOrderCycles"]
|
||||
{ id: "FilterShippingMethods", name: t('js.tag_rules.show_hide_shipping') },
|
||||
{ id: "FilterPaymentMethods", name: t('js.tag_rules.show_hide_payment') },
|
||||
{ id: "FilterOrderCycles", name: t('js.tag_rules.show_hide_order_cycles') }
|
||||
]
|
||||
|
||||
if helpers.feature?(:variant_tag, @object)
|
||||
@tag_rule_types.prepend([t(".form.tag_rules.show_hide_variants"), "FilterVariants"])
|
||||
elsif helpers.feature?(:inventory, @object)
|
||||
@tag_rule_types.prepend([t(".form.tag_rules.show_hide_variants"), "FilterProducts"])
|
||||
end
|
||||
end
|
||||
return unless helpers.feature?(:inventory, @object)
|
||||
|
||||
def load_tag_rules
|
||||
if helpers.feature?(:variant_tag, @object)
|
||||
@default_rules = @enterprise.tag_rules.exclude_inventory.select(&:is_default)
|
||||
@rules = @enterprise.tag_rules.exclude_inventory.prioritised.reject(&:is_default)
|
||||
elsif helpers.feature?(:inventory, @object)
|
||||
@default_rules = @enterprise.tag_rules.exclude_variant.select(&:is_default)
|
||||
@rules = @enterprise.tag_rules.exclude_variant.prioritised.reject(&:is_default)
|
||||
else
|
||||
@default_rules =
|
||||
@enterprise.tag_rules.exclude_inventory.exclude_variant.select(&:is_default)
|
||||
@rules =
|
||||
@enterprise.tag_rules.exclude_inventory.exclude_variant.prioritised.reject(&:is_default)
|
||||
end
|
||||
@tag_rule_types.prepend({ id: "FilterProducts", name: t('js.tag_rules.show_hide_variants') })
|
||||
end
|
||||
|
||||
def setup_property
|
||||
|
||||
@@ -49,7 +49,7 @@ module Admin
|
||||
errors: @importer.errors.full_messages
|
||||
}
|
||||
|
||||
if helpers.inventory_enabled?(spree_current_user.enterprises)
|
||||
if helpers.feature?(:inventory, spree_current_user.enterprises)
|
||||
json[:results][:inventory_created] = @importer.inventory_created_count
|
||||
json[:results][:inventory_updated] = @importer.inventory_updated_count
|
||||
end
|
||||
@@ -175,7 +175,7 @@ module Admin
|
||||
|
||||
# Return an error if trying to import into inventories when inventory is disable
|
||||
def can_import_into_inventories?
|
||||
return true if helpers.inventory_enabled?(spree_current_user.enterprises) ||
|
||||
return true if helpers.feature?(:inventory, spree_current_user.enterprises) ||
|
||||
params.dig(:settings, "import_into") != 'inventories'
|
||||
|
||||
redirect_to admin_product_import_url, notice: I18n.t(:product_import_inventory_disable)
|
||||
|
||||
@@ -11,8 +11,7 @@ module Admin
|
||||
def index
|
||||
fetch_products
|
||||
render "index",
|
||||
locals: { producer_options:, categories:, tax_category_options:, available_tags:,
|
||||
flash:, allowed_producers: }
|
||||
locals: { producers:, categories:, tax_category_options:, available_tags:, flash: }
|
||||
|
||||
session[:products_return_to_url] = request.url
|
||||
end
|
||||
@@ -33,8 +32,7 @@ module Admin
|
||||
|
||||
render "index", status: :unprocessable_entity,
|
||||
locals: {
|
||||
producer_options:, categories:, tax_category_options:, available_tags:,
|
||||
allowed_producers:, flash:
|
||||
producers:, categories:, tax_category_options:, available_tags:, flash:
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -80,29 +78,27 @@ module Admin
|
||||
end
|
||||
|
||||
def clone
|
||||
product = Spree::Product.find(params[:id])
|
||||
authorize! :clone, product
|
||||
@product = Spree::Product.find(params[:id])
|
||||
authorize! :clone, @product
|
||||
|
||||
status = :ok
|
||||
|
||||
begin
|
||||
cloned_product = product.duplicate
|
||||
@cloned_product = @product.duplicate
|
||||
flash.now[:success] = t('.success')
|
||||
|
||||
product_index = "-#{cloned_product.id}"
|
||||
@product_index = "-#{@cloned_product.id}"
|
||||
@producer_options = producers
|
||||
@category_options = categories
|
||||
@tax_category_options = tax_category_options
|
||||
rescue ActiveRecord::ActiveRecordError => e
|
||||
flash.now[:error] = clone_error_message(e)
|
||||
status = :unprocessable_entity
|
||||
product_index = "-1" # Create a unique enough index
|
||||
@product_index = "-1" # Create a unique enough index
|
||||
end
|
||||
|
||||
respond_with do |format|
|
||||
format.turbo_stream {
|
||||
render :clone, status:,
|
||||
locals: { product:, cloned_product:, product_index:, producer_options:,
|
||||
category_options: categories, tax_category_options:,
|
||||
allowed_producers: }
|
||||
}
|
||||
format.turbo_stream { render :clone, status: }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -127,32 +123,12 @@ module Admin
|
||||
@page = params[:page].presence || 1
|
||||
@per_page = params[:per_page].presence || 15
|
||||
@q = params.permit(q: {})[:q] || { s: 'name asc' }
|
||||
|
||||
# Transform on_hand sorting to properly handle On-Demand products:
|
||||
# - On-Demand products should ignore on_hand completely and sort alphabetically.
|
||||
# - Non-On-Demand products should continue sorting by on_hand as usual.
|
||||
if @q[:s] == 'on_hand asc'
|
||||
@q[:s] = [
|
||||
'backorderable_priority asc',
|
||||
'backorderable_name asc',
|
||||
@q[:s]
|
||||
]
|
||||
elsif @q[:s] == 'on_hand desc'
|
||||
@q[:s] = [
|
||||
'backorderable_priority desc',
|
||||
'backorderable_name asc',
|
||||
@q[:s]
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
def allowed_producers
|
||||
OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
def producers
|
||||
producers = OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
.managed_product_enterprises.is_primary_producer.by_name
|
||||
end
|
||||
|
||||
def producer_options
|
||||
allowed_producers.map { |p| [p.name, p.id] }
|
||||
producers.map { |p| [p.name, p.id] }
|
||||
end
|
||||
|
||||
def categories
|
||||
@@ -179,28 +155,8 @@ module Admin
|
||||
product_query = OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
.editable_products.merge(product_scope_with_includes).ransack(ransack_query).result
|
||||
|
||||
# Postgres requires ORDER BY expressions to appear in the SELECT list when using DISTINCT.
|
||||
# When the current ransack sort uses the computed stock columns, include them in the select
|
||||
# so the generated COUNT/DISTINCT query is valid.
|
||||
sort_columns = Array(@q && @q[:s]).flatten
|
||||
if sort_columns.any? { |s|
|
||||
s.to_s.include?('on_hand') || s.to_s.include?('backorderable_priority')
|
||||
}
|
||||
|
||||
product_query = product_query.select(
|
||||
Arel.sql('spree_products.*'),
|
||||
Spree::Product.backorderable_priority_sql,
|
||||
Spree::Product.backorderable_name_sql,
|
||||
Spree::Product.on_hand_sql
|
||||
)
|
||||
end
|
||||
|
||||
@pagy, @products = pagy(
|
||||
product_query.order(:name),
|
||||
limit: @per_page,
|
||||
page: @page,
|
||||
size: [1, 2, 2, 1]
|
||||
)
|
||||
@pagy, @products = pagy(product_query.order(:name), limit: @per_page, page: @page,
|
||||
size: [1, 2, 2, 1])
|
||||
end
|
||||
|
||||
def product_scope
|
||||
|
||||
@@ -4,7 +4,6 @@ module Admin
|
||||
class ReportsController < Spree::Admin::BaseController
|
||||
include ActiveStorage::SetCurrent
|
||||
include ReportsActions
|
||||
|
||||
helper ReportsHelper
|
||||
|
||||
before_action :authorize_report, only: [:show, :create]
|
||||
@@ -23,12 +22,14 @@ module Admin
|
||||
def show
|
||||
@report = report_class.new(spree_current_user, params, render: false)
|
||||
@rendering_options = rendering_options
|
||||
|
||||
show_report
|
||||
end
|
||||
|
||||
def create
|
||||
@report = report_class.new(spree_current_user, params, render: true)
|
||||
update_rendering_options
|
||||
|
||||
render_in_background
|
||||
end
|
||||
|
||||
@@ -60,9 +61,7 @@ module Admin
|
||||
@blob = ReportBlob.create_for_upload_later!(report_filename)
|
||||
|
||||
ReportJob.perform_later(
|
||||
report_class:,
|
||||
user: spree_current_user,
|
||||
params:,
|
||||
report_class:, user: spree_current_user, params:,
|
||||
format: report_format,
|
||||
blob: @blob,
|
||||
channel: ScopedChannel.for_id(params[:uuid]),
|
||||
|
||||
@@ -1,47 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class TagRulesController < Spree::Admin::BaseController
|
||||
class TagRulesController < Admin::ResourceController
|
||||
respond_to :json
|
||||
|
||||
def new
|
||||
@index = params[:index]
|
||||
@div_id = params[:div_id]
|
||||
is_default = params[:is_default]
|
||||
@customer_tags = params[:customer_tags]
|
||||
respond_override destroy: { json: {
|
||||
success: lambda { head :no_content }
|
||||
} }
|
||||
|
||||
status = :ok
|
||||
if permitted_tag_rule_type.include?(params[:rule_type])
|
||||
@default_rule = "TagRule::#{params[:rule_type]}".constantize.new(is_default:)
|
||||
else
|
||||
flash.now[:error] = t(".not_supported_type")
|
||||
status = :internal_server_error
|
||||
end
|
||||
|
||||
respond_with do |format|
|
||||
format.turbo_stream { render :new, status: }
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@rule = TagRule.find(params[:id])
|
||||
@index = params[:index]
|
||||
authorize! :destroy, @rule
|
||||
|
||||
status = :ok
|
||||
if @rule.destroy
|
||||
flash[:success] = Spree.t(:successfully_removed, resource: "Tag Rule")
|
||||
else
|
||||
flash.now[:error] = t(".destroy_error")
|
||||
status = :internal_server_error
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.turbo_stream { render :destroy, status: }
|
||||
end
|
||||
end
|
||||
|
||||
# Used by the tag input autocomplete
|
||||
def map_by_tag
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
@@ -51,26 +17,6 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
# Use to populate autocomplete with available rule for the given tag/enterprise
|
||||
def variant_tag_rules
|
||||
tag_rules =
|
||||
TagRule.matching_variant_tag_rules_by_enterprises(params[:enterprise_id], params[:q])
|
||||
|
||||
@formatted_tag_rules = tag_rules.each_with_object({}) do |rule, mapping|
|
||||
rule.preferred_variant_tags.split(",").each do |tag|
|
||||
if mapping[tag]
|
||||
mapping[tag][:rules] += 1
|
||||
else
|
||||
mapping[tag] = { tag:, rules: 1 }
|
||||
end
|
||||
end
|
||||
end.values
|
||||
|
||||
respond_with do |format|
|
||||
format.html { render :variant_tag_rules, layout: false }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def collection_actions
|
||||
@@ -93,13 +39,5 @@ module Admin
|
||||
Enterprise.managed_by(spree_current_user)
|
||||
end
|
||||
end
|
||||
|
||||
def model_class
|
||||
TagRule
|
||||
end
|
||||
|
||||
def permitted_tag_rule_type
|
||||
%w{FilterOrderCycles FilterPaymentMethods FilterProducts FilterShippingMethods FilterVariants}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,8 +44,6 @@ module Admin
|
||||
def load_data
|
||||
@hubs = OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||
variant_override_hubs.by_name
|
||||
# Only display the ones with inventory enabled
|
||||
@hubs = @hubs.select { |p| helpers.feature?(:inventory, p) }
|
||||
|
||||
# Used in JS to look up the name of the producer of each product
|
||||
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||
|
||||
@@ -43,7 +43,7 @@ module Api
|
||||
@enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id])
|
||||
authorize! :update, @enterprise
|
||||
|
||||
if params[:logo] && @enterprise.update!(logo: params[:logo])
|
||||
if params[:logo] && @enterprise.update( logo: params[:logo] )
|
||||
render(html: @enterprise.logo_url(:medium), status: :ok)
|
||||
elsif params[:promo] && @enterprise.update!( promo_image: params[:promo] )
|
||||
render(html: @enterprise.promo_image_url(:medium), status: :ok)
|
||||
|
||||
@@ -7,7 +7,6 @@ module Api
|
||||
module V0
|
||||
class ExchangeProductsController < Api::V0::BaseController
|
||||
include PaginationData
|
||||
|
||||
DEFAULT_PER_PAGE = 100
|
||||
|
||||
skip_authorization_check only: [:index]
|
||||
|
||||
@@ -23,8 +23,7 @@ module Api
|
||||
order_cycle,
|
||||
customer,
|
||||
search_params,
|
||||
inventory_enabled:,
|
||||
variant_tag_enabled:
|
||||
inventory_enabled:
|
||||
).products_json
|
||||
|
||||
render plain: products
|
||||
@@ -97,17 +96,13 @@ module Api
|
||||
|
||||
def distributed_products
|
||||
OrderCycles::DistributedProductsService.new(
|
||||
distributor, order_cycle, customer, inventory_enabled:, variant_tag_enabled:,
|
||||
distributor, order_cycle, customer, inventory_enabled:
|
||||
).products_relation.pluck(:id)
|
||||
end
|
||||
|
||||
def inventory_enabled
|
||||
OpenFoodNetwork::FeatureToggle.enabled?(:inventory, distributor)
|
||||
end
|
||||
|
||||
def variant_tag_enabled
|
||||
OpenFoodNetwork::FeatureToggle.enabled?(:variant_tag, distributor)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,6 @@ module Api
|
||||
module V0
|
||||
class ProductsController < Api::V0::BaseController
|
||||
include PaginationData
|
||||
|
||||
respond_to :json
|
||||
DEFAULT_PER_PAGE = 15
|
||||
|
||||
|
||||
@@ -8,10 +8,6 @@ module Api
|
||||
include AddressTransformation
|
||||
include ExtraFields
|
||||
|
||||
wrap_parameters :customer, include:
|
||||
Customer.attribute_names +
|
||||
[:billing_address, :shipping_address]
|
||||
|
||||
skip_authorization_check only: :index
|
||||
|
||||
before_action :authorize_action, only: [:show, :update, :destroy]
|
||||
@@ -92,8 +88,7 @@ module Api
|
||||
attributes = params.require(:customer).permit(
|
||||
:email, :enterprise_id,
|
||||
:code, :first_name, :last_name,
|
||||
:billing_address,
|
||||
shipping_address: [
|
||||
:billing_address, shipping_address: [
|
||||
:phone, :latitude, :longitude,
|
||||
:first_name, :last_name,
|
||||
:street_address_1, :street_address_2,
|
||||
|
||||
@@ -4,7 +4,7 @@ module ManagerInvitations
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def create_new_manager(email, enterprise)
|
||||
password = SecureRandom.base58(64)
|
||||
password = Devise.friendly_token
|
||||
new_user = Spree::User.create(email:, unconfirmed_email: email, password:)
|
||||
new_user.reset_password_token = Devise.friendly_token
|
||||
# Same time as used in Devise's lib/devise/models/recoverable.rb.
|
||||
|
||||
@@ -20,43 +20,25 @@ module OrderStockCheck
|
||||
@updated_variants = check_stock_service.update_line_items
|
||||
end
|
||||
|
||||
def check_order_cycle_expiry(should_empty_order: true)
|
||||
def check_order_cycle_expiry
|
||||
return unless current_order_cycle&.closed?
|
||||
|
||||
Alert.raise_with_record("Notice: order cycle closed during checkout completion", current_order)
|
||||
current_order.empty!
|
||||
current_order.assign_order_cycle! nil
|
||||
|
||||
handle_closed_order_cycle if should_empty_order
|
||||
|
||||
flash[:info] = build_order_cycle_message(should_empty_order)
|
||||
redirect_to_shop_page(should_empty_order)
|
||||
flash[:info] = I18n.t('order_cycle_closed')
|
||||
respond_to do |format|
|
||||
format.cable_ready {
|
||||
render status: :see_other, cable_ready: cable_car.redirect_to(url: main_app.shop_path)
|
||||
}
|
||||
format.json { render json: { path: main_app.shop_path }, status: :see_other }
|
||||
format.html { redirect_to main_app.shop_path, status: :see_other }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def handle_closed_order_cycle
|
||||
current_order.empty!
|
||||
current_order.assign_order_cycle!(nil)
|
||||
end
|
||||
|
||||
def build_order_cycle_message(should_empty_order)
|
||||
# If order is not emptied, we assume user will contact support for next steps
|
||||
key = should_empty_order ? 'order_cycle_closed' : 'order_cycle_closed_next_steps'
|
||||
I18n.t(key, order_number: current_order.number)
|
||||
end
|
||||
|
||||
def redirect_to_shop_page(should_empty_order)
|
||||
# If order is not emptied, redirect to shops page because shop page empties the order by default
|
||||
redirect_url = should_empty_order ? main_app.shop_path : main_app.shops_path
|
||||
|
||||
respond_to do |format|
|
||||
format.cable_ready {
|
||||
render status: :see_other, cable_ready: cable_car.redirect_to(url: redirect_url)
|
||||
}
|
||||
format.json { render json: { path: redirect_url }, status: :see_other }
|
||||
format.html { redirect_to redirect_url, status: :see_other }
|
||||
end
|
||||
end
|
||||
|
||||
def check_stock_service
|
||||
@check_stock_service ||= Orders::CheckStockService.new(order: @order)
|
||||
end
|
||||
|
||||
@@ -84,7 +84,6 @@ module ReportsActions
|
||||
else
|
||||
params[:fields_to_show]
|
||||
end,
|
||||
display_metadata_rows: false,
|
||||
display_summary_row: request.get?,
|
||||
display_header_row: false
|
||||
}
|
||||
@@ -95,7 +94,6 @@ module ReportsActions
|
||||
rendering_options.update(
|
||||
options: {
|
||||
fields_to_show: params[:fields_to_show],
|
||||
display_metadata_rows: params[:display_metadata_rows].present?,
|
||||
display_summary_row: params[:display_summary_row].present?,
|
||||
display_header_row: params[:display_header_row].present?
|
||||
}
|
||||
|
||||
@@ -8,9 +8,7 @@ module PaymentGateways
|
||||
before_action :destroy_orphaned_paypal_payments, only: :confirm
|
||||
before_action :load_checkout_order, only: [:express, :confirm]
|
||||
before_action :handle_insufficient_stock, only: [:express, :confirm]
|
||||
before_action -> { check_order_cycle_expiry(should_empty_order: false) }, only: [
|
||||
:express, :confirm
|
||||
]
|
||||
before_action :check_order_cycle_expiry, only: [:express, :confirm]
|
||||
before_action :permit_parameters!
|
||||
|
||||
after_action :reset_order_when_complete, only: :confirm
|
||||
|
||||
@@ -7,7 +7,7 @@ module PaymentGateways
|
||||
|
||||
before_action :load_checkout_order, only: :confirm
|
||||
before_action :validate_payment_intent, only: :confirm
|
||||
before_action -> { check_order_cycle_expiry(should_empty_order: false) }, only: :confirm
|
||||
before_action :check_order_cycle_expiry, only: :confirm
|
||||
|
||||
def confirm
|
||||
validate_stock
|
||||
|
||||
@@ -9,7 +9,11 @@ class PaymentsController < BaseController
|
||||
@payment = Spree::Payment.find(params[:id])
|
||||
authorize! :show, @payment.order
|
||||
|
||||
redirect_to(@payment.redirect_auth_url || order_url(@payment.order))
|
||||
if (url = @payment.cvv_response_message)
|
||||
redirect_to url
|
||||
else
|
||||
redirect_to order_url(@payment.order)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -6,7 +6,6 @@ module Spree
|
||||
module Admin
|
||||
class OrdersController < Spree::Admin::BaseController
|
||||
include OpenFoodNetwork::SpreeApiKeyLoader
|
||||
|
||||
helper CheckoutHelper
|
||||
|
||||
before_action :load_order, only: [:edit, :update, :fire, :resend, :invoice, :print]
|
||||
|
||||
@@ -10,12 +10,6 @@ module Spree
|
||||
|
||||
respond_to :html
|
||||
|
||||
PAYMENT_METHODS = %w{
|
||||
Spree::PaymentMethod::Check
|
||||
Spree::Gateway::PayPalExpress
|
||||
Spree::Gateway::StripeSCA
|
||||
}.index_with(&:constantize).freeze
|
||||
|
||||
def create
|
||||
force_environment
|
||||
|
||||
@@ -95,9 +89,8 @@ module Spree
|
||||
@payment_method = PaymentMethod.find(params[:pm_id])
|
||||
end
|
||||
else
|
||||
@payment_method = PAYMENT_METHODS.fetch(params[:provider_type], PaymentMethod).new
|
||||
@payment_method = params[:provider_type].constantize.new
|
||||
end
|
||||
|
||||
render partial: 'provider_settings'
|
||||
end
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ module Spree
|
||||
include OpenFoodNetwork::SpreeApiKeyLoader
|
||||
include OrderCyclesHelper
|
||||
include EnterprisesHelper
|
||||
|
||||
helper ::Admin::ProductsHelper
|
||||
helper Spree::Admin::TaxCategoriesHelper
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ module Spree
|
||||
include Spree::Core::ControllerHelpers::Order
|
||||
|
||||
include I18nHelper
|
||||
|
||||
before_action :set_locale
|
||||
|
||||
# Devise::PasswordsController allows for blank passwords.
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class WellKnownController < ApplicationController
|
||||
layout nil
|
||||
|
||||
def dfc
|
||||
base = "https://github.com/datafoodconsortium/taxonomies/releases/latest/download/scopes.rdf#"
|
||||
render json: {
|
||||
"#{base}ReadEnterprise" => "/api/dfc/enterprises/",
|
||||
"#{base}ReadProducts" => "/api/dfc/supplied_products/",
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -36,7 +36,9 @@ class ScheduleForm
|
||||
false unless @schedule.update(permitted_resource_params)
|
||||
end
|
||||
|
||||
delegate :order_cycle_ids, to: :@schedule
|
||||
def order_cycle_ids
|
||||
@schedule.order_cycle_ids
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
module EnterprisesHelper # rubocop:disable Metrics/ModuleLength
|
||||
module EnterprisesHelper
|
||||
def add_check_if_single(count)
|
||||
if count == 1
|
||||
{ checked: true }
|
||||
@@ -28,7 +28,7 @@ module Admin
|
||||
show_connected_apps = can?(:manage_connected_apps, enterprise) &&
|
||||
(connected_apps_enabled(enterprise).present? ||
|
||||
dfc_platforms_available?)
|
||||
show_inventory_settings = feature?(:inventory, *spree_current_user.enterprises) && is_shop
|
||||
show_inventory_settings = feature?(:inventory, spree_current_user.enterprises) && is_shop
|
||||
|
||||
show_options = {
|
||||
show_properties:,
|
||||
@@ -50,7 +50,7 @@ module Admin
|
||||
end
|
||||
|
||||
def dfc_platforms_available?
|
||||
ApiUser::PLATFORMS.keys.any? do |id|
|
||||
DfcProvider::PlatformsController::PLATFORM_IDS.keys.any? do |id|
|
||||
feature?(id, spree_current_user)
|
||||
end
|
||||
end
|
||||
@@ -76,30 +76,8 @@ module Admin
|
||||
Enterprise::SELLS.map { |s| [I18n.t(s, scope:), s] }
|
||||
end
|
||||
|
||||
# Group tag rules per rule.preferred_customer_tags
|
||||
def tag_groups(tag_rules)
|
||||
tag_rules.each_with_object([]) do |tag_rule, tag_groups|
|
||||
tag_group = find_match(tag_groups, tag_rule.preferred_customer_tags.split(","))
|
||||
|
||||
if tag_group[:rules].blank?
|
||||
tag_groups << tag_group
|
||||
tag_group[:position] = tag_groups.count
|
||||
end
|
||||
|
||||
tag_group[:rules] << tag_rule
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_match(tag_groups, tags)
|
||||
tag_groups.each do |tag_group|
|
||||
return tag_group if tag_group[:tags].length == tags.length &&
|
||||
(tag_group[:tags] & tags) == tag_group[:tags]
|
||||
end
|
||||
{ tags:, rules: [] }
|
||||
end
|
||||
|
||||
def build_enterprise_side_menu_items(is_shop:, show_options: ) # rubocop:disable Metrics/MethodLength
|
||||
[
|
||||
{ name: 'primary_details', icon_class: "icon-home", show: true, selected: 'selected' },
|
||||
|
||||
@@ -41,11 +41,5 @@ module Admin
|
||||
def hide_producer_column?(producer_options)
|
||||
spree_current_user.column_preferences.bulk_edit_product.empty? && producer_options.one?
|
||||
end
|
||||
|
||||
# check if the user is in the "admins" group or if it's enabled for any of
|
||||
# the enterprises the user manages
|
||||
def variant_tag_enabled?(user)
|
||||
feature?(:variant_tag, user) || feature?(:variant_tag, *user.enterprises)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -52,9 +52,9 @@ module ApplicationHelper
|
||||
|
||||
# Pass URL helper calls on to spree where applicable so that we don't need to use
|
||||
# spree.foo_path in any view rendered from non-spree-namespaced controllers.
|
||||
def method_missing(method, *, &)
|
||||
def method_missing(method, *args, &)
|
||||
if method.to_s.end_with?('_path', '_url') && spree.respond_to?(method)
|
||||
spree.public_send(method, *)
|
||||
spree.public_send(method, *args)
|
||||
else
|
||||
super
|
||||
end
|
||||
|
||||
@@ -120,7 +120,7 @@ module InjectionHelper
|
||||
|
||||
def inject_enterprise_attributes(enterprise_attributes)
|
||||
render partial: "json/injection_ams",
|
||||
locals: { name: 'enterpriseAttributes', json: enterprise_attributes.to_json }
|
||||
locals: { name: 'enterpriseAttributes', json: enterprise_attributes.to_json.to_s }
|
||||
end
|
||||
|
||||
def inject_saved_credit_cards
|
||||
|
||||
@@ -1,29 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module LinkHelper
|
||||
def link_to_or_disabled(name = nil, options = nil, html_options = nil, &block)
|
||||
html_options, options, name = options, name, block if block_given?
|
||||
html_options ||= {}
|
||||
|
||||
if !!html_options.delete(:disabled)
|
||||
# https://www.scottohara.me/blog/2021/05/28/disabled-links.html
|
||||
html_options.merge!(
|
||||
'aria-disabled': true,
|
||||
class: (html_options[:class].to_s.split + ["disabled"]).uniq.join(" "),
|
||||
role: "link"
|
||||
)
|
||||
if block_given?
|
||||
content_tag("a", name, **html_options, &block)
|
||||
else
|
||||
content_tag("a", name, **html_options)
|
||||
end
|
||||
elsif block_given?
|
||||
link_to options, html_options, &block
|
||||
else
|
||||
link_to name, options, html_options
|
||||
end
|
||||
end
|
||||
|
||||
def link_to_service(baseurl, name, html_options = {}, &)
|
||||
return if name.blank?
|
||||
|
||||
|
||||
@@ -44,7 +44,9 @@ module ReportsHelper
|
||||
.pluck(:name, :id)
|
||||
end
|
||||
|
||||
delegate :currency_symbol, to: :'Spree::Money'
|
||||
def currency_symbol
|
||||
Spree::Money.currency_symbol
|
||||
end
|
||||
|
||||
def enterprise_fee_owner_ids(orders)
|
||||
EnterpriseFee.where(id: enterprise_fee_ids(orders))
|
||||
|
||||
@@ -62,12 +62,6 @@ module ShopHelper
|
||||
true
|
||||
end
|
||||
|
||||
def shop_tab_class(tab)
|
||||
return unless (tab == "home" && show_home_tab?) || current_order(false)&.order_cycle.nil?
|
||||
|
||||
"with-darker-background"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def show_groups_tabs?
|
||||
|
||||
@@ -147,10 +147,6 @@ module Spree
|
||||
dom_id(record, 'spree')
|
||||
end
|
||||
|
||||
def inventory_enabled?(enterprises)
|
||||
!feature?(:variant_tag, *enterprises) && feature?(:inventory, *enterprises)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def attribute_name_for(field_name)
|
||||
|
||||
@@ -120,7 +120,7 @@ module Spree
|
||||
end
|
||||
|
||||
def cancel_event_link(order)
|
||||
event_label = I18n.t("cancel_order", scope: "actions")
|
||||
event_label = I18n.t("cancel", scope: "actions")
|
||||
button_link_to(event_label,
|
||||
fire_admin_order_url(order, e: "cancel"),
|
||||
method: :put, icon: "icon-cancel", form_id: "cancel_order_form")
|
||||
|
||||
@@ -10,7 +10,9 @@ module TermsAndConditionsHelper
|
||||
TermsOfService.required?(distributor)
|
||||
end
|
||||
|
||||
delegate :platform_terms_required?, to: :TermsOfService
|
||||
def platform_terms_required?
|
||||
TermsOfService.platform_terms_required?
|
||||
end
|
||||
|
||||
def distributor_terms_required?
|
||||
TermsOfService.distributor_terms_required?(current_order.distributor)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user