mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-16 19:16:49 +00:00
Compare commits
170 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f18487ea68 | ||
|
|
7c4714288d | ||
|
|
b6e393eabb | ||
|
|
d18aeb9918 | ||
|
|
587f76415b | ||
|
|
665aee6eb0 | ||
|
|
5e505c1240 | ||
|
|
e948f89625 | ||
|
|
f42b91f414 | ||
|
|
94bda6d0f8 | ||
|
|
1422b440e4 | ||
|
|
95ad87d840 | ||
|
|
7357419f6f | ||
|
|
8e5404a268 | ||
|
|
04fc729a5a | ||
|
|
8818a98230 | ||
|
|
d3efa3afa6 | ||
|
|
4414879b3f | ||
|
|
3c7aac59e9 | ||
|
|
41cd40a55b | ||
|
|
a0e8111b3a | ||
|
|
8f07ee5bf7 | ||
|
|
43da235d15 | ||
|
|
3252de19a3 | ||
|
|
fd3bd062fe | ||
|
|
029d447d98 | ||
|
|
8e5fac9fb3 | ||
|
|
30c0bcc910 | ||
|
|
1a4ba9b689 | ||
|
|
4de8191e27 | ||
|
|
472ca5a16b | ||
|
|
dab626031b | ||
|
|
913dded766 | ||
|
|
a36b7ce01a | ||
|
|
e4be336630 | ||
|
|
cae13df2c7 | ||
|
|
81796db6e5 | ||
|
|
ba3553854e | ||
|
|
c386d1af01 | ||
|
|
9916b361e4 | ||
|
|
b2d7d797d9 | ||
|
|
e385b9f708 | ||
|
|
2b9b02aeea | ||
|
|
009b5e5ff1 | ||
|
|
7c310e7e46 | ||
|
|
bd0db57768 | ||
|
|
bb8ecccc31 | ||
|
|
ffd5817749 | ||
|
|
1a68236c3c | ||
|
|
c057bab493 | ||
|
|
59340c7cff | ||
|
|
aebb18da99 | ||
|
|
ce60335a60 | ||
|
|
307acdd9d1 | ||
|
|
d51e257904 | ||
|
|
07a3e83dc6 | ||
|
|
38f58b168a | ||
|
|
34abca5ff1 | ||
|
|
145764a921 | ||
|
|
9bbe573335 | ||
|
|
c5d5694f24 | ||
|
|
ab194a0e80 | ||
|
|
749944fc25 | ||
|
|
3cffc5538a | ||
|
|
6d7908e1f8 | ||
|
|
965b34318f | ||
|
|
3bb9eb9765 | ||
|
|
bd39595917 | ||
|
|
81e16a9cdf | ||
|
|
c38c8bcff2 | ||
|
|
7633af8ff2 | ||
|
|
94c0ebd897 | ||
|
|
7b3db4bae4 | ||
|
|
b1d95cac7f | ||
|
|
3f297a8afa | ||
|
|
af111a9625 | ||
|
|
96f715b62b | ||
|
|
33b4e38fc5 | ||
|
|
27e4ae9892 | ||
|
|
f434d8b066 | ||
|
|
43d471f93d | ||
|
|
3794f69cad | ||
|
|
cf4cd311b3 | ||
|
|
275326eaa6 | ||
|
|
0c392d5302 | ||
|
|
e71a2603bd | ||
|
|
5aea527962 | ||
|
|
05b3e97a0e | ||
|
|
f9b76fadbd | ||
|
|
64f44b8a9b | ||
|
|
5dfb7645cb | ||
|
|
74927dd03d | ||
|
|
71dd398131 | ||
|
|
245f0caedb | ||
|
|
18bc95c6a3 | ||
|
|
243190491b | ||
|
|
7213dcf124 | ||
|
|
e90569bdcc | ||
|
|
404e27ab71 | ||
|
|
5af6d534df | ||
|
|
65410aabad | ||
|
|
2e78ea62b6 | ||
|
|
201461918d | ||
|
|
3efe0c7835 | ||
|
|
e3d453e397 | ||
|
|
0ecfc23c67 | ||
|
|
ff16b575c4 | ||
|
|
faa826a76e | ||
|
|
1e02084f95 | ||
|
|
44cca40db6 | ||
|
|
52174b1e06 | ||
|
|
cdf0777d8e | ||
|
|
9cb7c46b44 | ||
|
|
4c6d894bc0 | ||
|
|
27975252f5 | ||
|
|
9fc82776ec | ||
|
|
2c8bf82426 | ||
|
|
121019411c | ||
|
|
1a5eb5b39a | ||
|
|
2bd536298b | ||
|
|
7415503b63 | ||
|
|
895e142e2c | ||
|
|
f1ffadd39c | ||
|
|
cc35d118eb | ||
|
|
e09d78dfb2 | ||
|
|
dad7cfc180 | ||
|
|
678497914f | ||
|
|
852e7fa81e | ||
|
|
fb437fb34d | ||
|
|
025f8b25b1 | ||
|
|
3017f61047 | ||
|
|
8cb3d06f7c | ||
|
|
8f442e82ed | ||
|
|
b28886dd38 | ||
|
|
bd4f115185 | ||
|
|
c43650034f | ||
|
|
94bc787283 | ||
|
|
58851a8e67 | ||
|
|
c3e2382600 | ||
|
|
802878b4eb | ||
|
|
69d8fc3cad | ||
|
|
6a226e476d | ||
|
|
479d52a2bb | ||
|
|
8afd6eb0ab | ||
|
|
8d4a1ff320 | ||
|
|
1f0e541743 | ||
|
|
adb7563ccb | ||
|
|
73688b9544 | ||
|
|
02ea3cb61c | ||
|
|
c7d0594257 | ||
|
|
4eee7ad603 | ||
|
|
23f7f2974a | ||
|
|
8105b919e0 | ||
|
|
53ef5148e9 | ||
|
|
93e6f9034c | ||
|
|
125a92346c | ||
|
|
31b8fe16cb | ||
|
|
cbffea8d30 | ||
|
|
10917161b0 | ||
|
|
be9da62d98 | ||
|
|
9f6c149735 | ||
|
|
50578647ee | ||
|
|
a28f05fddc | ||
|
|
d6c044fd5b | ||
|
|
a75ea5b506 | ||
|
|
7f937fd4b1 | ||
|
|
667ce5eda2 | ||
|
|
c72f9477cd | ||
|
|
8787eed863 | ||
|
|
e2b6199f26 |
@@ -1,56 +0,0 @@
|
||||
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,7 +20,6 @@ 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"
|
||||
|
||||
|
||||
26
.github/workflows/linters.yml
vendored
26
.github/workflows/linters.yml
vendored
@@ -1,10 +1,11 @@
|
||||
name: Linters
|
||||
on: [push, pull_request]
|
||||
on: [pull_request]
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
checks: write # to post check annotations
|
||||
jobs:
|
||||
lint:
|
||||
name: prettier and rubocop
|
||||
name: reviewdog
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -21,21 +22,10 @@ jobs:
|
||||
|
||||
- run: git show --no-patch # the commit being tested (which is often a merge due to actions/checkout@v3)
|
||||
|
||||
- name: prettier
|
||||
uses: EPMatt/reviewdog-action-prettier@v1
|
||||
- uses: reviewdog/action-setup@v1
|
||||
with:
|
||||
github_token: ${{ secrets.github_token }}
|
||||
reporter: github-pr-check
|
||||
level: error
|
||||
fail_on_error: true
|
||||
reviewdog_version: v0.21.0
|
||||
|
||||
- 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
|
||||
- run: ./script/reviewdog.sh
|
||||
env:
|
||||
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.github_token }}
|
||||
|
||||
@@ -2,19 +2,12 @@
|
||||
# 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
|
||||
@@ -32,7 +25,6 @@ linters:
|
||||
enabled: true
|
||||
|
||||
LineLength:
|
||||
enabled: true
|
||||
max: 80
|
||||
|
||||
MultilinePipe:
|
||||
@@ -47,24 +39,11 @@ 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
|
||||
|
||||
153
.haml-lint_todo.yml
Normal file
153
.haml-lint_todo.yml
Normal file
@@ -0,0 +1,153 @@
|
||||
# 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"
|
||||
@@ -1,6 +0,0 @@
|
||||
rubocop:
|
||||
config_file: .rubocop_styleguide.yml
|
||||
scss:
|
||||
config_file: .scss-lint.yml
|
||||
haml:
|
||||
config_file: .haml-lint.yml
|
||||
@@ -1 +1 @@
|
||||
17.9.1
|
||||
24.10.0
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
# The configuration is split into three files. Look into those files for more details.
|
||||
#
|
||||
require:
|
||||
plugins:
|
||||
- rubocop-capybara
|
||||
- rubocop-factory_bot
|
||||
- rubocop-rails
|
||||
|
||||
@@ -94,7 +94,7 @@ Metrics/PerceivedComplexity:
|
||||
Enabled: true
|
||||
Max: 14 # default 8
|
||||
|
||||
Naming/PredicateName:
|
||||
Naming/PredicatePrefix:
|
||||
Enabled: false
|
||||
|
||||
Naming/VariableNumber:
|
||||
|
||||
@@ -1,11 +1,44 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 1400 --no-auto-gen-timestamp`
|
||||
# using RuboCop version 1.64.1.
|
||||
# using RuboCop version 1.81.6.
|
||||
# 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:
|
||||
@@ -42,7 +75,7 @@ Metrics/BlockLength:
|
||||
- 'lib/tasks/data.rake'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: CountBlocks, Max.
|
||||
# Configuration parameters: CountBlocks, CountModifierForms, Max.
|
||||
Metrics/BlockNesting:
|
||||
Exclude:
|
||||
- 'app/models/spree/payment/processing.rb'
|
||||
@@ -100,7 +133,7 @@ Metrics/ClassLength:
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
|
||||
- 'lib/reporting/reports/xero_invoices/base.rb'
|
||||
|
||||
# Offense count: 30
|
||||
# Offense count: 35
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
||||
Metrics/CyclomaticComplexity:
|
||||
Exclude:
|
||||
@@ -123,6 +156,11 @@ 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'
|
||||
@@ -182,8 +220,9 @@ Metrics/PerceivedComplexity:
|
||||
- 'app/models/spree/order/checkout.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: EnforcedStyle, AllowedPatterns.
|
||||
# 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'
|
||||
@@ -195,23 +234,132 @@ Naming/MethodParameterName:
|
||||
Exclude:
|
||||
- 'engines/dfc_provider/lib/dfc_provider/catalog_item.rb'
|
||||
|
||||
# Offense count: 59
|
||||
# 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.
|
||||
# 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: 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.
|
||||
# Configuration parameters: EnforcedStyle, EnforcedStyleForClasses, EnforcedStyleForModules.
|
||||
# SupportedStyles: nested, compact
|
||||
# SupportedStylesForClasses: ~, nested, compact
|
||||
# SupportedStylesForModules: ~, nested, compact
|
||||
Style/ClassAndModuleChildren:
|
||||
Exclude:
|
||||
- 'app/models/calculator/flat_percent_per_item.rb'
|
||||
@@ -237,13 +385,33 @@ Style/ClassAndModuleChildren:
|
||||
- 'lib/open_food_network/locking.rb'
|
||||
- 'spec/models/spree/payment_method_spec.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# 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
|
||||
# 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
|
||||
@@ -274,3 +442,22 @@ 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.1.4
|
||||
3.2.9
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
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 +1,4 @@
|
||||
FROM ruby:3.1.4-alpine3.19 AS base
|
||||
FROM ruby:3.2.9-alpine3.19 AS base
|
||||
ENV LANG=C.UTF-8 \
|
||||
LC_ALL=C.UTF-8 \
|
||||
TZ=Europe/London \
|
||||
|
||||
12
Gemfile
12
Gemfile
@@ -27,7 +27,6 @@ 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"
|
||||
@@ -44,7 +43,7 @@ gem 'web', path: './engines/web'
|
||||
|
||||
gem "activerecord-postgresql-adapter"
|
||||
gem "arel-helpers", "~> 2.12"
|
||||
gem "pg", "~> 1.2.3"
|
||||
gem "pg"
|
||||
|
||||
gem 'acts_as_list', '1.0.4'
|
||||
gem 'cancancan', '~> 1.15.0'
|
||||
@@ -58,7 +57,7 @@ gem 'state_machines-activerecord'
|
||||
gem 'stringex', '~> 2.8.5', require: false
|
||||
|
||||
gem 'paypal-sdk-merchant', '1.117.2'
|
||||
gem 'stripe'
|
||||
gem 'stripe', '~> 13'
|
||||
|
||||
gem 'devise'
|
||||
gem 'devise-encryptable'
|
||||
@@ -186,16 +185,19 @@ group :test do
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem 'debugger-linecache'
|
||||
gem 'foreman'
|
||||
gem 'haml_lint', require: false
|
||||
gem 'i18n-tasks'
|
||||
gem 'listen'
|
||||
gem 'pry', '~> 0.13.0'
|
||||
gem 'pry'
|
||||
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'
|
||||
|
||||
214
Gemfile.lock
214
Gemfile.lock
@@ -122,17 +122,16 @@ GEM
|
||||
activemodel (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
timeout (>= 0.4.0)
|
||||
activerecord-import (1.6.0)
|
||||
activerecord-import (2.2.0)
|
||||
activerecord (>= 4.2)
|
||||
activerecord-postgresql-adapter (0.0.1)
|
||||
pg
|
||||
activerecord-session_store (2.1.0)
|
||||
actionpack (>= 6.1)
|
||||
activerecord (>= 6.1)
|
||||
activerecord-session_store (2.2.0)
|
||||
actionpack (>= 7.0)
|
||||
activerecord (>= 7.0)
|
||||
cgi (>= 0.3.6)
|
||||
multi_json (~> 1.11, >= 1.11.2)
|
||||
rack (>= 2.0.8, < 4)
|
||||
railties (>= 6.1)
|
||||
railties (>= 7.0)
|
||||
activestorage (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activejob (= 7.1.5.2)
|
||||
@@ -156,8 +155,8 @@ GEM
|
||||
activerecord (>= 6.1, < 7.2)
|
||||
acts_as_list (1.0.4)
|
||||
activerecord (>= 4.2)
|
||||
addressable (2.8.6)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
aes_key_wrap (1.1.0)
|
||||
afm (0.2.2)
|
||||
angular-rails-templates (1.2.1)
|
||||
@@ -192,9 +191,9 @@ GEM
|
||||
base64 (0.3.0)
|
||||
bcp47_spec (0.2.1)
|
||||
bcrypt (3.1.20)
|
||||
benchmark (0.4.1)
|
||||
bigdecimal (3.2.2)
|
||||
bindata (2.5.0)
|
||||
benchmark (0.5.0)
|
||||
bigdecimal (3.3.1)
|
||||
bindata (2.5.1)
|
||||
bindex (0.8.1)
|
||||
bootsnap (1.18.3)
|
||||
msgpack (~> 1.2)
|
||||
@@ -264,11 +263,10 @@ GEM
|
||||
database_cleaner-core (2.0.1)
|
||||
datafoodconsortium-connector (1.1.0)
|
||||
virtual_assembly-semantizer (~> 1.0, >= 1.0.5)
|
||||
date (3.4.1)
|
||||
date (3.5.0)
|
||||
debug (1.9.2)
|
||||
irb (~> 1.10)
|
||||
reline (>= 0.3.8)
|
||||
debugger-linecache (1.2.0)
|
||||
devise (4.9.4)
|
||||
bcrypt (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
@@ -299,8 +297,7 @@ GEM
|
||||
eventmachine (>= 1.0.0.beta.1)
|
||||
email_validator (2.2.4)
|
||||
activemodel
|
||||
erb (4.0.4)
|
||||
cgi (>= 0.3.3)
|
||||
erb (5.1.3)
|
||||
erubi (1.13.1)
|
||||
et-orbi (1.3.0)
|
||||
tzinfo
|
||||
@@ -315,9 +312,9 @@ GEM
|
||||
railties (>= 5.0.0)
|
||||
faraday (2.9.0)
|
||||
faraday-net_http (>= 2.0, < 3.2)
|
||||
faraday-follow_redirects (0.3.0)
|
||||
faraday-follow_redirects (0.4.0)
|
||||
faraday (>= 1, < 3)
|
||||
faraday-net_http (3.1.0)
|
||||
faraday-net_http (3.1.1)
|
||||
net-http
|
||||
ferrum (0.14)
|
||||
addressable (~> 2.5)
|
||||
@@ -331,13 +328,13 @@ GEM
|
||||
flipper-active_record (1.3.0)
|
||||
activerecord (>= 4.2, < 8)
|
||||
flipper (~> 1.3.0)
|
||||
flipper-ui (1.3.0)
|
||||
flipper-ui (1.3.6)
|
||||
erubi (>= 1.0.0, < 2.0.0)
|
||||
flipper (~> 1.3.0)
|
||||
flipper (~> 1.3.6)
|
||||
rack (>= 1.4, < 4)
|
||||
rack-protection (>= 1.5.3, < 5.0.0)
|
||||
rack-session (>= 1.0.2, < 3.0.0)
|
||||
sanitize (< 7)
|
||||
sanitize (< 8)
|
||||
fog-aws (2.0.1)
|
||||
fog-core (~> 1.38)
|
||||
fog-json (~> 1.0)
|
||||
@@ -364,7 +361,7 @@ GEM
|
||||
geocoder (1.8.3)
|
||||
base64 (>= 0.1.0)
|
||||
csv (>= 3.0.0)
|
||||
globalid (1.2.1)
|
||||
globalid (1.3.0)
|
||||
activesupport (>= 6.1)
|
||||
gmaps4rails (2.1.2)
|
||||
good_migrations (0.2.1)
|
||||
@@ -374,17 +371,23 @@ GEM
|
||||
temple (>= 0.8.2)
|
||||
thor
|
||||
tilt
|
||||
hashdiff (1.1.0)
|
||||
haml_lint (0.67.0)
|
||||
haml (>= 5.0)
|
||||
parallel (~> 1.10)
|
||||
rainbow
|
||||
rubocop (>= 1.0)
|
||||
sysexits (~> 1.1)
|
||||
hashdiff (1.2.1)
|
||||
hashery (2.1.2)
|
||||
hashie (5.0.0)
|
||||
highline (2.0.3)
|
||||
htmlentities (4.3.4)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (1.14.5)
|
||||
i18n (1.14.7)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-js (3.9.2)
|
||||
i18n (>= 0.6.6)
|
||||
i18n-tasks (1.0.14)
|
||||
i18n-tasks (1.0.15)
|
||||
activesupport (>= 4.0.2)
|
||||
ast (>= 2.1.0)
|
||||
erubi
|
||||
@@ -393,6 +396,7 @@ GEM
|
||||
parser (>= 3.2.2.1)
|
||||
rails-i18n
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
ruby-progressbar (~> 1.8, >= 1.8.1)
|
||||
terminal-table (>= 1.5.1)
|
||||
image_processing (1.12.2)
|
||||
mini_magick (>= 4.9.5, < 5)
|
||||
@@ -405,7 +409,7 @@ GEM
|
||||
rails (>= 5.2)
|
||||
io-console (0.8.1)
|
||||
ipaddress (0.8.3)
|
||||
irb (1.15.2)
|
||||
irb (1.15.3)
|
||||
pp (>= 0.6.0)
|
||||
rdoc (>= 4.0.0)
|
||||
reline (>= 0.4.2)
|
||||
@@ -416,9 +420,9 @@ GEM
|
||||
thor (>= 0.14, < 2.0)
|
||||
jquery-ui-rails (4.2.1)
|
||||
railties (>= 3.2.16)
|
||||
json (2.7.2)
|
||||
json (2.15.2)
|
||||
json-canonicalization (1.0.0)
|
||||
json-jwt (1.16.6)
|
||||
json-jwt (1.17.0)
|
||||
activesupport (>= 4.2)
|
||||
aes_key_wrap
|
||||
base64
|
||||
@@ -442,15 +446,16 @@ GEM
|
||||
activesupport (>= 4.2)
|
||||
jwt (2.8.1)
|
||||
base64
|
||||
knapsack_pro (8.1.2)
|
||||
knapsack_pro (8.4.0)
|
||||
rake
|
||||
language_server-protocol (3.17.0.3)
|
||||
language_server-protocol (3.17.0.5)
|
||||
launchy (3.0.0)
|
||||
addressable (~> 2.8)
|
||||
childprocess (~> 5.0)
|
||||
letter_opener (1.10.0)
|
||||
launchy (>= 2.2, < 4)
|
||||
link_header (0.0.8)
|
||||
lint_roller (1.1.0)
|
||||
listen (3.9.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
@@ -458,7 +463,8 @@ GEM
|
||||
loofah (2.24.1)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
mail (2.8.1)
|
||||
mail (2.9.0)
|
||||
logger
|
||||
mini_mime (>= 0.1.1)
|
||||
net-imap
|
||||
net-pop
|
||||
@@ -473,28 +479,28 @@ GEM
|
||||
mimemagic (0.4.3)
|
||||
nokogiri (~> 1)
|
||||
rake
|
||||
mini_magick (4.11.0)
|
||||
mini_magick (4.13.2)
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.6)
|
||||
minitest (5.25.5)
|
||||
minitest (5.26.1)
|
||||
monetize (1.13.0)
|
||||
money (~> 6.12)
|
||||
money (6.16.0)
|
||||
i18n (>= 0.6.4, <= 2)
|
||||
msgpack (1.7.2)
|
||||
multi_json (1.15.0)
|
||||
multi_json (1.17.0)
|
||||
multi_xml (0.6.0)
|
||||
mutex_m (0.3.0)
|
||||
net-http (0.4.1)
|
||||
net-http (0.7.0)
|
||||
uri
|
||||
net-imap (0.4.20)
|
||||
net-imap (0.5.12)
|
||||
date
|
||||
net-protocol
|
||||
net-pop (0.1.2)
|
||||
net-protocol
|
||||
net-protocol (0.2.2)
|
||||
timeout
|
||||
net-smtp (0.5.0)
|
||||
net-smtp (0.5.1)
|
||||
net-protocol
|
||||
newrelic_rpm (9.22.0)
|
||||
nio4r (2.7.1)
|
||||
@@ -510,17 +516,18 @@ GEM
|
||||
multi_xml (~> 0.5)
|
||||
rack (>= 1.2, < 4)
|
||||
observer (0.1.2)
|
||||
omniauth (2.1.2)
|
||||
omniauth (2.1.4)
|
||||
hashie (>= 3.4.6)
|
||||
logger
|
||||
rack (>= 2.2.3)
|
||||
rack-protection
|
||||
omniauth-rails_csrf_protection (1.0.2)
|
||||
actionpack (>= 4.2)
|
||||
omniauth (~> 2.0)
|
||||
omniauth_openid_connect (0.7.1)
|
||||
omniauth_openid_connect (0.8.0)
|
||||
omniauth (>= 1.9, < 3)
|
||||
openid_connect (~> 2.2)
|
||||
openid_connect (2.3.0)
|
||||
openid_connect (2.3.1)
|
||||
activemodel
|
||||
attr_required (>= 1.0.0)
|
||||
email_validator
|
||||
@@ -539,10 +546,10 @@ GEM
|
||||
paper_trail (15.1.0)
|
||||
activerecord (>= 6.1)
|
||||
request_store (~> 1.4)
|
||||
parallel (1.24.0)
|
||||
paranoia (2.6.3)
|
||||
parallel (1.27.0)
|
||||
paranoia (2.6.4)
|
||||
activerecord (>= 5.1, < 7.2)
|
||||
parser (3.3.9.0)
|
||||
parser (3.3.10.0)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
paypal-sdk-core (0.3.4)
|
||||
@@ -556,18 +563,19 @@ GEM
|
||||
hashery (~> 2.0)
|
||||
ruby-rc4
|
||||
ttfunk
|
||||
pg (1.2.3)
|
||||
pp (0.6.2)
|
||||
pg (1.6.2)
|
||||
pp (0.6.3)
|
||||
prettyprint
|
||||
prettyprint (0.2.0)
|
||||
prism (1.6.0)
|
||||
private_address_check (0.5.0)
|
||||
pry (0.13.1)
|
||||
pry (0.15.2)
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
psych (5.2.6)
|
||||
date
|
||||
stringio
|
||||
public_suffix (5.0.5)
|
||||
public_suffix (6.0.2)
|
||||
puffing-billy (4.0.2)
|
||||
addressable (~> 2.5)
|
||||
em-http-request (~> 1.1, >= 1.1.0)
|
||||
@@ -583,10 +591,10 @@ GEM
|
||||
railties (>= 4.2)
|
||||
raabro (1.4.0)
|
||||
racc (1.8.1)
|
||||
rack (2.2.20)
|
||||
rack (2.2.21)
|
||||
rack-mini-profiler (2.3.4)
|
||||
rack (>= 1.2.0)
|
||||
rack-oauth2 (2.2.1)
|
||||
rack-oauth2 (2.3.0)
|
||||
activesupport
|
||||
attr_required
|
||||
faraday (~> 2.0)
|
||||
@@ -640,7 +648,6 @@ GEM
|
||||
rails-i18n (7.0.10)
|
||||
i18n (>= 0.7, < 2)
|
||||
railties (>= 6.0.0, < 8)
|
||||
rails_safe_tasks (1.0.0)
|
||||
railties (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
@@ -650,7 +657,7 @@ GEM
|
||||
thor (~> 1.0, >= 1.2.2)
|
||||
zeitwerk (~> 2.6)
|
||||
rainbow (3.1.1)
|
||||
rake (13.3.0)
|
||||
rake (13.3.1)
|
||||
ransack (4.1.1)
|
||||
activerecord (>= 6.1.5)
|
||||
activesupport (>= 6.1.5)
|
||||
@@ -662,7 +669,7 @@ GEM
|
||||
bcp47_spec (~> 0.2)
|
||||
bigdecimal (~> 3.1, >= 3.1.5)
|
||||
link_header (~> 0.0, >= 0.0.8)
|
||||
rdoc (6.15.0)
|
||||
rdoc (6.15.1)
|
||||
erb
|
||||
psych (>= 4.0.0)
|
||||
tsort
|
||||
@@ -671,7 +678,7 @@ GEM
|
||||
redis-client (>= 0.22.0)
|
||||
redis-client (0.26.1)
|
||||
connection_pool
|
||||
regexp_parser (2.9.2)
|
||||
regexp_parser (2.11.3)
|
||||
reline (0.6.2)
|
||||
io-console (~> 0.5)
|
||||
request_store (1.5.1)
|
||||
@@ -734,35 +741,39 @@ GEM
|
||||
rswag-ui (2.16.0)
|
||||
actionpack (>= 5.2, < 8.1)
|
||||
railties (>= 5.2, < 8.1)
|
||||
rubocop (1.64.1)
|
||||
rubocop (1.81.6)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (>= 3.17.0)
|
||||
language_server-protocol (~> 3.17.0.2)
|
||||
lint_roller (~> 1.1.0)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.3.0.2)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.8, < 3.0)
|
||||
rexml (>= 3.2.5, < 4.0)
|
||||
rubocop-ast (>= 1.31.1, < 2.0)
|
||||
regexp_parser (>= 2.9.3, < 3.0)
|
||||
rubocop-ast (>= 1.47.1, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 2.4.0, < 3.0)
|
||||
rubocop-ast (1.31.3)
|
||||
parser (>= 3.3.1.0)
|
||||
rubocop-capybara (2.20.0)
|
||||
rubocop (~> 1.41)
|
||||
rubocop-factory_bot (2.25.1)
|
||||
rubocop (~> 1.41)
|
||||
rubocop-rails (2.28.0)
|
||||
unicode-display_width (>= 2.4.0, < 4.0)
|
||||
rubocop-ast (1.47.1)
|
||||
parser (>= 3.3.7.2)
|
||||
prism (~> 1.4)
|
||||
rubocop-capybara (2.22.1)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-factory_bot (2.27.1)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-rails (2.33.4)
|
||||
activesupport (>= 4.2.0)
|
||||
lint_roller (~> 1.1)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 1.52.0, < 2.0)
|
||||
rubocop-ast (>= 1.31.1, < 2.0)
|
||||
rubocop-rspec (2.29.2)
|
||||
rubocop (~> 1.40)
|
||||
rubocop-capybara (~> 2.17)
|
||||
rubocop-factory_bot (~> 2.22)
|
||||
rubocop-rspec_rails (~> 2.28)
|
||||
rubocop-rspec_rails (2.28.3)
|
||||
rubocop (~> 1.40)
|
||||
rubocop (>= 1.75.0, < 2.0)
|
||||
rubocop-ast (>= 1.44.0, < 2.0)
|
||||
rubocop-rspec (3.7.0)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-rspec_rails (2.31.0)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-rspec (~> 3.5)
|
||||
ruby-graphviz (1.2.5)
|
||||
rexml
|
||||
ruby-progressbar (1.13.0)
|
||||
@@ -773,9 +784,9 @@ GEM
|
||||
rufus-scheduler (3.8.2)
|
||||
fugit (~> 1.1, >= 1.1.6)
|
||||
rugged (1.9.0)
|
||||
sanitize (6.1.0)
|
||||
sanitize (7.0.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
nokogiri (>= 1.16.8)
|
||||
sass (3.4.25)
|
||||
sass-rails (5.0.8)
|
||||
railties (>= 5.2.0)
|
||||
@@ -806,7 +817,7 @@ GEM
|
||||
spreadsheet_architect (5.0.0)
|
||||
caxlsx (>= 3.3.0, < 4)
|
||||
rodf (>= 1.0.0, < 2)
|
||||
spring (4.2.1)
|
||||
spring (4.4.0)
|
||||
spring-commands-rspec (1.0.4)
|
||||
spring (>= 0.9.1)
|
||||
spring-commands-rubocop (0.4.0)
|
||||
@@ -819,13 +830,13 @@ GEM
|
||||
actionpack (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
sprockets (>= 3.0.0)
|
||||
state_machines (0.6.0)
|
||||
state_machines-activemodel (0.9.0)
|
||||
activemodel (>= 6.0)
|
||||
state_machines (>= 0.6.0)
|
||||
state_machines-activerecord (0.9.0)
|
||||
activerecord (>= 6.0)
|
||||
state_machines-activemodel (>= 0.9.0)
|
||||
state_machines (0.20.0)
|
||||
state_machines-activemodel (0.10.0)
|
||||
activemodel (>= 7.1)
|
||||
state_machines (>= 0.10.0)
|
||||
state_machines-activerecord (0.31.0)
|
||||
activerecord (>= 7.1)
|
||||
state_machines-activemodel (>= 0.10.0)
|
||||
stimulus_reflex (3.5.5)
|
||||
actioncable (>= 5.2)
|
||||
actionpack (>= 5.2)
|
||||
@@ -840,20 +851,21 @@ GEM
|
||||
redis (>= 4.0, < 6.0)
|
||||
stringex (2.8.6)
|
||||
stringio (3.1.7)
|
||||
stripe (11.1.0)
|
||||
strscan (3.1.2)
|
||||
stripe (13.5.1)
|
||||
strscan (3.1.5)
|
||||
swd (2.0.3)
|
||||
activesupport (>= 3)
|
||||
attr_required (>= 0.0.5)
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects
|
||||
sysexits (1.2.0)
|
||||
temple (0.8.2)
|
||||
terminal-table (4.0.0)
|
||||
unicode-display_width (>= 1.1.1, < 4)
|
||||
thor (1.4.0)
|
||||
thread-local (1.1.0)
|
||||
tilt (2.3.0)
|
||||
timeout (0.4.3)
|
||||
timeout (0.4.4)
|
||||
tsort (0.2.0)
|
||||
ttfunk (1.8.0)
|
||||
bigdecimal (~> 3.1)
|
||||
@@ -861,7 +873,7 @@ GEM
|
||||
actionpack (>= 6.0.0)
|
||||
activejob (>= 6.0.0)
|
||||
railties (>= 6.0.0)
|
||||
turbo_power (0.6.2)
|
||||
turbo_power (0.7.0)
|
||||
turbo-rails (>= 1.3.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
@@ -873,9 +885,11 @@ GEM
|
||||
rugged (>= 0.27, < 1.10)
|
||||
simplecov
|
||||
simplecov_json_formatter
|
||||
unicode-display_width (2.5.0)
|
||||
unicode-display_width (3.2.0)
|
||||
unicode-emoji (~> 4.1)
|
||||
unicode-emoji (4.1.0)
|
||||
uniform_notifier (1.17.0)
|
||||
uri (0.13.2)
|
||||
uri (1.1.1)
|
||||
valid_email2 (5.2.3)
|
||||
activemodel (>= 3.2)
|
||||
mail (~> 2.5)
|
||||
@@ -906,7 +920,7 @@ GEM
|
||||
activesupport
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects
|
||||
webmock (3.23.1)
|
||||
webmock (3.25.1)
|
||||
addressable (>= 2.8.0)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
@@ -927,7 +941,7 @@ GEM
|
||||
xml-simple (1.1.8)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.6.18)
|
||||
zeitwerk (2.7.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
@@ -964,7 +978,6 @@ DEPENDENCIES
|
||||
datafoodconsortium-connector
|
||||
db2fog!
|
||||
debug (>= 1.0.0)
|
||||
debugger-linecache
|
||||
devise
|
||||
devise-encryptable
|
||||
devise-i18n
|
||||
@@ -985,6 +998,7 @@ DEPENDENCIES
|
||||
gmaps4rails
|
||||
good_migrations
|
||||
haml
|
||||
haml_lint
|
||||
highline (= 2.0.3)
|
||||
i18n
|
||||
i18n-js (~> 3.9.0)
|
||||
@@ -1016,9 +1030,9 @@ DEPENDENCIES
|
||||
paranoia (~> 2.4)
|
||||
paypal-sdk-merchant (= 1.117.2)
|
||||
pdf-reader
|
||||
pg (~> 1.2.3)
|
||||
pg
|
||||
private_address_check
|
||||
pry (~> 0.13.0)
|
||||
pry
|
||||
puffing-billy
|
||||
puma
|
||||
query_count
|
||||
@@ -1029,7 +1043,6 @@ DEPENDENCIES
|
||||
rails-controller-testing
|
||||
rails-erd
|
||||
rails-i18n
|
||||
rails_safe_tasks (~> 1.0)
|
||||
ransack (~> 4.1.0)
|
||||
redcarpet
|
||||
redis
|
||||
@@ -1043,8 +1056,11 @@ DEPENDENCIES
|
||||
rswag-api
|
||||
rswag-ui
|
||||
rubocop
|
||||
rubocop-capybara
|
||||
rubocop-factory_bot
|
||||
rubocop-rails
|
||||
rubocop-rspec
|
||||
rubocop-rspec_rails
|
||||
sd_notify
|
||||
select2-rails!
|
||||
shoulda-matchers
|
||||
@@ -1060,7 +1076,7 @@ DEPENDENCIES
|
||||
stimulus_reflex
|
||||
stimulus_reflex_testing!
|
||||
stringex (~> 2.8.5)
|
||||
stripe
|
||||
stripe (~> 13)
|
||||
turbo-rails
|
||||
turbo_power
|
||||
undercover
|
||||
@@ -1078,7 +1094,7 @@ DEPENDENCIES
|
||||
wkhtmltopdf-binary
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.4p223
|
||||
ruby 3.2.9p265
|
||||
|
||||
BUNDLED WITH
|
||||
2.4.3
|
||||
2.4.19
|
||||
|
||||
@@ -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 ofnEmptiesCart
|
||||
# To be used with ofnChangeHub
|
||||
# Takes "change" and "shop" as text string attributes
|
||||
restrict: "A"
|
||||
scope:
|
||||
|
||||
@@ -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", "ofn-empties-cart" => "hub",
|
||||
"ng-href" => "{{::hub.path}}#/shop_panel",
|
||||
"ng-class" => "::{primary: hub.active, secondary: !hub.active}",
|
||||
"ng-click" => "$close()",
|
||||
"ofn-change-hub" => "hub"}
|
||||
|
||||
@@ -30,7 +30,7 @@ class SearchableDropdownComponent < ViewComponent::Base
|
||||
:aria_label, :other_attrs
|
||||
|
||||
def classes
|
||||
"fullwidth #{remove_search_plugin? ? 'no-input' : ''}"
|
||||
"fullwidth #{'no-input' if remove_search_plugin?}"
|
||||
end
|
||||
|
||||
def data
|
||||
|
||||
@@ -5,16 +5,19 @@ class TagListInputComponent < ViewComponent::Base
|
||||
placeholder: I18n.t("components.tag_list_input.default_placeholder"),
|
||||
only_one: false,
|
||||
aria_label: nil,
|
||||
hidden_field_data_options: {})
|
||||
hidden_field_data_options: {},
|
||||
autocomplete_url: "")
|
||||
@name = name
|
||||
@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
|
||||
attr_reader :name, :tags, :placeholder, :only_one, :aria_label_option,
|
||||
:hidden_field_data_options, :autocomplete_url
|
||||
|
||||
private
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
%div{ "data-controller": "tag-list-input", "data-tag-list-input-only-one-value": "#{only_one}" }
|
||||
%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" }
|
||||
.tags-input
|
||||
.tags
|
||||
- # We use display:none instead of hidden field, so changes to the value can be picked up by the bulkFormController
|
||||
@@ -16,4 +16,12 @@
|
||||
%span=tag
|
||||
%a.remove-button{ "data-action": "click->tag-list-input#removeTag" }
|
||||
×
|
||||
= text_field_tag "variant_add_tag", nil, class: "input", placeholder: placeholder, "data-action": "keydown.enter->tag-list-input#addTag keyup->tag-list-input#filterInput blur->tag-list-input#addTag", "data-tag-list-input-target": "newTag", **aria_label_option, style: "display: #{display};"
|
||||
= 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 }
|
||||
|
||||
@@ -67,4 +67,35 @@
|
||||
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,14 +1,23 @@
|
||||
import { Controller } from "stimulus";
|
||||
import { Autocomplete } from "stimulus-autocomplete";
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["tagList", "newTag", "template", "list"];
|
||||
// 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 };
|
||||
|
||||
addTag(event) {
|
||||
// prevent hotkey form submitting the form (default action for "enter" key)
|
||||
event.preventDefault();
|
||||
connect() {
|
||||
// Don't start autocomplete controller if we don't have an url
|
||||
if (this.urlValue.length == 0) return;
|
||||
|
||||
const newTagName = this.newTagTarget.value.trim().replaceAll(" ", "-");
|
||||
super.connect();
|
||||
}
|
||||
|
||||
addTag(event) {
|
||||
const newTagName = this.inputTarget.value.trim().replaceAll(" ", "-");
|
||||
if (newTagName.length == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -18,7 +27,7 @@ export default class extends Controller {
|
||||
const index = tags.indexOf(newTagName);
|
||||
if (index != -1) {
|
||||
// highlight the value in red
|
||||
this.newTagTarget.classList.add("tag-error");
|
||||
this.inputTarget.classList.add("tag-error");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -38,14 +47,23 @@ export default class extends Controller {
|
||||
this.listTarget.appendChild(newTagElement);
|
||||
|
||||
// Clear new tag value
|
||||
this.newTagTarget.value = "";
|
||||
this.inputTarget.value = "";
|
||||
|
||||
// hide tag input if limited to one tag
|
||||
if (this.tagListTarget.value.split(",").length == 1 && this.onlyOneValue == true) {
|
||||
this.newTagTarget.style.display = "none";
|
||||
this.inputTarget.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
keyboardAddTag(event) {
|
||||
// prevent hotkey form submitting the form (default action for "enter" key)
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
this.addTag();
|
||||
}
|
||||
|
||||
removeTag(event) {
|
||||
// Text to remove
|
||||
const tagName = event.srcElement.previousElementSibling.textContent;
|
||||
@@ -62,14 +80,14 @@ export default class extends Controller {
|
||||
|
||||
// Make sure the tag input is displayed
|
||||
if (this.tagListTarget.value.length == 0) {
|
||||
this.newTagTarget.style.display = "block";
|
||||
this.inputTarget.style.display = "block";
|
||||
}
|
||||
}
|
||||
|
||||
filterInput(event) {
|
||||
// clear error class if key is not enter
|
||||
if (event.key !== "Enter") {
|
||||
this.newTagTarget.classList.remove("tag-error");
|
||||
this.inputTarget.classList.remove("tag-error");
|
||||
}
|
||||
|
||||
// Strip comma from tag name
|
||||
@@ -77,4 +95,53 @@ export default class extends Controller {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,13 @@ class TagRuleFormComponent < ViewComponent::Base
|
||||
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
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
module Admin
|
||||
class BulkLineItemsController < Spree::Admin::BaseController
|
||||
include PaginationData
|
||||
|
||||
# GET /admin/bulk_line_items.json
|
||||
#
|
||||
def index
|
||||
|
||||
@@ -51,6 +51,7 @@ module Admin
|
||||
|
||||
load_tag_rule_types
|
||||
|
||||
load_tag_rules
|
||||
return unless params[:stimulus]
|
||||
|
||||
@enterprise.is_primary_producer = params[:is_primary_producer]
|
||||
@@ -84,6 +85,7 @@ module Admin
|
||||
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
|
||||
@@ -398,9 +400,26 @@ module Admin
|
||||
[t(".form.tag_rules.show_hide_order_cycles"), "FilterOrderCycles"]
|
||||
]
|
||||
|
||||
return unless helpers.feature?(:inventory, @object)
|
||||
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
|
||||
|
||||
@tag_rule_types.prepend([t(".form.tag_rules.show_hide_variants"), "FilterProducts"])
|
||||
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
|
||||
end
|
||||
|
||||
def setup_property
|
||||
|
||||
@@ -4,6 +4,7 @@ module Admin
|
||||
class ReportsController < Spree::Admin::BaseController
|
||||
include ActiveStorage::SetCurrent
|
||||
include ReportsActions
|
||||
|
||||
helper ReportsHelper
|
||||
|
||||
before_action :authorize_report, only: [:show, :create]
|
||||
|
||||
@@ -41,6 +41,7 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
# Used by the tag input autocomplete
|
||||
def map_by_tag
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
@@ -50,6 +51,26 @@ 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
|
||||
@@ -78,7 +99,7 @@ module Admin
|
||||
end
|
||||
|
||||
def permitted_tag_rule_type
|
||||
%w{FilterOrderCycles FilterPaymentMethods FilterProducts FilterShippingMethods}
|
||||
%w{FilterOrderCycles FilterPaymentMethods FilterProducts FilterShippingMethods FilterVariants}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,6 +7,7 @@ module Api
|
||||
module V0
|
||||
class ExchangeProductsController < Api::V0::BaseController
|
||||
include PaginationData
|
||||
|
||||
DEFAULT_PER_PAGE = 100
|
||||
|
||||
skip_authorization_check only: [:index]
|
||||
|
||||
@@ -23,7 +23,8 @@ module Api
|
||||
order_cycle,
|
||||
customer,
|
||||
search_params,
|
||||
inventory_enabled:
|
||||
inventory_enabled:,
|
||||
variant_tag_enabled:
|
||||
).products_json
|
||||
|
||||
render plain: products
|
||||
@@ -96,13 +97,17 @@ module Api
|
||||
|
||||
def distributed_products
|
||||
OrderCycles::DistributedProductsService.new(
|
||||
distributor, order_cycle, customer, inventory_enabled:
|
||||
distributor, order_cycle, customer, inventory_enabled:, variant_tag_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,6 +7,7 @@ module Api
|
||||
module V0
|
||||
class ProductsController < Api::V0::BaseController
|
||||
include PaginationData
|
||||
|
||||
respond_to :json
|
||||
DEFAULT_PER_PAGE = 15
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@ 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]
|
||||
@@ -88,7 +92,8 @@ 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,
|
||||
|
||||
@@ -20,25 +20,43 @@ module OrderStockCheck
|
||||
@updated_variants = check_stock_service.update_line_items
|
||||
end
|
||||
|
||||
def check_order_cycle_expiry
|
||||
def check_order_cycle_expiry(should_empty_order: true)
|
||||
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
|
||||
|
||||
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
|
||||
handle_closed_order_cycle if should_empty_order
|
||||
|
||||
flash[:info] = build_order_cycle_message(should_empty_order)
|
||||
redirect_to_shop_page(should_empty_order)
|
||||
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
|
||||
|
||||
@@ -8,7 +8,9 @@ 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, only: [:express, :confirm]
|
||||
before_action -> { check_order_cycle_expiry(should_empty_order: false) }, 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, only: :confirm
|
||||
before_action -> { check_order_cycle_expiry(should_empty_order: false) }, only: :confirm
|
||||
|
||||
def confirm
|
||||
validate_stock
|
||||
|
||||
@@ -6,6 +6,7 @@ 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,6 +10,12 @@ 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
|
||||
|
||||
@@ -89,8 +95,9 @@ module Spree
|
||||
@payment_method = PaymentMethod.find(params[:pm_id])
|
||||
end
|
||||
else
|
||||
@payment_method = params[:provider_type].constantize.new
|
||||
@payment_method = PAYMENT_METHODS.fetch(params[:provider_type], PaymentMethod).new
|
||||
end
|
||||
|
||||
render partial: 'provider_settings'
|
||||
end
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ module Spree
|
||||
include OpenFoodNetwork::SpreeApiKeyLoader
|
||||
include OrderCyclesHelper
|
||||
include EnterprisesHelper
|
||||
|
||||
helper ::Admin::ProductsHelper
|
||||
helper Spree::Admin::TaxCategoriesHelper
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ module Spree
|
||||
include Spree::Core::ControllerHelpers::Order
|
||||
|
||||
include I18nHelper
|
||||
|
||||
before_action :set_locale
|
||||
|
||||
# Devise::PasswordsController allows for blank passwords.
|
||||
|
||||
@@ -36,9 +36,7 @@ class ScheduleForm
|
||||
false unless @schedule.update(permitted_resource_params)
|
||||
end
|
||||
|
||||
def order_cycle_ids
|
||||
@schedule.order_cycle_ids
|
||||
end
|
||||
delegate :order_cycle_ids, to: :@schedule
|
||||
|
||||
private
|
||||
|
||||
|
||||
@@ -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, *args, &)
|
||||
def method_missing(method, *, &)
|
||||
if method.to_s.end_with?('_path', '_url') && spree.respond_to?(method)
|
||||
spree.public_send(method, *args)
|
||||
spree.public_send(method, *)
|
||||
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.to_s }
|
||||
locals: { name: 'enterpriseAttributes', json: enterprise_attributes.to_json }
|
||||
end
|
||||
|
||||
def inject_saved_credit_cards
|
||||
|
||||
@@ -44,9 +44,7 @@ module ReportsHelper
|
||||
.pluck(:name, :id)
|
||||
end
|
||||
|
||||
def currency_symbol
|
||||
Spree::Money.currency_symbol
|
||||
end
|
||||
delegate :currency_symbol, to: :'Spree::Money'
|
||||
|
||||
def enterprise_fee_owner_ids(orders)
|
||||
EnterpriseFee.where(id: enterprise_fee_ids(orders))
|
||||
|
||||
@@ -10,9 +10,7 @@ module TermsAndConditionsHelper
|
||||
TermsOfService.required?(distributor)
|
||||
end
|
||||
|
||||
def platform_terms_required?
|
||||
TermsOfService.platform_terms_required?
|
||||
end
|
||||
delegate :platform_terms_required?, to: :TermsOfService
|
||||
|
||||
def distributor_terms_required?
|
||||
TermsOfService.distributor_terms_required?(current_order.distributor)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
class BulkInvoiceJob < ApplicationJob
|
||||
include CableReady::Broadcaster
|
||||
|
||||
delegate :render, to: ActionController::Base
|
||||
attr_reader :options
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# Renders a report and stores it in a given blob.
|
||||
class ReportJob < ApplicationJob
|
||||
include CableReady::Broadcaster
|
||||
|
||||
delegate :render, to: ActionController::Base
|
||||
|
||||
before_perform :enable_active_storage_urls
|
||||
|
||||
@@ -29,7 +29,7 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def url_for(*args)
|
||||
Rails.application.routes.url_helpers.url_for(*args)
|
||||
def url_for(*)
|
||||
Rails.application.routes.url_helpers.url_for(*)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,6 +4,7 @@ require 'active_support/concern'
|
||||
|
||||
module LogDestroyPerformer
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
attr_accessor :destroyed_by
|
||||
|
||||
|
||||
@@ -25,11 +25,13 @@ class Customer < ApplicationRecord
|
||||
before_destroy :update_orders_and_delete_canceled_subscriptions
|
||||
|
||||
belongs_to :bill_address, class_name: "Spree::Address", optional: true
|
||||
alias_attribute :billing_address, :bill_address
|
||||
alias_method :billing_address, :bill_address
|
||||
alias_method :billing_address=, :bill_address=
|
||||
accepts_nested_attributes_for :bill_address
|
||||
|
||||
belongs_to :ship_address, class_name: "Spree::Address", optional: true
|
||||
alias_attribute :shipping_address, :ship_address
|
||||
alias_method :shipping_address, :ship_address
|
||||
alias_method :shipping_address=, :ship_address=
|
||||
accepts_nested_attributes_for :ship_address
|
||||
|
||||
validates :code, uniqueness: { scope: :enterprise_id, allow_nil: true }
|
||||
|
||||
@@ -408,7 +408,7 @@ class Enterprise < ApplicationRecord
|
||||
def category
|
||||
# Make this crazy logic human readable so we can argue about it sanely.
|
||||
cat = is_primary_producer ? "producer_" : "non_producer_"
|
||||
cat << ("sells_#{sells}")
|
||||
cat << "sells_#{sells}"
|
||||
|
||||
# Map backend cases to front end cases.
|
||||
case cat
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
class Invoice
|
||||
class DataPresenter
|
||||
include ::ActionView::Helpers::NumberHelper
|
||||
|
||||
attr_reader :invoice
|
||||
|
||||
delegate :display_number, :data, :previous_invoice, to: :invoice
|
||||
@@ -142,7 +143,7 @@ class Invoice
|
||||
end
|
||||
|
||||
def paid?
|
||||
data[:payment_state] == 'paid' || data[:payment_state] == 'credit_owed'
|
||||
['paid', 'credit_owed'].include?(data[:payment_state])
|
||||
end
|
||||
|
||||
def outstanding_balance?
|
||||
|
||||
@@ -4,6 +4,7 @@ class Invoice
|
||||
class DataPresenter
|
||||
class Base
|
||||
include ::ActionView::Helpers::NumberHelper
|
||||
|
||||
attr_reader :data
|
||||
|
||||
def initialize(data)
|
||||
|
||||
@@ -81,17 +81,13 @@ module ProductImport
|
||||
@reset_counts
|
||||
end
|
||||
|
||||
def enterprises_index
|
||||
@spreadsheet_data.enterprises_index
|
||||
end
|
||||
delegate :enterprises_index, to: :@spreadsheet_data
|
||||
|
||||
def enterprise_products
|
||||
@processor&.enterprise_products
|
||||
end
|
||||
|
||||
def total_enterprise_products
|
||||
@processor.total_enterprise_products
|
||||
end
|
||||
delegate :total_enterprise_products, to: :@processor
|
||||
|
||||
def entries_json
|
||||
entries = {}
|
||||
@@ -130,13 +126,9 @@ module ProductImport
|
||||
@processor.inventory_updated
|
||||
end
|
||||
|
||||
def products_reset_count
|
||||
@processor.products_reset_count
|
||||
end
|
||||
delegate :products_reset_count, to: :@processor
|
||||
|
||||
def total_saved_count
|
||||
@processor.total_saved_count
|
||||
end
|
||||
delegate :total_saved_count, to: :@processor
|
||||
|
||||
def import_results
|
||||
{ entries: entries_json, reset_counts: }
|
||||
@@ -183,7 +175,7 @@ module ProductImport
|
||||
end
|
||||
|
||||
def staged_import?
|
||||
@import_settings&.key?(:start) && @import_settings&.key?(:end)
|
||||
@import_settings&.key?(:start) && @import_settings.key?(:end)
|
||||
end
|
||||
|
||||
def init_permissions
|
||||
|
||||
@@ -143,7 +143,7 @@ module Spree
|
||||
can [:admin, :index, :read, :create, :edit, :update_positions, :destroy], ProducerProperty
|
||||
|
||||
can :new, TagRule
|
||||
can [:admin, :map_by_tag, :destroy], TagRule do |tag_rule|
|
||||
can [:admin, :map_by_tag, :destroy, :variant_tag_rules], TagRule do |tag_rule|
|
||||
user.enterprises.include? tag_rule.enterprise
|
||||
end
|
||||
|
||||
|
||||
@@ -31,9 +31,7 @@ module Spree
|
||||
self.class.name.titleize.gsub("Calculator/", "")
|
||||
end
|
||||
|
||||
def description
|
||||
self.class.description
|
||||
end
|
||||
delegate :description, to: :class
|
||||
|
||||
def available?(_object)
|
||||
true
|
||||
|
||||
@@ -34,11 +34,11 @@ module Spree
|
||||
@provider.respond_to?(method_name, include_private) || super
|
||||
end
|
||||
|
||||
def method_missing(method, *args)
|
||||
def method_missing(method, *)
|
||||
if @provider.nil? || !@provider.respond_to?(method)
|
||||
super
|
||||
else
|
||||
provider.__send__(method, *args)
|
||||
provider.__send__(method, *)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -35,10 +35,12 @@ module Spree
|
||||
belongs_to :created_by, class_name: "Spree::User", optional: true
|
||||
|
||||
belongs_to :bill_address, class_name: 'Spree::Address', optional: true
|
||||
alias_attribute :billing_address, :bill_address
|
||||
alias_method :billing_address, :bill_address
|
||||
alias_method :billing_address=, :bill_address=
|
||||
|
||||
belongs_to :ship_address, class_name: 'Spree::Address', optional: true
|
||||
alias_attribute :shipping_address, :ship_address
|
||||
alias_method :shipping_address, :ship_address
|
||||
alias_method :shipping_address=, :ship_address=
|
||||
|
||||
has_many :state_changes, as: :stateful, dependent: :destroy
|
||||
has_many :line_items, -> {
|
||||
@@ -97,7 +99,7 @@ module Spree
|
||||
}
|
||||
validate :disallow_guest_order
|
||||
validates :email, presence: true,
|
||||
format: /\A([\w.%+\-']+)@([\w\-]+\.)+(\w{2,})\z/i,
|
||||
format: /\A([\w.%+\-']+)@([\w-]+\.)+(\w{2,})\z/i,
|
||||
if: :require_email
|
||||
|
||||
validates :order_cycle, presence: true, on: :require_distribution
|
||||
@@ -417,7 +419,7 @@ module Spree
|
||||
|
||||
# Helper methods for checkout steps
|
||||
def paid?
|
||||
payment_state == 'paid' || payment_state == 'credit_owed'
|
||||
['paid', 'credit_owed'].include?(payment_state)
|
||||
end
|
||||
|
||||
# "Checkout" is the initial state and, for card payments, "pending" is the state after auth
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
module Spree
|
||||
class ShippingMethod < ApplicationRecord
|
||||
include CalculatedAdjustments
|
||||
|
||||
DISPLAY_ON_OPTIONS = {
|
||||
both: "",
|
||||
back_end: "back_end"
|
||||
|
||||
@@ -56,8 +56,8 @@ module Spree
|
||||
|
||||
# Send devise-based user emails asyncronously via ActiveJob
|
||||
# See: https://github.com/heartcombo/devise/tree/v3.5.10#activejob-integration
|
||||
def send_devise_notification(notification, *args)
|
||||
devise_mailer.public_send(notification, self, *args).deliver_later
|
||||
def send_devise_notification(notification, *)
|
||||
devise_mailer.public_send(notification, self, *).deliver_later
|
||||
end
|
||||
|
||||
def regenerate_reset_password_token
|
||||
|
||||
@@ -24,8 +24,10 @@ class Subscription < ApplicationRecord
|
||||
has_many :proxy_orders, dependent: :destroy
|
||||
has_many :orders, through: :proxy_orders
|
||||
|
||||
alias_attribute :billing_address, :bill_address
|
||||
alias_attribute :shipping_address, :ship_address
|
||||
alias_method :billing_address, :bill_address
|
||||
alias_method :billing_address=, :bill_address=
|
||||
alias_method :shipping_address, :ship_address
|
||||
alias_method :shipping_address=, :ship_address=
|
||||
|
||||
accepts_nested_attributes_for :subscription_line_items, allow_destroy: true
|
||||
accepts_nested_attributes_for :bill_address, :ship_address
|
||||
|
||||
@@ -7,6 +7,8 @@ class TagRule < ApplicationRecord
|
||||
|
||||
scope :for, ->(enterprise) { where(enterprise_id: enterprise) }
|
||||
scope :prioritised, -> { order('priority ASC') }
|
||||
scope :exclude_inventory, -> { where.not(type: "TagRule::FilterProducts") }
|
||||
scope :exclude_variant, -> { where.not(type: "TagRule::FilterVariants") }
|
||||
|
||||
def self.mapping_for(enterprises)
|
||||
self.for(enterprises).each_with_object({}) do |rule, mapping|
|
||||
@@ -20,6 +22,14 @@ class TagRule < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def self.matching_variant_tag_rules_by_enterprises(enterprise_id, tag)
|
||||
rules = where(type: "TagRule::FilterVariants").for(enterprise_id)
|
||||
|
||||
return [] if rules.empty?
|
||||
|
||||
rules.select { |r| r.preferred_variant_tags =~ /#{tag}/ }
|
||||
end
|
||||
|
||||
# The following method must be overriden in a concrete tagRule
|
||||
def tags
|
||||
raise NotImplementedError, 'please use concrete TagRule'
|
||||
|
||||
22
app/models/tag_rule/filter_variants.rb
Normal file
22
app/models/tag_rule/filter_variants.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class TagRule
|
||||
class FilterVariants < TagRule
|
||||
preference :matched_variants_visibility, :string, default: "visible"
|
||||
preference :variant_tags, :string, default: ""
|
||||
|
||||
def tags_match?(variant)
|
||||
variant_tags = variant&.[]("tag_list") || []
|
||||
preferred_tags = preferred_variant_tags.split(",")
|
||||
variant_tags.intersect?(preferred_tags)
|
||||
end
|
||||
|
||||
def reject_matched?
|
||||
preferred_matched_variants_visibility != "visible"
|
||||
end
|
||||
|
||||
def tags
|
||||
preferred_variant_tags
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -8,24 +8,14 @@ module Api
|
||||
:open_street_map_default_latitude,
|
||||
:open_street_map_default_longitude
|
||||
|
||||
def open_street_map_enabled
|
||||
ContentConfig.open_street_map_enabled
|
||||
end
|
||||
delegate :open_street_map_enabled, to: :ContentConfig
|
||||
|
||||
def open_street_map_provider_name
|
||||
ContentConfig.open_street_map_provider_name
|
||||
end
|
||||
delegate :open_street_map_provider_name, to: :ContentConfig
|
||||
|
||||
def open_street_map_provider_options
|
||||
ContentConfig.open_street_map_provider_options
|
||||
end
|
||||
delegate :open_street_map_provider_options, to: :ContentConfig
|
||||
|
||||
def open_street_map_default_latitude
|
||||
ContentConfig.open_street_map_default_latitude
|
||||
end
|
||||
delegate :open_street_map_default_latitude, to: :ContentConfig
|
||||
|
||||
def open_street_map_default_longitude
|
||||
ContentConfig.open_street_map_default_longitude
|
||||
end
|
||||
delegate :open_street_map_default_longitude, to: :ContentConfig
|
||||
end
|
||||
end
|
||||
|
||||
@@ -36,7 +36,7 @@ class EmbeddedPageService
|
||||
|
||||
def embedding_without_https?
|
||||
@request.referer && URI(@request.referer).scheme != 'https' &&
|
||||
!Rails.env.test? && !Rails.env.development?
|
||||
!Rails.env.local?
|
||||
end
|
||||
|
||||
def process_embedded_request
|
||||
|
||||
@@ -118,13 +118,22 @@ module OrderCycles
|
||||
end
|
||||
|
||||
def variants
|
||||
options[:inventory_enabled] ? stocked_variants_and_overrides : stocked_variants
|
||||
return tag_rule_filtered_variants if options[:variant_tag_enabled]
|
||||
|
||||
return stocked_variants_and_overrides if options[:inventory_enabled]
|
||||
|
||||
stocked_variants
|
||||
end
|
||||
|
||||
def stocked_variants
|
||||
Spree::Variant.joins(:stock_items).where(query_stock)
|
||||
end
|
||||
|
||||
def tag_rule_filtered_variants
|
||||
VariantTagRulesFilterer.new(distributor:, customer:,
|
||||
variants_relation: stocked_variants).call
|
||||
end
|
||||
|
||||
def stocked_variants_and_overrides
|
||||
stocked_variants = Spree::Variant.
|
||||
joins("LEFT OUTER JOIN variant_overrides ON variant_overrides.variant_id = spree_variants.id
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
# ( despite the use of `TagRule::FilterProducts.prioritised` ). It will apply the "show rule"
|
||||
# if any
|
||||
# * When there is no default rule, the order of customer related rules doesn't matter, it will
|
||||
# apply the "hide rule" if any
|
||||
# apply the "show rule" over any hide rule
|
||||
#
|
||||
class ProductTagRulesFilterer
|
||||
def initialize(distributor, customer, variants_relation)
|
||||
|
||||
109
app/services/variant_tag_rules_filterer.rb
Normal file
109
app/services/variant_tag_rules_filterer.rb
Normal file
@@ -0,0 +1,109 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Takes a Spree::Variant AR object and filters results based on applicable tag rules.
|
||||
# Tag rules exists in the context of enterprise, customer, and variants.
|
||||
# Returns a Spree::Variant AR object.
|
||||
|
||||
# The filtering is somewhat not intuitive when they are conflicting rules in play:
|
||||
# * When a variant is hidden by a default rule, It will apply the "show rule" if any
|
||||
# * When there is no default rule, it will apply the "show rule" over any "hide rule"
|
||||
#
|
||||
class VariantTagRulesFilterer
|
||||
def initialize(distributor:, customer:, variants_relation: )
|
||||
@distributor = distributor
|
||||
@customer = customer
|
||||
@variants_relation = variants_relation
|
||||
end
|
||||
|
||||
def call
|
||||
return variants_relation unless distributor_rules.any?
|
||||
|
||||
filter(variants_relation)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_accessor :distributor, :customer, :variants_relation
|
||||
|
||||
def distributor_rules
|
||||
@distributor_rules ||= TagRule::FilterVariants.for(distributor).all
|
||||
end
|
||||
|
||||
def filter(variants_relation)
|
||||
return variants_relation unless variants_to_hide.any?
|
||||
|
||||
variants_relation.where(query_with_tag_rules)
|
||||
end
|
||||
|
||||
def query_with_tag_rules
|
||||
"#{variant_not_hidden_by_rule} OR #{variant_shown_by_rule}"
|
||||
end
|
||||
|
||||
def variant_not_hidden_by_rule
|
||||
return "FALSE" unless variants_to_hide.any?
|
||||
|
||||
"spree_variants.id NOT IN (#{variants_to_hide.join(',')})"
|
||||
end
|
||||
|
||||
def variant_shown_by_rule
|
||||
return "FALSE" unless variants_to_show.any?
|
||||
|
||||
"spree_variants.id IN (#{variants_to_show.join(',')})"
|
||||
end
|
||||
|
||||
def variants_to_hide
|
||||
@variants_to_hide ||= Spree::Variant.where(supplier: distributor)
|
||||
.tagged_with(default_rule_tags + hide_rule_tags, any: true)
|
||||
.pluck(:id)
|
||||
end
|
||||
|
||||
def variants_to_show
|
||||
@variants_to_show ||= Spree::Variant.where(supplier: distributor)
|
||||
.tagged_with(show_rule_tags, any: true)
|
||||
.pluck(:id)
|
||||
end
|
||||
|
||||
def default_rule_tags
|
||||
default_rules.map(&:preferred_variant_tags)
|
||||
end
|
||||
|
||||
def hide_rule_tags
|
||||
hide_rules.map(&:preferred_variant_tags)
|
||||
end
|
||||
|
||||
def show_rule_tags
|
||||
show_rules.map(&:preferred_variant_tags)
|
||||
end
|
||||
|
||||
def default_rules
|
||||
# These rules hide a variant with tag X and apply to all customers
|
||||
distributor_rules.select(&:is_default?)
|
||||
end
|
||||
|
||||
def non_default_rules
|
||||
# These rules show or hide a variant with tag X for customer with tag Y
|
||||
distributor_rules.reject(&:is_default?)
|
||||
end
|
||||
|
||||
def customer_applicable_rules
|
||||
# Rules which apply specifically to the current customer
|
||||
@customer_applicable_rules ||= non_default_rules.select{ |rule| customer_tagged?(rule) }
|
||||
end
|
||||
|
||||
def hide_rules
|
||||
@hide_rules ||= customer_applicable_rules
|
||||
.select{ |rule| rule.preferred_matched_variants_visibility == 'hidden' }
|
||||
end
|
||||
|
||||
def show_rules
|
||||
customer_applicable_rules - hide_rules
|
||||
end
|
||||
|
||||
def customer_tagged?(rule)
|
||||
customer_tag_list.include? rule.preferred_customer_tags
|
||||
end
|
||||
|
||||
def customer_tag_list
|
||||
customer&.tag_list || []
|
||||
end
|
||||
end
|
||||
@@ -5,15 +5,14 @@
|
||||
- # We use a high enough index increment so that the default tag rule should not overlap with the tag rules
|
||||
- # Rails will deal with non continous numbered tag_rules_attributes just fine, it saves us from having to manage the index state in javascript
|
||||
- current_rule_index = 1000
|
||||
- rules = @enterprise.tag_rules.prioritised.reject(&:is_default)
|
||||
- if rules.empty?
|
||||
- if @rules.empty?
|
||||
.no_tags
|
||||
= t('.no_tags_yet')
|
||||
|
||||
= render 'admin/enterprises/form/tag_rules/default_rules', f:, current_rule_index:
|
||||
|
||||
#customer-tag-rule
|
||||
- tag_groups(rules).each_with_index do |group, group_index|
|
||||
- tag_groups(@rules).each_with_index do |group, group_index|
|
||||
- current_group_index = group_index + 1
|
||||
= render TagRuleGroupFormComponent.new(group:, index: group_index, customer_rule_index: current_rule_index, tag_rule_types: @tag_rule_types)
|
||||
- # Same as above, We use a high enough increcment so that the previous tag rule group does not overlap with the next tag rule group
|
||||
|
||||
@@ -9,13 +9,12 @@
|
||||
= t('.by_default')
|
||||
%i.text-big.icon-question-sign{ "data-controller": "help-modal-link", "data-action": "click->help-modal-link#open", "data-help-modal-link-target-value": "tag_rule_help_modal" }
|
||||
#default-tag-rule
|
||||
- default_rules = @enterprise.tag_rules.select(&:is_default)
|
||||
- current_rule_index = 0
|
||||
- if default_rules.empty?
|
||||
- if @default_rules.empty?
|
||||
.no_rules
|
||||
= t('.no_rules_yet')
|
||||
- else
|
||||
- default_rules.each_with_index do |default_rule, index|
|
||||
- @default_rules.each_with_index do |default_rule, index|
|
||||
- current_rule_index = index + 1
|
||||
= render TagRuleFormComponent.new(rule: default_rule, index: index)
|
||||
%hr
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
= error_message_on variant, :tax_category
|
||||
- if feature?(:variant_tag, spree_current_user)
|
||||
%td.col-tags.field.naked_inputs
|
||||
= render TagListInputComponent.new(name: f.field_name(:tag_list), tags: variant.tag_list, placeholder: t('.add_a_tag'), aria_label: t('admin.products_page.columns.tags'))
|
||||
= render TagListInputComponent.new(name: f.field_name(:tag_list), tags: variant.tag_list, autocomplete_url: variant_tag_rules_admin_tag_rules_path(enterprise_id: variant.supplier_id), placeholder: t('.add_a_tag'), aria_label: t('admin.products_page.columns.tags'))
|
||||
%td.col-inherits_properties.align-left
|
||||
-# empty
|
||||
%td.align-right
|
||||
|
||||
3
app/views/admin/tag_rules/variant_tag_rules.html.haml
Normal file
3
app/views/admin/tag_rules/variant_tag_rules.html.haml
Normal file
@@ -0,0 +1,3 @@
|
||||
- @formatted_tag_rules.each do |tag_rule|
|
||||
%li.suggestion-item{ role: "option", "data-autocomplete-value": tag_rule[:tag], "data-autocomplete-label": tag_rule[:tag] }
|
||||
= t("admin.products_v3.tag_rules.rules_per_tag", tag: tag_rule[:tag], count: tag_rule[:rules])
|
||||
@@ -65,7 +65,7 @@
|
||||
.row
|
||||
.small-12.columns
|
||||
.active_table
|
||||
%producer.active_table_node.row.animate-repeat{id: "{{producer.path}}",
|
||||
%producer.active_table_node.row.animate-repeat{
|
||||
"ng-repeat" => "producer in filteredEnterprises = (Enterprises.producers | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties:'supplied_properties')",
|
||||
"ng-controller" => "ProducerNodeCtrl",
|
||||
"ng-class" => "{'closed' : !open(), 'open' : open(), 'inactive' : !producer.active}",
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
.row
|
||||
.small-12.columns
|
||||
.active_table
|
||||
%producer.active_table_node.row.animate-repeat{id: "{{producer.path}}",
|
||||
%producer.active_table_node.row.animate-repeat{
|
||||
"ng-repeat" => "producer in filteredEnterprises = (Enterprises.producers | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties:'supplied_properties')",
|
||||
"ng-controller" => "ProducerNodeCtrl",
|
||||
"ng-class" => "{'closed' : !open(), 'open' : open(), 'inactive' : !producer.active}",
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
.row
|
||||
.columns.small-12.medium-5
|
||||
- if current_order.nil? || current_order.distributor.nil? || current_order.distributor == @order.distributor
|
||||
- if current_order&.line_items.present?
|
||||
= link_to main_app.cart_path, :class => "button expand" do
|
||||
= t(:order_back_to_cart)
|
||||
- else
|
||||
.columns.small-12.medium-6
|
||||
= link_to "#{main_app.enterprise_shop_path(@order.distributor)}#/shop_panel", class: "button expand" do
|
||||
= t(:order_back_to_store)
|
||||
.columns.small-12.medium-6
|
||||
- if @order.distributor.website.present?
|
||||
= link_to_service "https://", @order.distributor.website, class: "button expand" do
|
||||
= t(:order_back_to_website)
|
||||
- if current_order.nil? || current_order.distributor.nil? || current_order.distributor == @order.distributor
|
||||
- if current_order&.line_items.present?
|
||||
= link_to main_app.cart_path, :class => "button expand" do
|
||||
= t(:order_back_to_cart)
|
||||
- else
|
||||
|
||||
.columns.small-12.medium-3
|
||||
= link_to "#{main_app.enterprise_shop_path(@order.distributor)}#/shop_panel", class: "button expand" do
|
||||
= t(:order_back_to_store)
|
||||
.columns.small-12.medium-3
|
||||
- if @order.distributor.website.present?
|
||||
= link_to_service "https://", @order.distributor.website, class: "button expand" do
|
||||
= t(:order_back_to_website)
|
||||
- else
|
||||
|
||||
- if order.changes_allowed?
|
||||
.columns.show-for-medium-up.medium-1
|
||||
.columns.small-12.medium-3
|
||||
= link_to main_app.cancel_order_path(@order), method: :put, class: "button secondary expand", "data-confirm": t('orders_confirm_cancel') do
|
||||
%i.ofn-i_009-close
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
= inject_json_array("shops", @shops.all, Api::ShopForOrdersSerializer)
|
||||
= inject_saved_credit_cards
|
||||
|
||||
- if Stripe.publishable_key
|
||||
- if Spree::Config.stripe_connect_enabled && Stripe.publishable_key
|
||||
:javascript
|
||||
angular.module('Darkswarm').value("stripeObject", Stripe("#{Stripe.publishable_key}"))
|
||||
angular.module('Darkswarm').value("stripePublishableKey", "#{Stripe.publishable_key}")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import consumer from './consumer'
|
||||
import CableReady from 'cable_ready'
|
||||
import consumer from "./consumer";
|
||||
import CableReady from "cable_ready";
|
||||
|
||||
consumer.subscriptions.create("SessionChannel", {
|
||||
received(data) {
|
||||
if (data.cableReady) CableReady.perform(data.operations)
|
||||
}
|
||||
if (data.cableReady) CableReady.perform(data.operations);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import ApplicationController from "./application_controller";
|
||||
|
||||
export default class extends ApplicationController {
|
||||
static targets = ["extraParams"]
|
||||
static values = { reflex: String }
|
||||
static targets = ["extraParams"];
|
||||
static values = { reflex: String };
|
||||
|
||||
connect() {
|
||||
super.connect();
|
||||
@@ -12,7 +12,7 @@ export default class extends ApplicationController {
|
||||
let params = { bulk_ids: this.getSelectedIds() };
|
||||
|
||||
if (this.hasExtraParamsTarget) {
|
||||
Object.assign(params, this.extraFormData())
|
||||
Object.assign(params, this.extraFormData());
|
||||
}
|
||||
|
||||
this.stimulate(this.reflexValue, params);
|
||||
@@ -21,15 +21,15 @@ export default class extends ApplicationController {
|
||||
// private
|
||||
|
||||
getSelectedIds() {
|
||||
const checkboxes = document.querySelectorAll(
|
||||
"table input[name='bulk_ids[]']:checked"
|
||||
);
|
||||
const checkboxes = document.querySelectorAll("table input[name='bulk_ids[]']:checked");
|
||||
return Array.from(checkboxes).map((checkbox) => checkbox.value);
|
||||
}
|
||||
|
||||
extraFormData() {
|
||||
if (this.extraParamsTarget.constructor.name !== "HTMLFormElement") { return {} }
|
||||
if (this.extraParamsTarget.constructor.name !== "HTMLFormElement") {
|
||||
return {};
|
||||
}
|
||||
|
||||
return Object.fromEntries(new FormData(this.extraParamsTarget).entries())
|
||||
return Object.fromEntries(new FormData(this.extraParamsTarget).entries());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export default class extends Controller {
|
||||
|
||||
countValueChanged() {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("checked:updated", { detail: { count: this.countValue } })
|
||||
new CustomEvent("checked:updated", { detail: { count: this.countValue } }),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -50,11 +50,10 @@ export default class extends Controller {
|
||||
}
|
||||
|
||||
#closeDetails(elmnt) {
|
||||
if (elmnt.getElementsByTagName('details').length == 0)
|
||||
return;
|
||||
if (elmnt.getElementsByTagName("details").length == 0) return;
|
||||
|
||||
Array.from(elmnt.getElementsByTagName('details')).forEach((element) => element.open = false);
|
||||
}
|
||||
Array.from(elmnt.getElementsByTagName("details")).forEach((element) => (element.open = false));
|
||||
}
|
||||
|
||||
#toggleDisabled() {
|
||||
if (!this.hasDisableTarget) {
|
||||
|
||||
@@ -5,10 +5,10 @@ import { Controller } from "stimulus";
|
||||
export default class ColumnPreferencesController extends Controller {
|
||||
connect() {
|
||||
this.table = document.querySelector('table[data-column-preferences-target="table"]');
|
||||
this.cols = Array.from(this.table.querySelectorAll('col'));
|
||||
this.colSpanCells = Array.from(this.table.querySelectorAll('th[colspan],td[colspan]'));
|
||||
this.cols = Array.from(this.table.querySelectorAll("col"));
|
||||
this.colSpanCells = Array.from(this.table.querySelectorAll("th[colspan],td[colspan]"));
|
||||
// Initialise data-default-col-span
|
||||
this.colSpanCells.forEach((cell)=> {
|
||||
this.colSpanCells.forEach((cell) => {
|
||||
cell.dataset.defaultColSpan ||= cell.colSpan;
|
||||
});
|
||||
|
||||
@@ -33,24 +33,24 @@ export default class ColumnPreferencesController extends Controller {
|
||||
this.table.classList.toggle(`hide-${name}`, !element.checked);
|
||||
|
||||
// Reset cell colspans
|
||||
for(const cell of this.colSpanCells) {
|
||||
for (const cell of this.colSpanCells) {
|
||||
this.#updateColSpanCell(cell);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#showHideElement(element, show) {
|
||||
element.style.display = show ? "" : "none";
|
||||
}
|
||||
|
||||
#observeProductsTableRows(){
|
||||
#observeProductsTableRows() {
|
||||
this.productsTableObserver = new MutationObserver((mutations, _observer) => {
|
||||
const mutationRecord = mutations[0];
|
||||
|
||||
if(mutationRecord){
|
||||
if (mutationRecord) {
|
||||
const productRowElement = mutationRecord.addedNodes[0];
|
||||
|
||||
if(productRowElement){
|
||||
const newColSpanCell = productRowElement.querySelector('td[colspan]');
|
||||
if (productRowElement) {
|
||||
const newColSpanCell = productRowElement.querySelector("td[colspan]");
|
||||
newColSpanCell.dataset.defaultColSpan ||= newColSpanCell.colSpan;
|
||||
this.#updateColSpanCell(newColSpanCell);
|
||||
this.colSpanCells.push(newColSpanCell);
|
||||
@@ -61,11 +61,11 @@ export default class ColumnPreferencesController extends Controller {
|
||||
this.productsTableObserver.observe(this.table, { childList: true });
|
||||
}
|
||||
|
||||
#hiddenColCount(){
|
||||
return this.checkboxes.filter((checkbox)=> !checkbox.checked).length;
|
||||
#hiddenColCount() {
|
||||
return this.checkboxes.filter((checkbox) => !checkbox.checked).length;
|
||||
}
|
||||
|
||||
#updateColSpanCell(cell){
|
||||
#updateColSpanCell(cell) {
|
||||
cell.colSpan = parseInt(cell.dataset.defaultColSpan, 10) - this.#hiddenColCount();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@ export default class extends Controller {
|
||||
static targets = ["reportType", "checkbox", "label"];
|
||||
|
||||
handleSelectChange() {
|
||||
this.reportTypeTarget.value == "csv" ?
|
||||
this.disableField():
|
||||
this.enableField();
|
||||
this.reportTypeTarget.value == "csv" ? this.disableField() : this.enableField();
|
||||
}
|
||||
|
||||
disableField() {
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Controller } from "stimulus";
|
||||
|
||||
// Close a <details> element when click outside
|
||||
export default class extends Controller {
|
||||
|
||||
connect() {
|
||||
document.body.addEventListener("click", this.#close.bind(this));
|
||||
this.element.addEventListener("click", this.#stopPropagation.bind(this));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Controller } from "stimulus";
|
||||
|
||||
document.addEventListener("turbolinks:before-cache", () =>
|
||||
document.getElementById("flash").remove()
|
||||
document.getElementById("flash").remove(),
|
||||
);
|
||||
|
||||
export default class extends Controller {
|
||||
|
||||
@@ -9,7 +9,7 @@ export default class extends Controller {
|
||||
|
||||
connect() {
|
||||
if (this.hasSummaryTarget) {
|
||||
window.addEventListener('beforeunload', this.handlePageUnload);
|
||||
window.addEventListener("beforeunload", this.handlePageUnload);
|
||||
}
|
||||
|
||||
if (!this.hasGuestTarget) {
|
||||
@@ -50,7 +50,7 @@ export default class extends Controller {
|
||||
|
||||
removeUnloadEvent() {
|
||||
if (this.hasSummaryTarget) {
|
||||
window.removeEventListener('beforeunload', this.handlePageUnload);
|
||||
window.removeEventListener("beforeunload", this.handlePageUnload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import consumer from "../channels/consumer";
|
||||
import controller from "../controllers/application_controller";
|
||||
import CableReady from "cable_ready";
|
||||
import RailsNestedForm from "@stimulus-components/rails-nested-form/dist/stimulus-rails-nested-form.umd.js"; // the default module entry point is broken
|
||||
import { Autocomplete } from "stimulus-autocomplete";
|
||||
|
||||
const application = Application.start();
|
||||
const context = require.context("controllers", true, /_controller\.js$/);
|
||||
@@ -37,6 +38,7 @@ contextComponents.keys().forEach((path) => {
|
||||
});
|
||||
|
||||
application.register("nested-form", RailsNestedForm);
|
||||
application.register("autocomplete", Autocomplete);
|
||||
|
||||
application.consumer = consumer;
|
||||
StimulusReflex.initialize(application, { controller, isolate: true });
|
||||
|
||||
@@ -9,10 +9,7 @@ export default class extends Controller {
|
||||
}
|
||||
|
||||
countCharacters() {
|
||||
this.displayCount(
|
||||
this.inputTarget.value.length,
|
||||
this.inputTarget.maxLength
|
||||
);
|
||||
this.displayCount(this.inputTarget.value.length, this.inputTarget.maxLength);
|
||||
}
|
||||
|
||||
displayCount(count, max) {
|
||||
|
||||
@@ -40,20 +40,11 @@ export default class extends Controller {
|
||||
document.querySelector("body").classList.add("modal-open");
|
||||
});
|
||||
|
||||
window._paq?.push([
|
||||
"trackEvent",
|
||||
"Signin/Signup",
|
||||
"Login Modal View",
|
||||
window.location.href,
|
||||
]);
|
||||
window._paq?.push(["trackEvent", "Signin/Signup", "Login Modal View", window.location.href]);
|
||||
};
|
||||
|
||||
close() {
|
||||
history.pushState(
|
||||
{},
|
||||
"",
|
||||
window.location.pathname + window.location.search
|
||||
);
|
||||
history.pushState({}, "", window.location.pathname + window.location.search);
|
||||
|
||||
this.modalTarget.classList.remove("in");
|
||||
this.backgroundTarget.classList.remove("in");
|
||||
|
||||
@@ -4,9 +4,7 @@ export default class extends Controller {
|
||||
static targets = ["reportType", "checkbox", "label"];
|
||||
|
||||
handleSelectChange() {
|
||||
this.reportTypeTarget.value == "csv" ?
|
||||
this.enableField():
|
||||
this.disableField();
|
||||
this.reportTypeTarget.value == "csv" ? this.enableField() : this.disableField();
|
||||
}
|
||||
|
||||
disableField() {
|
||||
@@ -27,4 +25,4 @@ export default class extends Controller {
|
||||
this.labelTarget.classList.remove("disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,8 @@ export const useRenderCustomer = (controller) => {
|
||||
${
|
||||
item.bill_address.firstname
|
||||
? `<strong>${I18n.t("bill_address")}</strong>
|
||||
${item.bill_address.firstname} ${
|
||||
item.bill_address.lastname
|
||||
}<br>
|
||||
${item.bill_address.address1}, ${
|
||||
item.bill_address.address2
|
||||
}<br>
|
||||
${item.bill_address.firstname} ${item.bill_address.lastname}<br>
|
||||
${item.bill_address.address1}, ${item.bill_address.address2}<br>
|
||||
${item.bill_address.city}
|
||||
<br>
|
||||
${
|
||||
@@ -27,8 +23,7 @@ export const useRenderCustomer = (controller) => {
|
||||
}
|
||||
|
||||
${
|
||||
item.bill_address.country &&
|
||||
item.bill_address.country.name
|
||||
item.bill_address.country && item.bill_address.country.name
|
||||
? item.bill_address.country.name
|
||||
: item.bill_address.country_name
|
||||
}
|
||||
@@ -41,9 +36,7 @@ export const useRenderCustomer = (controller) => {
|
||||
|
||||
renderWithNoBillAddress(item, escape) {
|
||||
return `<div class='customer-autocomplete-item'>
|
||||
<div class='customer-details'><h5>${escape(
|
||||
item.email
|
||||
)}</h5></div>
|
||||
<div class='customer-details'><h5>${escape(item.email)}</h5></div>
|
||||
</div>`;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3,13 +3,15 @@ import { useOpenAndCloseAsAModal } from "./mixins/useOpenAndCloseAsAModal";
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["background", "modal"];
|
||||
static values = { instant: { type: Boolean, default: false } }
|
||||
static values = { instant: { type: Boolean, default: false } };
|
||||
|
||||
connect() {
|
||||
useOpenAndCloseAsAModal(this);
|
||||
window.addEventListener("modal:close", this.close.bind(this));
|
||||
|
||||
if (this.instantValue) { this.open() }
|
||||
if (this.instantValue) {
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
@@ -17,6 +19,6 @@ export default class extends Controller {
|
||||
}
|
||||
|
||||
remove(event) {
|
||||
this.close(event, true)
|
||||
this.close(event, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ export default class extends Controller {
|
||||
let modal = document.getElementById(this.targetValue);
|
||||
let modalController = this.application.getControllerForElementAndIdentifier(
|
||||
modal,
|
||||
this.getIdentifier()
|
||||
this.getIdentifier(),
|
||||
);
|
||||
modalController.open();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Controller } from "stimulus";
|
||||
import L from "leaflet";
|
||||
import LeafetProviders from "leaflet-providers";
|
||||
import { OpenStreetMapProvider } from 'leaflet-geosearch';
|
||||
import { OpenStreetMapProvider } from "leaflet-geosearch";
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["confirmAddressField", "dragPinNote"];
|
||||
@@ -9,7 +9,7 @@ export default class extends Controller {
|
||||
defaultLatitude: Number,
|
||||
defaultLongitude: Number,
|
||||
providerName: String,
|
||||
providerOptions: Object
|
||||
providerOptions: Object,
|
||||
};
|
||||
|
||||
connect() {
|
||||
@@ -23,7 +23,7 @@ export default class extends Controller {
|
||||
|
||||
async locateAddress() {
|
||||
const results = await this.provider.search({ query: this.#addressQuery() });
|
||||
if(results.length > 0) {
|
||||
if (results.length > 0) {
|
||||
const result = results[0];
|
||||
this.#setLatitudeLongitude(result.y, result.x);
|
||||
this.#addMarker(result.y, result.x);
|
||||
@@ -46,13 +46,15 @@ export default class extends Controller {
|
||||
// If someone clicks the locate address on map button without filling in their address the
|
||||
// geocoded address will not be very accurate so don't zoom in too close so it's easier for
|
||||
// people to see where the marker is.
|
||||
if(!addressLine1 && !city && !zipcode) {
|
||||
if (!addressLine1 && !city && !zipcode) {
|
||||
this.zoomLevel = 6;
|
||||
} else {
|
||||
this.zoomLevel = 14;
|
||||
}
|
||||
|
||||
return [addressLine1, addressLine2, city, state, zipcode, country].filter((value) => !!value).join(", ")
|
||||
return [addressLine1, addressLine2, city, state, zipcode, country]
|
||||
.filter((value) => !!value)
|
||||
.join(", ");
|
||||
}
|
||||
|
||||
#addMarker(latitude, longitude) {
|
||||
@@ -72,13 +74,13 @@ export default class extends Controller {
|
||||
|
||||
#displayMap() {
|
||||
// Don't initialise map in test environment because that could possibly abuse OSM tile servers
|
||||
if(process.env.RAILS_ENV == "test") {
|
||||
if (process.env.RAILS_ENV == "test") {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.map = L.map('open-street-map')
|
||||
L.tileLayer.provider(this.providerNameValue, this.providerOptionsValue).addTo(this.map)
|
||||
this.map.setView([this.defaultLatitudeValue, this.defaultLongitudeValue], this.zoomLevel)
|
||||
this.map = L.map("open-street-map");
|
||||
L.tileLayer.provider(this.providerNameValue, this.providerOptionsValue).addTo(this.map);
|
||||
this.map.setView([this.defaultLatitudeValue, this.defaultLongitudeValue], this.zoomLevel);
|
||||
this.provider = new OpenStreetMapProvider();
|
||||
}
|
||||
|
||||
@@ -88,12 +90,12 @@ export default class extends Controller {
|
||||
#displayMapWhenAtRegistrationDetailsStep() {
|
||||
const observer = new IntersectionObserver(
|
||||
([intersectionObserverEntry]) => {
|
||||
if(intersectionObserverEntry.target.offsetParent !== null) {
|
||||
if (intersectionObserverEntry.target.offsetParent !== null) {
|
||||
this.#displayMap();
|
||||
observer.disconnect()
|
||||
observer.disconnect();
|
||||
}
|
||||
},
|
||||
{ threshold: [0] }
|
||||
{ threshold: [0] },
|
||||
);
|
||||
observer.observe(document.getElementById("registration-details"));
|
||||
}
|
||||
|
||||
@@ -1,55 +1,58 @@
|
||||
import { Controller } from "stimulus";
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ['statusMessage', 'cancel']
|
||||
static targets = ["statusMessage", "cancel"];
|
||||
connect() {
|
||||
this.observer = new MutationObserver(this.updateCallback);
|
||||
this.observer.observe(
|
||||
this.statusMessageTarget,
|
||||
{ attributes: true, attributeOldValue: true, attributeFilter: ['data-type'] }
|
||||
);
|
||||
this.observer.observe(this.statusMessageTarget, {
|
||||
attributes: true,
|
||||
attributeOldValue: true,
|
||||
attributeFilter: ["data-type"],
|
||||
});
|
||||
|
||||
if (this.hasCancelTarget) {
|
||||
this.cancelTarget.addEventListener('click', this.removeUnloadEvent)
|
||||
this.cancelTarget.addEventListener("click", this.removeUnloadEvent);
|
||||
}
|
||||
}
|
||||
|
||||
// Callback to trigger warning modal
|
||||
updateCallback(mutationsList) {
|
||||
const newDataType = document.getElementById('status-message').getAttribute('data-type');
|
||||
const actionName = document.getElementById('status-message').getAttribute('data-action-name');
|
||||
if(!actionName) return;
|
||||
const newDataType = document.getElementById("status-message").getAttribute("data-type");
|
||||
const actionName = document.getElementById("status-message").getAttribute("data-action-name");
|
||||
if (!actionName) return;
|
||||
|
||||
for(let mutation of mutationsList) {
|
||||
if (mutation.type === 'attributes' && mutation.attributeName === 'data-type') {
|
||||
for (let mutation of mutationsList) {
|
||||
if (mutation.type === "attributes" && mutation.attributeName === "data-type") {
|
||||
// Only trigger warning modal when notice display (notice) is preceeded by progress display (progress)
|
||||
if(mutation.oldValue === 'progress' && newDataType === 'notice') {
|
||||
if (mutation.oldValue === "progress" && newDataType === "notice") {
|
||||
// Hide all confirmation buttons in warning modal
|
||||
document.querySelectorAll(
|
||||
'#linked-order-warning-modal .modal-actions button.secondary'
|
||||
).forEach((node) => {
|
||||
node.style.display = 'none';
|
||||
});
|
||||
document
|
||||
.querySelectorAll("#linked-order-warning-modal .modal-actions button.secondary")
|
||||
.forEach((node) => {
|
||||
node.style.display = "none";
|
||||
});
|
||||
// Show the appropriate confirmation button, open warning modal, and return
|
||||
document.querySelectorAll(
|
||||
`#linked-order-warning-modal button[data-trigger-action=${actionName}]`
|
||||
).forEach((node) => {
|
||||
node.style.display = 'block';
|
||||
})
|
||||
document.querySelector('.warning-modal button.modal-target-trigger').click();
|
||||
document
|
||||
.querySelectorAll(
|
||||
`#linked-order-warning-modal button[data-trigger-action=${actionName}]`,
|
||||
)
|
||||
.forEach((node) => {
|
||||
node.style.display = "block";
|
||||
});
|
||||
document.querySelector(".warning-modal button.modal-target-trigger").click();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removeUnloadEvent() {
|
||||
window.removeEventListener('beforeunload', window.onBeforeUnloadHandler)
|
||||
window.removeEventListener("beforeunload", window.onBeforeUnloadHandler);
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this.observer.disconnect();
|
||||
if (this.hasCancelTarget) {
|
||||
this.cancelTarget.removeEventListener('click', this.removeUnloadEvent)
|
||||
this.cancelTarget.removeEventListener("click", this.removeUnloadEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { Controller } from "stimulus";
|
||||
|
||||
export default class extends Controller {
|
||||
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"];
|
||||
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",
|
||||
];
|
||||
|
||||
connect() {
|
||||
// Wait a moment after page load before showing the alert. Otherwise we often miss the
|
||||
|
||||
@@ -21,11 +21,8 @@ export default class extends Controller {
|
||||
}
|
||||
|
||||
setPaymentMethod(paymentMethodContainerId) {
|
||||
Array.from(
|
||||
document.getElementsByClassName("paymentmethod-container")
|
||||
).forEach((container) => {
|
||||
const enabled =
|
||||
container.dataset.paymentmethodId === paymentMethodContainerId;
|
||||
Array.from(document.getElementsByClassName("paymentmethod-container")).forEach((container) => {
|
||||
const enabled = container.dataset.paymentmethodId === paymentMethodContainerId;
|
||||
|
||||
if (enabled) {
|
||||
container.style.display = "block";
|
||||
|
||||
@@ -12,9 +12,7 @@ export default class extends Controller {
|
||||
this.hideAvailability();
|
||||
this.showSpinner();
|
||||
|
||||
const response = await fetch(
|
||||
this.urlValue + `?permalink="${this.permalinkFieldTarget.value}"`
|
||||
);
|
||||
const response = await fetch(this.urlValue + `?permalink="${this.permalinkFieldTarget.value}"`);
|
||||
const result = await response.text();
|
||||
|
||||
if (this.initialPermalinkValue == result) {
|
||||
|
||||
@@ -4,8 +4,8 @@ import { Controller } from "stimulus";
|
||||
export default class PopoutController extends Controller {
|
||||
static targets = ["button", "dialog"];
|
||||
static values = {
|
||||
updateDisplay: { Boolean, default: true }
|
||||
}
|
||||
updateDisplay: { Boolean, default: true },
|
||||
};
|
||||
|
||||
connect() {
|
||||
this.displayElements = Array.from(this.element.querySelectorAll('input:not([type="hidden"]'));
|
||||
|
||||
@@ -23,7 +23,7 @@ export default class extends Controller {
|
||||
{
|
||||
method: "GET",
|
||||
headers: { "Content-type": "application/json; charset=UTF-8" },
|
||||
}
|
||||
},
|
||||
)
|
||||
.then((data) => data.json())
|
||||
.then((operation) => {
|
||||
|
||||
@@ -18,11 +18,11 @@ export default class extends ApplicationController {
|
||||
}
|
||||
|
||||
delete_product() {
|
||||
this.#deleteByRecordType('product');
|
||||
this.#deleteByRecordType("product");
|
||||
}
|
||||
|
||||
delete_variant() {
|
||||
this.#deleteByRecordType('variant');
|
||||
this.#deleteByRecordType("variant");
|
||||
}
|
||||
|
||||
showLoading = () => {
|
||||
@@ -44,51 +44,52 @@ export default class extends ApplicationController {
|
||||
getLoadingController = () => {
|
||||
return (this.loadingController ||= this.application.getControllerForElementAndIdentifier(
|
||||
this.loadingTarget,
|
||||
"loading"
|
||||
"loading",
|
||||
));
|
||||
};
|
||||
|
||||
// +recordType+ can either be 'product' or 'variant'
|
||||
#deleteByRecordType(recordType) {
|
||||
const deletePath = document.querySelector(`#${recordType}-delete-modal #modal-confirm-button`).getAttribute('data-delete-path');
|
||||
const deletePath = document
|
||||
.querySelector(`#${recordType}-delete-modal #modal-confirm-button`)
|
||||
.getAttribute("data-delete-path");
|
||||
const elementToBeRemoved = this.#getElementToBeRemoved(deletePath, recordType);
|
||||
|
||||
const handleSlideOutAnimationEnd = async () => {
|
||||
// in case of test env, we won't be having csrf token
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute("content");
|
||||
|
||||
try {
|
||||
const response = await fetch(deletePath, {
|
||||
method: 'DELETE',
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
Accept: 'text/vnd.turbo-stream.html',
|
||||
'X-CSRF-Token': csrfToken,
|
||||
}
|
||||
Accept: "text/vnd.turbo-stream.html",
|
||||
"X-CSRF-Token": csrfToken,
|
||||
},
|
||||
});
|
||||
// need to render the turboStream message, that's why not throwing error here
|
||||
if(response.status === 500) elementToBeRemoved.classList.remove('slide-out');
|
||||
// need to render the turboStream message, that's why not throwing error here
|
||||
if (response.status === 500) elementToBeRemoved.classList.remove("slide-out");
|
||||
|
||||
const responseTurboStream = await response.text();
|
||||
Turbo.renderStreamMessage(responseTurboStream);
|
||||
} catch(error) {
|
||||
} catch (error) {
|
||||
console.error(error.message);
|
||||
elementToBeRemoved.classList.remove('slide-out');
|
||||
}
|
||||
finally {
|
||||
elementToBeRemoved.removeEventListener('animationend', handleSlideOutAnimationEnd);
|
||||
elementToBeRemoved.classList.remove("slide-out");
|
||||
} finally {
|
||||
elementToBeRemoved.removeEventListener("animationend", handleSlideOutAnimationEnd);
|
||||
}
|
||||
};
|
||||
|
||||
// remove the clone animation before deleting
|
||||
elementToBeRemoved.classList.remove('slide-in');
|
||||
elementToBeRemoved.classList.add('slide-out');
|
||||
elementToBeRemoved.addEventListener('animationend', handleSlideOutAnimationEnd);
|
||||
};
|
||||
elementToBeRemoved.classList.remove("slide-in");
|
||||
elementToBeRemoved.classList.add("slide-out");
|
||||
elementToBeRemoved.addEventListener("animationend", handleSlideOutAnimationEnd);
|
||||
}
|
||||
|
||||
#getElementToBeRemoved(path, recordType) {
|
||||
const recordId = path.substring(path.lastIndexOf('/') + 1);
|
||||
const recordId = path.substring(path.lastIndexOf("/") + 1);
|
||||
const elementDomId = `${recordType}_${recordId}`;
|
||||
|
||||
return document.getElementById(elementDomId);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export default class extends Controller {
|
||||
received(data) {
|
||||
if (data.cableReady) CableReady.perform(data.operations);
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,16 +3,12 @@ import ApplicationController from "./application_controller";
|
||||
export default class extends ApplicationController {
|
||||
connect() {
|
||||
super.connect();
|
||||
this.element
|
||||
.querySelector("input")
|
||||
.addEventListener("keydown", this.searchOnEnter);
|
||||
this.element.querySelector("input").addEventListener("keydown", this.searchOnEnter);
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
super.disconnect();
|
||||
this.element
|
||||
.querySelector("input")
|
||||
.removeEventListener("keydown", this.searchOnEnter);
|
||||
this.element.querySelector("input").removeEventListener("keydown", this.searchOnEnter);
|
||||
}
|
||||
|
||||
searchOnEnter = (e) => {
|
||||
@@ -22,7 +18,6 @@ export default class extends ApplicationController {
|
||||
};
|
||||
|
||||
search(e) {
|
||||
this.element.querySelector(".search-button").dataset["value"] =
|
||||
e.target.value;
|
||||
this.element.querySelector(".search-button").dataset["value"] = e.target.value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,11 +42,11 @@ export default class extends TomSelectController {
|
||||
});
|
||||
this.setValueOnTomSelectController(
|
||||
document.querySelector(attribute_wrapper + "state_id"),
|
||||
data ? data.state_id : ""
|
||||
data ? data.state_id : "",
|
||||
);
|
||||
this.setValueOnTomSelectController(
|
||||
document.querySelector(attribute_wrapper + "country_id"),
|
||||
data ? data.country_id : ""
|
||||
data ? data.country_id : "",
|
||||
);
|
||||
});
|
||||
document.querySelector("#order_email").value = customer.email;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user