Compare commits

..

192 Commits

Author SHA1 Message Date
David Cook
59547ba9e4 Merge pull request #13964 from mkllnk/flaky-spec
Stabilise actions_spec
2026-03-04 13:06:08 +11:00
Maikel
9fb8bb15e8 Merge pull request #13951 from zilton7/fix/spree-credit-card-brand-deprecation
Fix Spree::CreditCard#brand= deprecation for Rails 7.2 compatibility
2026-03-04 11:01:10 +11:00
Maikel
8aa89c0bf7 Merge pull request #13669 from pacodelaluna/repair-proxy-order-to-support-order-cycle-without-closing-time
Repair ProxyOrder to support order cycle without closing time
2026-03-04 10:59:21 +11:00
Maikel
7a4beb8b22 Merge pull request #13982 from openfoodfoundation/dependabot/npm_and_yarn/tom-select-2.5.2
Bump tom-select from 2.5.1 to 2.5.2
2026-03-04 09:49:28 +11:00
Maikel
9a48ee16cc Merge pull request #13983 from openfoodfoundation/dependabot/npm_and_yarn/hotkeys-js-4.0.1
Bump hotkeys-js from 4.0.0 to 4.0.1
2026-03-04 09:48:23 +11:00
Maikel
50c0e8af7d Merge pull request #13984 from openfoodfoundation/dependabot/bundler/pdf-reader-2.15.1
Bump pdf-reader from 2.15.0 to 2.15.1
2026-03-04 09:47:35 +11:00
David Cook
1cf2928f9f Merge pull request #13979 from openfoodfoundation/RachL-patch-1
Update release issue template
2026-03-04 09:10:24 +11:00
François Turbelin
6cacde837d Remove duplicated test 2026-03-03 14:27:20 +01:00
dependabot[bot]
1d2d661675 Bump pdf-reader from 2.15.0 to 2.15.1
Bumps [pdf-reader](https://github.com/yob/pdf-reader) from 2.15.0 to 2.15.1.
- [Changelog](https://github.com/yob/pdf-reader/blob/main/CHANGELOG)
- [Commits](https://github.com/yob/pdf-reader/compare/v2.15.0...v2.15.1)

---
updated-dependencies:
- dependency-name: pdf-reader
  dependency-version: 2.15.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-03 09:33:47 +00:00
dependabot[bot]
5029c03205 Bump hotkeys-js from 4.0.0 to 4.0.1
Bumps [hotkeys-js](https://github.com/jaywcjlove/hotkeys-js) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/jaywcjlove/hotkeys-js/releases)
- [Commits](https://github.com/jaywcjlove/hotkeys-js/compare/v4.0.0...v4.0.1)

---
updated-dependencies:
- dependency-name: hotkeys-js
  dependency-version: 4.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-03 09:33:32 +00:00
dependabot[bot]
2b648f3f3c Bump tom-select from 2.5.1 to 2.5.2
Bumps [tom-select](https://github.com/orchidjs/tom-select) from 2.5.1 to 2.5.2.
- [Release notes](https://github.com/orchidjs/tom-select/releases)
- [Commits](https://github.com/orchidjs/tom-select/compare/v2.5.1...2.5.2)

---
updated-dependencies:
- dependency-name: tom-select
  dependency-version: 2.5.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-03 09:33:16 +00:00
David Cook
b2e847b551 Merge pull request #13957 from openfoodfoundation/dependabot/bundler/i18n-1.14.8
Bump i18n from 1.14.7 to 1.14.8
2026-03-03 17:16:58 +11:00
Maikel Linke
4873fd3275 Remove non-task item 2026-03-03 16:16:57 +11:00
Maikel Linke
e0ad4363a9 Fix formatting 2026-03-03 16:12:47 +11:00
Gaetan Craig-Riou
efdbf25f86 Merge pull request #13248 from drummer83/email_whitelabel
White labelling all customer facing emails
2026-03-03 09:40:47 +11:00
François Turbelin
7010cda9f7 Tidy up the tests 2026-03-02 22:07:45 +01:00
Konrad
498ed5a3ec Resolve conflicts 2026-03-02 22:05:29 +01:00
Rachel Arnould
c7d4c6f3c4 Merge pull request #13835 from prikeshsavla/13569-remove-v3-admin-styles
Refactor admin CSS: Promote v3 to canonical admin styles
2026-03-02 12:29:33 +01:00
Rachel Arnould
70b2a6d999 Update release template
Currently testers are using google docs to store release tests. This is maybe overkill.

I've documented the steps here and the proposal is for testers to document their test in the release issue.
2026-03-02 12:22:11 +01:00
dependabot[bot]
36e3e16ba0 Bump i18n from 1.14.7 to 1.14.8
Bumps [i18n](https://github.com/ruby-i18n/i18n) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/ruby-i18n/i18n/releases)
- [Changelog](https://github.com/ruby-i18n/i18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ruby-i18n/i18n/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: i18n
  dependency-version: 1.14.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-02 02:36:18 +00:00
Gaetan Craig-Riou
0f047e2c25 Merge pull request #13977 from openfoodfoundation/dependabot/npm_and_yarn/minimatch-3.1.5
Bump minimatch from 3.1.2 to 3.1.5
2026-03-02 12:00:02 +11:00
dependabot[bot]
ef7bd083ed Bump minimatch from 3.1.2 to 3.1.5
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.1.2 to 3.1.5.
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-version: 3.1.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-28 03:02:06 +00:00
Rachel Arnould
c13785f2e3 Merge pull request #13943 from pavelk-lab/replace-brand-story-angular-with-details
Replace Angular expand/collapse with native HTML <details>/<summary> for brand story
2026-02-27 15:37:00 +01:00
François Turbelin
28dde86960 Repair ProxyOrder to support order cycle without closing time 2026-02-27 14:36:20 +01:00
Gaetan Craig-Riou
0c0304b1c1 Merge pull request #13976 from openfoodfoundation/revert-13973-fix-rubocop-violations
Revert "Fix 9 Rubocop violations (Rails/Presence and Rails/RedirectBackOrTo)Fix rubocop violations"
2026-02-27 10:06:29 +11:00
David-OFN-CA
7922bf7b65 Revert "Fix 9 Rubocop violations (Rails/Presence and Rails/RedirectBackOrTo)Fix rubocop violations" 2026-02-26 17:04:21 -05:00
David-OFN-CA
2d46676bb4 Merge pull request #13973 from David-OFN-CA/fix-rubocop-violations
Fix 9 Rubocop violations (Rails/Presence and Rails/RedirectBackOrTo)Fix rubocop violations
2026-02-26 16:01:15 -05:00
David Thomas
2808a41f0d Safely autocorrect Rails/RedirectBackOrTo
Inspecting 1721 files
........................................W...................................................................W................W..W.......W................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

Offenses:

app/controllers/admin/order_cycles_controller.rb:212:9: W: [Corrected] Rails/RedirectBackOrTo: Use redirect_back_or_to instead of redirect_back with :fallback_location keyword argument.
        redirect_back(fallback_location: root_path)
        ^^^^^^^^^^^^^
app/controllers/locales_controller.rb:6:5: W: [Corrected] Rails/RedirectBackOrTo: Use redirect_back_or_to instead of redirect_back with :fallback_location keyword argument.
    redirect_back fallback_location: main_app.root_url
    ^^^^^^^^^^^^^
app/controllers/spree/admin/invoices_controller.rb:31:9: W: [Corrected] Rails/RedirectBackOrTo: Use redirect_back_or_to instead of redirect_back with :fallback_location keyword argument.
        redirect_back(fallback_location: spree.admin_dashboard_path)
        ^^^^^^^^^^^^^
app/controllers/spree/admin/orders_controller.rb:83:9: W: [Corrected] Rails/RedirectBackOrTo: Use redirect_back_or_to instead of redirect_back with :fallback_location keyword argument.
        redirect_back fallback_location: spree.admin_dashboard_path
        ^^^^^^^^^^^^^
app/controllers/spree/admin/orders_controller.rb:91:25: W: [Corrected] Rails/RedirectBackOrTo: Use redirect_back_or_to instead of redirect_back with :fallback_location keyword argument.
          format.html { redirect_back(fallback_location: spree.admin_dashboard_path) }
                        ^^^^^^^^^^^^^
app/controllers/spree/admin/return_authorizations_controller.rb:13:9: W: [Corrected] Rails/RedirectBackOrTo: Use redirect_back_or_to instead of redirect_back with :fallback_location keyword argument.
        redirect_back fallback_location: spree.admin_dashboard_path
        ^^^^^^^^^^^^^

1721 files inspected, 6 offenses detected, 6 offenses corrected
2026-02-26 15:35:55 -05:00
David Thomas
18869979db Safely autocorrect Rails/Presence
Inspecting 1721 files
...................................C.................................................................................................................................................................................................................................................................................................................................................C...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

Offenses:

app/controllers/admin/enterprises_controller.rb:180:7: C: [Corrected] Rails/Presence: Use @object.custom_tab.presence&.destroy instead of @object.custom_tab.destroy if @object.custom_tab.present?.
      @object.custom_tab.destroy if @object.custom_tab.present?
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/controllers/admin/enterprises_controller.rb:243:9: C: [Corrected] Rails/Presence: Use (enterprises.presence&.includes(supplied_products: [:variants, :image])) instead of if enterprises.present? ... end.
        if enterprises.present? ...
        ^^^^^^^^^^^^^^^^^^^^^^^
app/controllers/admin/enterprises_controller.rb:243:9: C: [Corrected] Style/RedundantParentheses: Don't use parentheses around a method call.
        (enterprises.presence&.includes(supplied_products: [:variants, :image]))
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/models/spree/product.rb:298:7: C: [Corrected] Rails/Presence: Use (first_variant.supplier.presence&.touch) instead of first_variant.supplier.touch if first_variant.supplier.present?.
      first_variant.supplier.touch if first_variant.supplier.present?
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/models/spree/product.rb:298:7: C: [Corrected] Style/RedundantParentheses: Don't use parentheses around a method call.
      (first_variant.supplier.presence&.touch)
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

1721 files inspected, 5 offenses detected, 5 offenses corrected
2026-02-26 15:34:45 -05:00
David Thomas
708dbb2270 Regenerate Rubocop's TODO file 2026-02-26 15:33:37 -05:00
Zil Norvilis
9488e9b459 feat: display credit card brand instead of card type in the saved cards list. 2026-02-26 15:52:45 +02:00
Zil Norvilis
503429960a Reverse credit_card_serializer changes 2026-02-26 15:10:21 +02:00
Rachel Arnould
83ec97e720 Merge pull request #13944 from pavelk-lab/fix/rails-7-serialize-deprecation
Fix Rails 7.2 serialize deprecation warnings
2026-02-26 11:29:27 +01:00
Maikel Linke
c0b6f26338 Update all locales with the latest Transifex translations 2026-02-26 12:43:07 +11:00
Maikel Linke
fd178ee80b Use unique categories to avoid flakiness 2026-02-26 11:42:46 +11:00
Maikel Linke
e4db20f86e Remove unncessary expectation
This assertion was confusing me. It was quite complex and the only thing
it was asserting was the placeholder via a CSS selector. I don't think
it's worth keeping.
2026-02-26 11:37:30 +11:00
Zil Norvilis
58520a0c4c test: Add specs for the stripe_card_options helper method, verifying card formatting and month padding. 2026-02-25 19:49:10 +02:00
Zil Norvilis
0bc4b1c885 refactor: Standardize credit card type attribute to cc_type across the application, removing the brand alias and related methods. 2026-02-25 19:35:53 +02:00
Maikel Linke
560348722c Revert "Test current flakiness of spec"
This reverts commit 7b715bf6c7.
2026-02-25 15:18:39 +11:00
Maikel Linke
6d17cf50fb Test impact of longer wait time on flakiness 2026-02-25 15:08:50 +11:00
Maikel Linke
7b715bf6c7 Test current flakiness of spec 2026-02-25 15:07:52 +11:00
Gaetan Craig-Riou
f6c426ef17 Merge pull request #13956 from openfoodfoundation/dependabot/npm_and_yarn/css-loader-7.1.4
Bump css-loader from 7.1.3 to 7.1.4
2026-02-25 10:24:55 +11:00
Ahmed Ejaz
0a42f15c25 Merge pull request #13960 from chahmedejaz/bugfix/13776-datetime-format-for-finnish
Update Finnish date and datetime formats in locale file
2026-02-25 04:19:08 +05:00
Ahmed Ejaz
95412bd203 Update Finnish date and datetime formats in locale file 2026-02-24 20:27:14 +05:00
Rachel Arnould
81aac877a5 Merge pull request #13945 from mkllnk/taler-refund
Add "void" action to Taler payment admin page
2026-02-24 11:23:07 +01:00
dependabot[bot]
2330c7cfc2 Bump css-loader from 7.1.3 to 7.1.4
Bumps [css-loader](https://github.com/webpack/css-loader) from 7.1.3 to 7.1.4.
- [Release notes](https://github.com/webpack/css-loader/releases)
- [Changelog](https://github.com/webpack/css-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webpack/css-loader/compare/v7.1.3...v7.1.4)

---
updated-dependencies:
- dependency-name: css-loader
  dependency-version: 7.1.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-24 09:31:34 +00:00
Rachel Arnould
68c7d8f9f5 Merge pull request #13934 from chahmedejaz/bugfix/13827-tag-filters-reset-upon-product-update
Tag filters are reset after updating a product
2026-02-24 10:20:11 +01:00
Maikel
cf3175c16e Merge pull request #13709 from openfoodfoundation/dependabot/bundler/cuprite-0.17
Bump cuprite from 0.15 to 0.17
2026-02-24 12:05:17 +11:00
Pavel
85c903cb7f Remove fixed serialize deprecation from allowed warnings
The "Passing the class as positional argument" warning was suppressed
while serialize calls were being updated to use the keyword argument
form. Now that the fix is applied, the suppression is no longer needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 23:30:48 +00:00
Gaetan Craig-Riou
ebd7b0b24d Merge pull request #13952 from openfoodfoundation/dependabot/npm_and_yarn/postcss-loader-8.2.1
Bump postcss-loader from 8.2.0 to 8.2.1
2026-02-24 10:11:42 +11:00
Gaetan Craig-Riou
78cf0434d6 Merge pull request #13953 from openfoodfoundation/dependabot/npm_and_yarn/webpack-sources-3.3.4
Bump webpack-sources from 3.3.3 to 3.3.4
2026-02-24 10:11:23 +11:00
dependabot[bot]
74e7e9b17b Bump webpack-sources from 3.3.3 to 3.3.4
Bumps [webpack-sources](https://github.com/webpack/webpack-sources) from 3.3.3 to 3.3.4.
- [Release notes](https://github.com/webpack/webpack-sources/releases)
- [Commits](https://github.com/webpack/webpack-sources/compare/v3.3.3...v3.3.4)

---
updated-dependencies:
- dependency-name: webpack-sources
  dependency-version: 3.3.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-23 10:24:42 +00:00
dependabot[bot]
2b32d53911 Bump postcss-loader from 8.2.0 to 8.2.1
Bumps [postcss-loader](https://github.com/webpack/postcss-loader) from 8.2.0 to 8.2.1.
- [Release notes](https://github.com/webpack/postcss-loader/releases)
- [Changelog](https://github.com/webpack/postcss-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webpack/postcss-loader/compare/v8.2.0...v8.2.1)

---
updated-dependencies:
- dependency-name: postcss-loader
  dependency-version: 8.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-23 10:24:16 +00:00
Maikel Linke
2cff5bc4df Style helper code 2026-02-23 13:08:56 +11:00
Maikel Linke
1dbcddf799 Select found option after search to fix spec
Selecting the tom select option in the dropdown often happened quicker
than the search finished. In that case we selected the option from the
list of all options and then the search would present the found option
again and leave the dropdown open.

This didn't cause any trouble in the past because any other action would
close the dropdown again. But the new cuprite version didn't trigger the
next click on the target element. It would just close the dropdown on
the next click without further action. That would then break the next
assertion looking for the next open dropdown, which didn't open with the
click.

Selecting the "active" option means that we wait for the search to
finish and present an option as active. Clicking that option closes the
dropdown without opening it again.
2026-02-23 13:08:55 +11:00
Maikel Linke
702db32595 Connect unit label to input
And replace redundant spec helper method.
2026-02-23 13:08:55 +11:00
Maikel Linke
d770049d2d Replace redundant spec helper method 2026-02-23 13:08:55 +11:00
Maikel Linke
424e25f83e Merge mostly duplicate Tom Select helpers 2026-02-23 13:08:55 +11:00
dependabot[bot]
ce12bc4dbc Bump cuprite from 0.15 to 0.17
Bumps [cuprite](https://github.com/rubycdp/cuprite) from 0.15 to 0.17.
- [Release notes](https://github.com/rubycdp/cuprite/releases)
- [Changelog](https://github.com/rubycdp/cuprite/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rubycdp/cuprite/compare/v0.15...v0.17)

---
updated-dependencies:
- dependency-name: cuprite
  dependency-version: '0.17'
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-23 13:08:53 +11:00
Maikel Linke
9d79119eb0 Link to payment action with title
The custom helper was adding a PowerTip which replaced the title
attribute with its own display. I removed the PowerTip and use a simple
title attribute. This should have several benefits:

- Capybara can find the link by the title.
- Screenreaders should be able read the title.
- Browser can show the title in the best position.
- Using the browser feature is more consistent and efficient.
2026-02-23 13:00:02 +11:00
Maikel Linke
f2eec5685e Include amount in refund email 2026-02-23 13:00:02 +11:00
Gaetan Craig-Riou
8aac400c14 Merge pull request #13948 from openfoodfoundation/dependabot/bundler/sidekiq-scheduler-6.0.1
Bump sidekiq-scheduler from 5.0.3 to 6.0.1
2026-02-23 10:03:50 +11:00
Gaetan Craig-Riou
f31976a3a4 Merge pull request #13950 from openfoodfoundation/dependabot/npm_and_yarn/ajv-6.14.0
Bump ajv from 6.12.6 to 6.14.0
2026-02-23 09:58:17 +11:00
Gaetan Craig-Riou
0bb2c867e0 Merge pull request #13947 from openfoodfoundation/dependabot/npm_and_yarn/webpack-5.105.2
Bump webpack from 5.105.1 to 5.105.2
2026-02-23 09:45:01 +11:00
Gaetan Craig-Riou
cd68ddc34f Merge pull request #13946 from mkllnk/erb
Remove unnecessary erb compilation on JS file
2026-02-23 09:43:11 +11:00
Zil Norvilis
2cfd386ad7 test: add spec for Spree::CreditCard#brand= setter to verify card type reformatting 2026-02-22 22:28:40 +02:00
Zil Norvilis
ce94b394b2 feat: Add brand= setter to Spree::CreditCard for cc_type assignment. 2026-02-22 22:01:54 +02:00
Pavel
98775bfdb8 Pass type as keyword argument in migration serialize call
Same fix as applied to Invoice and ReportRenderingOptions models in
the parent PR: Rails 7.2 requires the type class to be passed as a
keyword argument to serialize.

  serialize :options, Hash, coder: YAML
  ->
  serialize :options, type: Hash, coder: YAML

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-21 23:23:12 +00:00
pavelk-lab
47ef21deb3 Merge branch 'master' into fix/rails-7-serialize-deprecation 2026-02-21 23:19:58 +00:00
dependabot[bot]
f80b484b12 Bump ajv from 6.12.6 to 6.14.0
Bumps [ajv](https://github.com/ajv-validator/ajv) from 6.12.6 to 6.14.0.
- [Release notes](https://github.com/ajv-validator/ajv/releases)
- [Commits](https://github.com/ajv-validator/ajv/compare/v6.12.6...v6.14.0)

---
updated-dependencies:
- dependency-name: ajv
  dependency-version: 6.14.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-21 16:39:48 +00:00
Ahmed Ejaz
b455755bfc Update all locales with the latest Transifex translations 2026-02-21 02:34:10 +05:00
dependabot[bot]
1f7c08bbb0 Bump sidekiq-scheduler from 5.0.3 to 6.0.1
Bumps [sidekiq-scheduler](https://github.com/moove-it/sidekiq-scheduler) from 5.0.3 to 6.0.1.
- [Release notes](https://github.com/moove-it/sidekiq-scheduler/releases)
- [Changelog](https://github.com/sidekiq-scheduler/sidekiq-scheduler/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moove-it/sidekiq-scheduler/compare/v5.0.3...v6.0.1)

---
updated-dependencies:
- dependency-name: sidekiq-scheduler
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-20 09:33:43 +00:00
dependabot[bot]
fcb9439cd2 Bump webpack from 5.105.1 to 5.105.2
Bumps [webpack](https://github.com/webpack/webpack) from 5.105.1 to 5.105.2.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Changelog](https://github.com/webpack/webpack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack/compare/v5.105.1...v5.105.2)

---
updated-dependencies:
- dependency-name: webpack
  dependency-version: 5.105.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-20 09:33:13 +00:00
Maikel Linke
96c2b75a0a Spec admin display of Taler payment actions
This should satisfy code coverage.
2026-02-20 13:43:09 +11:00
Maikel Linke
b6438992b9 Speed up spec by not saving to database 2026-02-20 13:43:09 +11:00
Maikel Linke
69108df206 Use Rails to translate email subject
And translate the subject with the user's locale.
If the subject doesn't need parameters, you don't need to supply it.
Rails finds the translation automatically.
2026-02-20 13:43:09 +11:00
Maikel Linke
c66b9611b6 Move PaymentMailer translations out of Spree namespace
The mailer is not in the Spree namespace and we don't need to keep the
clutter.
2026-02-20 13:43:09 +11:00
Maikel Linke
de873ae42c Add void action to Taler for refunds 2026-02-20 13:43:09 +11:00
Maikel Linke
ed701b00dc Stop storing now redundant redirect URL
The Taler gem now computes it from the order id. No need to store it.
2026-02-20 13:43:04 +11:00
Maikel Linke
52e2fb923e Update Taler calls for new v0.2.0 2026-02-20 13:37:46 +11:00
Maikel Linke
a2a9d32c5b Bump taler from 0.1.0 to 0.2.0 2026-02-20 13:37:45 +11:00
Gaetan Craig-Riou
619ecf9432 Merge pull request #13820 from openfoodfoundation/dependabot/npm_and_yarn/hotkeys-js-4.0.0
Bump hotkeys-js from 3.13.15 to 4.0.0
2026-02-20 09:29:22 +11:00
Gaetan Craig-Riou
4f152a9151 Merge pull request #13942 from openfoodfoundation/dependabot/bundler/rubocop-rails-2.34.3
Bump rubocop-rails from 2.34.2 to 2.34.3
2026-02-20 09:21:21 +11:00
dependabot[bot]
8d7252f078 Bump hotkeys-js from 3.13.15 to 4.0.0
Bumps [hotkeys-js](https://github.com/jaywcjlove/hotkeys-js) from 3.13.15 to 4.0.0.
- [Release notes](https://github.com/jaywcjlove/hotkeys-js/releases)
- [Commits](https://github.com/jaywcjlove/hotkeys-js/compare/v3.13.15...v4.0.0)

---
updated-dependencies:
- dependency-name: hotkeys-js
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-19 22:15:49 +00:00
Gaetan Craig-Riou
08399e753d Merge pull request #13941 from openfoodfoundation/dependabot/npm_and_yarn/tom-select-2.5.1
Bump tom-select from 2.4.6 to 2.5.1
2026-02-20 09:13:15 +11:00
Gaetan Craig-Riou
8d721ccac8 Merge pull request #13940 from mkllnk/faraday
Bump faraday from 2.9.0 to 2.14.1
2026-02-20 09:12:08 +11:00
Gaetan Craig-Riou
b7a1b39c1a Merge pull request #13937 from mkllnk/rack
Bump rack from 2.2.21 to 2.2.22
2026-02-20 09:06:16 +11:00
Gaetan Craig-Riou
e276fb0386 Merge pull request #13930 from openfoodfoundation/dependabot/bundler/rubocop-1.84.1
Bump rubocop from 1.81.7 to 1.84.2
2026-02-20 09:05:41 +11:00
Pavel
e98244fe63 Fix Rails 7.2 serialize deprecation warnings
Pass type as keyword argument in serialize calls, as required from Rails 7.2 onwards.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 21:55:13 +00:00
Pavel
b348536d12 Clean up dead code after Angular brand story removal
- Delete HomeCtrl controller file (nothing references it anymore)
- Remove misplaced .text-vbig class from <details> (was on the old <a> toggle; summary has no visible text)
- Remove redundant cursor: pointer on #brand-story-text (<summary> already sets it)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 21:39:32 +00:00
Pavel
b528bb47a0 Replace Angular expand/collapse with native HTML details/summary for brand story
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-19 21:23:09 +00:00
Rachel Arnould
f86eb3fb82 Merge pull request #13920 from mkllnk/clean-name
Stop pre-selecting Paypal when creating a payment method
2026-02-19 11:38:56 +01:00
Rachel Arnould
0d46a3bc2e Merge pull request #13902 from mkllnk/refund-simple
Simplify refund logic
2026-02-19 11:06:00 +01:00
dependabot[bot]
0418163ad7 Bump rubocop-rails from 2.34.2 to 2.34.3
Bumps [rubocop-rails](https://github.com/rubocop/rubocop-rails) from 2.34.2 to 2.34.3.
- [Release notes](https://github.com/rubocop/rubocop-rails/releases)
- [Changelog](https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rails/compare/v2.34.2...v2.34.3)

---
updated-dependencies:
- dependency-name: rubocop-rails
  dependency-version: 2.34.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-19 09:34:06 +00:00
dependabot[bot]
2e67899bcc Bump tom-select from 2.4.6 to 2.5.1
Bumps [tom-select](https://github.com/orchidjs/tom-select) from 2.4.6 to 2.5.1.
- [Release notes](https://github.com/orchidjs/tom-select/releases)
- [Commits](https://github.com/orchidjs/tom-select/compare/v2.4.6...v2.5.1)

---
updated-dependencies:
- dependency-name: tom-select
  dependency-version: 2.5.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-19 09:32:42 +00:00
Maikel Linke
e2536ffe71 Bump faraday from 2.9.0 to 2.14.1 2026-02-19 14:07:47 +11:00
Maikel
2c6b758f66 Merge pull request #13938 from openfoodfoundation/dependabot/bundler/spring-4.4.2
Bump spring from 4.4.0 to 4.4.2
2026-02-19 09:54:03 +11:00
Rachel Arnould
fb0f379c43 Merge pull request #13823 from chahmedejaz/bugfix/13625-enterprise-fee-reports-throws-504
Some Enterprise Fee reports are unusable when managing big shops
2026-02-18 15:22:21 +01:00
dependabot[bot]
7a4aa9dcb1 Bump spring from 4.4.0 to 4.4.2
Bumps [spring](https://github.com/rails/spring) from 4.4.0 to 4.4.2.
- [Release notes](https://github.com/rails/spring/releases)
- [Changelog](https://github.com/rails/spring/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rails/spring/compare/v4.4.0...v4.4.2)

---
updated-dependencies:
- dependency-name: spring
  dependency-version: 4.4.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-18 09:33:00 +00:00
Maikel
4e8d37b0b5 Merge pull request #13935 from openfoodfoundation/dependabot/npm_and_yarn/webpack-5.105.1
Bump webpack from 5.105.0 to 5.105.1
2026-02-18 15:51:35 +11:00
Maikel
616de3a9c0 Merge pull request #13936 from openfoodfoundation/dependabot/bundler/knapsack_pro-9.2.2
Bump knapsack_pro from 8.4.0 to 9.2.2
2026-02-18 15:50:59 +11:00
Maikel Linke
16b3da66c2 Style/HashAsLastArrayItem 2026-02-18 12:45:37 +11:00
Maikel Linke
691995eeaa Bump rubocop from 1.84.1 to 1.84.2 2026-02-18 12:44:41 +11:00
Maikel Linke
045482e07d Revert "Deactivate cooldown for testing"
This reverts commit 13cec27f6b.
2026-02-18 12:11:37 +11:00
dependabot[bot]
62f25d4d31 Bump knapsack_pro from 8.4.0 to 9.2.2
Bumps [knapsack_pro](https://github.com/KnapsackPro/knapsack_pro-ruby) from 8.4.0 to 9.2.2.
- [Changelog](https://github.com/KnapsackPro/knapsack_pro-ruby/blob/main/CHANGELOG.md)
- [Commits](https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v8.4.0...v9.2.2)

---
updated-dependencies:
- dependency-name: knapsack_pro
  dependency-version: 9.2.2
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-18 00:57:55 +00:00
dependabot[bot]
618c7028e2 Bump webpack from 5.105.0 to 5.105.1
Bumps [webpack](https://github.com/webpack/webpack) from 5.105.0 to 5.105.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Changelog](https://github.com/webpack/webpack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack/compare/v5.105.0...v5.105.1)

---
updated-dependencies:
- dependency-name: webpack
  dependency-version: 5.105.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-18 00:55:57 +00:00
Maikel Linke
13cec27f6b Deactivate cooldown for testing 2026-02-18 11:54:32 +11:00
Maikel Linke
5b925517f0 Bump rack from 2.2.21 to 2.2.22 2026-02-18 11:52:33 +11:00
Maikel Linke
167099badf Lint/NoReturnInBeginEndBlocks 2026-02-18 09:44:19 +11:00
Maikel Linke
40d8839bc4 Style Heredoc indentation 2026-02-18 09:42:33 +11:00
Maikel Linke
da1e1a9859 Style indentation 2026-02-18 09:42:07 +11:00
Maikel
43ad7654b6 Merge pull request #13931 from openfoodfoundation/dependabot/bundler/listen-3.10.0
Bump listen from 3.9.0 to 3.10.0
2026-02-18 09:16:12 +11:00
Ahmed Ejaz
1d4bbfa506 Supports tag filters persistence during product updates
Adds functionality to retain tag filters applied in the admin product interface after bulk updates. Updates controller parameters to include tags_name_in, adds hidden fields for tag persistence in the view, and includes specs to verify filter state retention across update operations.
2026-02-18 01:37:41 +05:00
dependabot[bot]
15d83724ea Bump listen from 3.9.0 to 3.10.0
Bumps [listen](https://github.com/guard/listen) from 3.9.0 to 3.10.0.
- [Release notes](https://github.com/guard/listen/releases)
- [Commits](https://github.com/guard/listen/compare/v3.9.0...v3.10.0)

---
updated-dependencies:
- dependency-name: listen
  dependency-version: 3.10.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-17 09:34:08 +00:00
dependabot[bot]
47652e9d25 Bump rubocop from 1.81.7 to 1.84.1
Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.81.7 to 1.84.1.
- [Release notes](https://github.com/rubocop/rubocop/releases)
- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop/compare/v1.81.7...v1.84.1)

---
updated-dependencies:
- dependency-name: rubocop
  dependency-version: 1.84.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-17 09:31:48 +00:00
Maikel Linke
4b689d00a4 Remove unnecessary erb compilation on JS file 2026-02-17 13:56:30 +11:00
Gaetan Craig-Riou
b5315c2123 Merge pull request #13925 from openfoodfoundation/dependabot/npm_and_yarn/tom-select-2.4.6
Bump tom-select from 2.4.5 to 2.4.6
2026-02-17 09:56:09 +11:00
Gaetan Craig-Riou
97ce4eaccd Merge pull request #13928 from openfoodfoundation/dependabot/bundler/pry-0.16.0
Bump pry from 0.15.2 to 0.16.0
2026-02-17 09:48:40 +11:00
Gaetan Craig-Riou
8814427677 Merge pull request #13927 from openfoodfoundation/dependabot/bundler/bootsnap-1.22.0
Bump bootsnap from 1.19.0 to 1.22.0
2026-02-17 09:47:13 +11:00
Gaetan Craig-Riou
4b69e192ec Merge pull request #13926 from openfoodfoundation/dependabot/bundler/rubocop-rspec-3.9.0
Bump rubocop-rspec from 3.8.0 to 3.9.0
2026-02-17 09:45:46 +11:00
dependabot[bot]
9c99f4868c Bump pry from 0.15.2 to 0.16.0
Bumps [pry](https://github.com/pry/pry) from 0.15.2 to 0.16.0.
- [Release notes](https://github.com/pry/pry/releases)
- [Changelog](https://github.com/pry/pry/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pry/pry/compare/v0.15.2...v0.16.0)

---
updated-dependencies:
- dependency-name: pry
  dependency-version: 0.16.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-16 10:22:39 +00:00
dependabot[bot]
39d59c3a5f Bump bootsnap from 1.19.0 to 1.22.0
Bumps [bootsnap](https://github.com/rails/bootsnap) from 1.19.0 to 1.22.0.
- [Release notes](https://github.com/rails/bootsnap/releases)
- [Changelog](https://github.com/rails/bootsnap/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rails/bootsnap/compare/v1.19.0...v1.22.0)

---
updated-dependencies:
- dependency-name: bootsnap
  dependency-version: 1.22.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-16 10:21:52 +00:00
dependabot[bot]
ad9a12da0e Bump rubocop-rspec from 3.8.0 to 3.9.0
Bumps [rubocop-rspec](https://github.com/rubocop/rubocop-rspec) from 3.8.0 to 3.9.0.
- [Release notes](https://github.com/rubocop/rubocop-rspec/releases)
- [Changelog](https://github.com/rubocop/rubocop-rspec/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rspec/compare/v3.8.0...v3.9.0)

---
updated-dependencies:
- dependency-name: rubocop-rspec
  dependency-version: 3.9.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-16 10:20:43 +00:00
dependabot[bot]
9968776726 Bump tom-select from 2.4.5 to 2.4.6
Bumps [tom-select](https://github.com/orchidjs/tom-select) from 2.4.5 to 2.4.6.
- [Release notes](https://github.com/orchidjs/tom-select/releases)
- [Commits](https://github.com/orchidjs/tom-select/compare/v2.4.5...v2.4.6)

---
updated-dependencies:
- dependency-name: tom-select
  dependency-version: 2.4.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-16 10:20:27 +00:00
Gaetan Craig-Riou
d99a88817d Merge pull request #13825 from openfoodfoundation/dependabot/bundler/omniauth-rails_csrf_protection-2.0.1
Bump omniauth-rails_csrf_protection from 1.0.2 to 2.0.1
2026-02-16 11:52:16 +11:00
dependabot[bot]
1b36cce816 Bump omniauth-rails_csrf_protection from 1.0.2 to 2.0.1
Bumps [omniauth-rails_csrf_protection](https://github.com/cookpad/omniauth-rails_csrf_protection) from 1.0.2 to 2.0.1.
- [Release notes](https://github.com/cookpad/omniauth-rails_csrf_protection/releases)
- [Commits](https://github.com/cookpad/omniauth-rails_csrf_protection/compare/v1.0.2...v2.0.1)

---
updated-dependencies:
- dependency-name: omniauth-rails_csrf_protection
  dependency-version: 2.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-16 00:30:33 +00:00
Gaetan Craig-Riou
4b157abd4d Merge pull request #13809 from openfoodfoundation/dependabot/bundler/active_storage_validations-3.0.3
Bump active_storage_validations from 3.0.2 to 3.0.3
2026-02-16 11:28:41 +11:00
Gaetan Craig-Riou
dc494bb0f9 Merge pull request #13801 from openfoodfoundation/dependabot/bundler/bullet-8.1.0
Bump bullet from 8.0.8 to 8.1.0
2026-02-16 11:12:39 +11:00
dependabot[bot]
b3e7b12b86 Bump active_storage_validations from 1.1.4 to 3.0.3
Bumps [active_storage_validations](https://github.com/igorkasyanchuk/active_storage_validations) from 1.1.4 to 3.0.3.
- [Release notes](https://github.com/igorkasyanchuk/active_storage_validations/releases)
- [Changelog](https://github.com/igorkasyanchuk/active_storage_validations/blob/master/CHANGES.md)
- [Commits](https://github.com/igorkasyanchuk/active_storage_validations/commits/3.0.03)

---
updated-dependencies:
- dependency-name: active_storage_validations
  dependency-version: 3.0.3
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-15 23:47:01 +00:00
dependabot[bot]
b69e6827cc Bump bullet from 8.0.8 to 8.1.0
Bumps [bullet](https://github.com/flyerhzm/bullet) from 8.0.8 to 8.1.0.
- [Changelog](https://github.com/flyerhzm/bullet/blob/main/CHANGELOG.md)
- [Commits](https://github.com/flyerhzm/bullet/compare/8.0.8...8.1.0)

---
updated-dependencies:
- dependency-name: bullet
  dependency-version: 8.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-15 23:46:31 +00:00
Gaetan Craig-Riou
340f459912 Merge pull request #13791 from openfoodfoundation/dependabot/bundler/responders-3.2.0
Bump responders from 3.1.1 to 3.2.0
2026-02-16 10:44:39 +11:00
dependabot[bot]
33a96d5a0f Bump responders from 3.1.1 to 3.2.0
Bumps [responders](https://github.com/heartcombo/responders) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/heartcombo/responders/releases)
- [Changelog](https://github.com/heartcombo/responders/blob/main/CHANGELOG.md)
- [Commits](https://github.com/heartcombo/responders/compare/v3.1.1...v3.2.0)

---
updated-dependencies:
- dependency-name: responders
  dependency-version: 3.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-15 22:49:10 +00:00
Gaetan Craig-Riou
93d6db9d44 Merge pull request #13924 from openfoodfoundation/dependabot/npm_and_yarn/sass-loader-16.0.7
Bump sass-loader from 16.0.6 to 16.0.7
2026-02-16 09:42:37 +11:00
dependabot[bot]
c1068af0ba Bump sass-loader from 16.0.6 to 16.0.7
Bumps [sass-loader](https://github.com/webpack/sass-loader) from 16.0.6 to 16.0.7.
- [Release notes](https://github.com/webpack/sass-loader/releases)
- [Changelog](https://github.com/webpack/sass-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webpack/sass-loader/compare/v16.0.6...v16.0.7)

---
updated-dependencies:
- dependency-name: sass-loader
  dependency-version: 16.0.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-13 09:32:32 +00:00
Maikel Linke
482c2a4a6e Delete now unused method clean_name 2026-02-13 12:36:26 +11:00
Gaetan Craig-Riou
2557a4de39 Merge pull request #13921 from openfoodfoundation/dependabot/npm_and_yarn/qs-6.14.2
Bump qs from 6.14.1 to 6.14.2
2026-02-13 12:27:04 +11:00
dependabot[bot]
ab1f43f1ac Bump qs from 6.14.1 to 6.14.2
Bumps [qs](https://github.com/ljharb/qs) from 6.14.1 to 6.14.2.
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.14.1...v6.14.2)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.14.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-13 01:17:44 +00:00
Maikel
f921524588 Merge pull request #13923 from rioug/upgrade-redit-github-action
Upgrade redis-github-action to 1.8.1
2026-02-13 11:45:13 +11:00
Gaetan Craig-Riou
5cbd507c1e Upgrade redis-github-action to 1.8.1
The version we were using, uses an obsolete version of Docker
2026-02-13 10:20:51 +11:00
Gaetan Craig-Riou
532bfaaa2d Merge pull request #13919 from pacodelaluna/allow-s3-compatible-provider-for-db2fog-config
Allow S3-compatible provider for db2fog configuration
2026-02-13 10:07:20 +11:00
Gaetan Craig-Riou
70b31a4212 Merge pull request #13918 from openfoodfoundation/dependabot/npm_and_yarn/webpack-5.105.0
Bump webpack from 5.104.1 to 5.105.0
2026-02-13 09:49:06 +11:00
Maikel Linke
9da3b0ea01 User must choose payment method type on creation 2026-02-12 15:15:27 +11:00
Maikel Linke
51df612c51 Spec current default selection
And fix the matcher!

This matcher was written over ten years ago in 2015. But it never failed
wrong tests.
2026-02-12 15:15:27 +11:00
Maikel Linke
3be0cca230 Move options code into helper 2026-02-12 11:47:01 +11:00
Maikel Linke
283d13eb35 Move payment method display logic to helper
So we don't need to convert strings into classes to then only convert it
into the same string again.
2026-02-12 11:25:13 +11:00
François Turbelin
b21224d5ff Allow s3-compatible provider for db2fog configuration 2026-02-11 13:35:22 +01:00
dependabot[bot]
4744d7b741 Bump webpack from 5.104.1 to 5.105.0
Bumps [webpack](https://github.com/webpack/webpack) from 5.104.1 to 5.105.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Changelog](https://github.com/webpack/webpack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack/compare/v5.104.1...v5.105.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-version: 5.105.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-11 09:33:05 +00:00
Gaetan Craig-Riou
ac1dd74e23 Merge pull request #13914 from openfoodfoundation/dependabot/npm_and_yarn/babel/plugin-transform-runtime-7.29.0
Bump @babel/plugin-transform-runtime from 7.28.5 to 7.29.0
2026-02-11 10:13:13 +11:00
Gaetan Craig-Riou
970f486ec0 Merge pull request #13913 from openfoodfoundation/dependabot/npm_and_yarn/tom-select-2.4.5
Bump tom-select from 2.4.3 to 2.4.5
2026-02-11 10:12:11 +11:00
dependabot[bot]
8c244e8b56 Bump @babel/plugin-transform-runtime from 7.28.5 to 7.29.0
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.28.5 to 7.29.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.29.0/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-version: 7.29.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-10 09:33:14 +00:00
dependabot[bot]
c3cc01c677 Bump tom-select from 2.4.3 to 2.4.5
Bumps [tom-select](https://github.com/orchidjs/tom-select) from 2.4.3 to 2.4.5.
- [Release notes](https://github.com/orchidjs/tom-select/releases)
- [Commits](https://github.com/orchidjs/tom-select/compare/v2.4.3...v2.4.5)

---
updated-dependencies:
- dependency-name: tom-select
  dependency-version: 2.4.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-10 09:32:51 +00:00
Gaetan Craig-Riou
c63e60d782 Merge pull request #13910 from openfoodfoundation/dependabot/npm_and_yarn/babel/core-7.29.0
Bump @babel/core from 7.28.6 to 7.29.0
2026-02-10 09:24:06 +11:00
dependabot[bot]
11e8c9456d Bump @babel/core from 7.28.6 to 7.29.0
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.28.6 to 7.29.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.29.0/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-version: 7.29.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-09 22:10:18 +00:00
Gaetan Craig-Riou
860a21f86f Merge pull request #13909 from openfoodfoundation/dependabot/npm_and_yarn/babel/preset-env-7.29.0
Bump @babel/preset-env from 7.28.6 to 7.29.0
2026-02-10 09:09:09 +11:00
dependabot[bot]
d24af18ff4 Bump @babel/preset-env from 7.28.6 to 7.29.0
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.28.6 to 7.29.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.29.0/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-version: 7.29.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-09 10:39:41 +00:00
David Cook
33b191f439 Merge pull request #13908 from chahmedejaz/bugfix/13776-datetime-format-for-finnish
Update Finnish date and datetime formats in locale file
2026-02-09 10:41:22 +11:00
Ahmed Ejaz
a690d39864 Update Finnish date and datetime formats in locale file 2026-02-08 18:41:49 +05:00
Ahmed Ejaz
7c0586db7b Enhance comment for shouldLoad function 2026-02-08 18:29:55 +05:00
Ahmed Ejaz
461fd00ccd Add specs for non-linked fees by introducing specs for non-admin users. Plus include specs refactoring 2026-02-08 18:06:54 +05:00
Maikel Linke
f872201fef Delete defunct spec
From a comment on Github:

> In this particular case, the spec is broken, actually. I just looked into it and you are right that StripeSCA supports payment profiles but the spec finds that the profile is not stored. And that is because `source.try(:save_requested_by_customer?)` returns false. We only store the profile when the customer is storing their credit card info.
2026-02-06 11:35:24 +11:00
Maikel Linke
162c58ac39 Check which methods we need to delegate
This implicit delegation makes it impossible to know which code is used
and which code is dead. The refund method is very rarely used though. So
we'll need to wait for a while.
2026-02-04 12:24:50 +11:00
Maikel Linke
02d47d0a0d Remove unused method #payment_profiles_supported?
And useless specs.
2026-02-04 11:37:53 +11:00
Maikel Linke
e86bf441ab Remove last use of #payment_profiles_supported? 2026-02-04 11:30:36 +11:00
Maikel Linke
f9617b8156 Remove broken dead code branch
The StripeSCA method is forwarding all missing methods to the provider
gateway. The ActiveMerchant gateway used to be decorated by our code and
that's how this code may have worked one day. But we removed the
decorator years ago:

- 549610bc35

A bit later we found that refunds are broken with Stripe:

- https://github.com/openfoodfoundation/openfoodnetwork/issues/12843

This commit could potentiall fix that, I guess? I haven't tested that.
It's a rare use case and not the aim of this work.
2026-02-04 11:30:36 +11:00
Maikel Linke
4650e30c09 Remove useless branch on credit method 2026-02-04 11:30:36 +11:00
Maikel Linke
2749965e73 Remove useless branch calling #void
StripeSCA is the only method with a different method signature for
`#void` but the additional parameter wasn't used. So this special case
can just be removed.
2026-02-04 11:30:36 +11:00
Maikel Linke
e87965bda0 Simplify storing of payment profiles
StripeSCA is the only payment method storing profiles following this
logic. This is the first step to remove indirection and let the payment
method handle this instead of the payment decided for the payment
method.
2026-02-04 11:30:36 +11:00
Ahmed Ejaz
9dcb3ec748 Refactor report routes to use scoped routes for better organization and readability 2026-02-04 03:55:07 +05:00
Ahmed Ejaz
90c23d0245 fix lint issue 2026-02-04 02:26:44 +05:00
Ahmed Ejaz
99e238d92d Improve reports AJAX search safety, permissions, and TomSelect UX
- Sanitize AJAX search queries to safely support wildcard searches (ILIKE)
- Centralize reports search actions in Spree::Ability and reuse across roles
- Fix TomSelect remote loading to fetch on dropdown open and typing
- Surface HTTP errors in TomSelect via showHttpError and improve error handling
- Update dropdown behavior to show proper “no results” feedback
- Move reports AJAX specs to request specs and expand pagination coverage
- Simplify searchable dropdown component attribute passing
2026-02-04 02:25:41 +05:00
Ahmed Ejaz
8eb9709a04 Fix specs:
Fix tom_select_options_value to conditionally include 'virtual_scroll' plugin based on remote URL presence
2026-02-01 19:45:39 +05:00
Ahmed Ejaz
5f31baa022 Refactor TomSelectController to enhance remote data loading and update SearchableDropdownComponent options 2026-02-01 19:32:18 +05:00
Prikesh Savla
5a9aa87831 Rename admin-style-v3 to admin-style and remove the admin_legacy styles folder that has no references 2026-01-25 21:15:40 +05:30
Prikesh Savla
8cfab08f9e Refactor admin CSS: Promote v3 to canonical admin styles
The Admin V3 styles are now the primary styles for the application. This change promotes the `admin_v3` directory to `admin` and archives the old styles.

Changes:
- Renamed `app/webpacker/css/admin_v3` to `app/webpacker/css/admin`.
- Renamed the previous `app/webpacker/css/admin` to `app/webpacker/css/admin_legacy`.
- Moved all files referenced by V3 styles from the legacy directory to the new `admin` directory.
- Updated imports in `all.scss` to distinct local files instead of relative paths.
- Cleaned up `admin_legacy` by removing files that are duplicates (by name or content) of the new admin styles.
- Updated `admin-style-v3` pack to point to the new location.
2026-01-25 21:05:38 +05:30
Ahmed Ejaz
b58834b11f Fix failing specs 2026-01-25 19:13:43 +05:00
Ahmed Ejaz
d4811648f1 Merge branch 'master' into bugfix/13625-enterprise-fee-reports-throws-504 2026-01-25 11:22:57 +05:00
Ahmed Ejaz
77fe1fa6f9 Refactor SearchableDropdownComponent and integrate remote data loading with TomSelect 2026-01-25 11:14:49 +05:00
Ahmed Ejaz
03b7c07495 Add tests for Select2AjaxController with AJAX functionality 2025-12-30 01:25:35 +05:00
Ahmed Ejaz
a3c08ceb7c Add AJAX search functionality for enterprise fees and related entities in reports 2025-12-30 01:25:25 +05:00
Konrad
e814fdd447 Remove test for active white labeling in test email as proposed by David 2025-12-29 12:36:50 +01:00
David Cook
4d6231105f Assign attribute directly instead of mocking
It's better to set a variable the same way the real code would

Co-authored-by: Maikel <maikel@email.org.au>
2025-12-29 12:18:55 +01:00
Konrad
3a75c3446e Update backorder mailer specs to check that these hub facing emails remain unaffected by white labelling (there are no customer facing emails here)
Also make use of the newly separated shared_examples
2025-12-29 12:18:55 +01:00
Konrad
29a76fd721 Update report mailer specs to check that this enterprise facing email remains unaffected by white labelling (there are no customer facing emails here)
Also make use of the newly separated shared_examples
2025-12-29 12:18:55 +01:00
Konrad
593bd89095 Update test mailer specs to check that this super admin facing email remains unaffected by white labelling (there are no user or customer facing emails here)
Also make use of the newly separated shared_examples
2025-12-29 12:18:55 +01:00
Konrad
0079ed219b Update producer mailer specs to check that this producer facing email remains unaffected by white labelling (there are no customer facing emails here)
Also make use of the newly separated shared_examples
2025-12-29 12:18:55 +01:00
Konrad
5957d99812 Update enterprise mailer specs to check that enterprise facing emails remain unaffected by white labelling (there are no customer facing emails here)
Also make use of the newly separated shared_examples
2025-12-29 12:18:55 +01:00
Konrad
89453ec758 Update subscription mailer specs to check that customer facing emails are white labelled, while shop facing emails are not
Also make use of the newly separated shared_examples

Made the check for link to order page more general, because on my system a double quote was expected but a single quote was generated
2025-12-29 12:18:55 +01:00
Konrad
0de4f2f596 Update payment mailer specs to check that customer facing emails are white labelled, while shop facing emails are not
Also make use of the newly separated shared_examples
2025-12-29 12:18:55 +01:00
Konrad
183cbecef6 Update shipment mailer specs to check that customer facing emails are white labelled (there are no shop facing emails here)
Make use of the newly separated shared_examples
2025-12-29 12:18:55 +01:00
Konrad
ab6a49e568 Update order mailer specs to check that customer facing emails are white labelled, while shop facing emails are not
Also make use of the newly separated shared_examples

Including the invoice email was too tricky for me for now, sorry
2025-12-29 12:18:55 +01:00
Konrad
52ddb29dc7 Update user mailer specs to check that white labelling does not affect these emails
Move tests to separate file for reuse in other emails

Pass on :mail symbol and obtain the mail-object using public_send() to call it with different names
2025-12-29 12:18:54 +01:00
drummer83
5ce7905a33 White labelling ALL customer facing emails
White labelling added for Order: cancellation email, Order: invoice email, Shipment: shipped email, Subscriptions: authorize payment email, Subscriptions: placement email, Subscriptions: empty order email, Subscriptions: failed payment email

White labelling existed already for Order: confirmation email, Subscriptions: order confirmation email
2025-12-29 12:18:54 +01:00
197 changed files with 2711 additions and 2791 deletions

View File

@@ -27,7 +27,12 @@ assignees: ''
- [ ] Move this issue to Test Ready. - [ ] Move this issue to Test Ready.
- [ ] Notify `@testers` in [#testing]. - [ ] Notify `@testers` in [#testing].
- [ ] Test build: [Deploy to Staging] with release tag. - [ ] Test build: [Deploy to Staging] with release tag.
- [ ] Notify a deployer to deploy it - [ ] Map is displayed correctly. Address changes are reflected in the map.
- [ ] Stripe with no authentication card: `4242424242424242` as shopper and as Admin. Order confirmation displays order as "Paid".
- [ ] Stripe with Authentication required card: `4000002760003184` as shopper and as Admin. As admin, check authorization through customer account `/account#/transactions` and email.
- [ ] Pay with Paypal.
- [ ] Order on mobile.
- [ ] Notify a deployer to deploy it.
## 3. Deployment at beginning of week ## 3. Deployment at beginning of week

View File

@@ -46,7 +46,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup redis - name: Setup redis
uses: supercharge/redis-github-action@1.4.0 uses: supercharge/redis-github-action@1.8.1
with: with:
redis-version: 6 redis-version: 6
@@ -124,7 +124,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup redis - name: Setup redis
uses: supercharge/redis-github-action@1.4.0 uses: supercharge/redis-github-action@1.8.1
with: with:
redis-version: 6 redis-version: 6
@@ -211,7 +211,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup redis - name: Setup redis
uses: supercharge/redis-github-action@1.4.0 uses: supercharge/redis-github-action@1.8.1
with: with:
redis-version: 6 redis-version: 6
@@ -290,7 +290,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup redis - name: Setup redis
uses: supercharge/redis-github-action@1.4.0 uses: supercharge/redis-github-action@1.8.1
with: with:
redis-version: 6 redis-version: 6

View File

@@ -112,7 +112,7 @@ GEM
rails-html-sanitizer (~> 1.6) rails-html-sanitizer (~> 1.6)
active_model_serializers (0.8.4) active_model_serializers (0.8.4)
activemodel (>= 3.0) activemodel (>= 3.0)
active_storage_validations (3.0.2) active_storage_validations (3.0.3)
activejob (>= 6.1.4) activejob (>= 6.1.4)
activemodel (>= 6.1.4) activemodel (>= 6.1.4)
activestorage (>= 6.1.4) activestorage (>= 6.1.4)
@@ -170,7 +170,7 @@ GEM
addressable (2.8.8) addressable (2.8.8)
public_suffix (>= 2.0.2, < 8.0) public_suffix (>= 2.0.2, < 8.0)
aes_key_wrap (1.1.0) aes_key_wrap (1.1.0)
afm (0.2.2) afm (1.0.0)
angular-rails-templates (1.4.0) angular-rails-templates (1.4.0)
railties (>= 5.0, < 8.2) railties (>= 5.0, < 8.2)
sprockets (>= 3.0, < 5) sprockets (>= 3.0, < 5)
@@ -210,12 +210,12 @@ GEM
bigdecimal (3.3.1) bigdecimal (3.3.1)
bindata (2.5.1) bindata (2.5.1)
bindex (0.8.1) bindex (0.8.1)
bootsnap (1.19.0) bootsnap (1.22.0)
msgpack (~> 1.2) msgpack (~> 1.2)
bugsnag (6.28.0) bugsnag (6.28.0)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
builder (3.3.0) builder (3.3.0)
bullet (8.0.8) bullet (8.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
uniform_notifier (~> 1.11) uniform_notifier (~> 1.11)
cable_ready (5.0.6) cable_ready (5.0.6)
@@ -242,7 +242,7 @@ GEM
marcel (~> 1.0) marcel (~> 1.0)
nokogiri (~> 1.10, >= 1.10.4) nokogiri (~> 1.10, >= 1.10.4)
rubyzip (>= 1.3.0, < 3) rubyzip (>= 1.3.0, < 3)
cgi (0.5.0) cgi (0.5.1)
childprocess (5.0.0) childprocess (5.0.0)
choice (0.2.0) choice (0.2.0)
chronic (0.10.2) chronic (0.10.2)
@@ -257,7 +257,7 @@ GEM
combine_pdf (1.0.31) combine_pdf (1.0.31)
matrix matrix
ruby-rc4 (>= 0.1.5) ruby-rc4 (>= 0.1.5)
concurrent-ruby (1.3.5) concurrent-ruby (1.3.6)
connection_pool (2.5.5) connection_pool (2.5.5)
cookiejar (0.3.4) cookiejar (0.3.4)
crack (1.0.1) crack (1.0.1)
@@ -267,9 +267,9 @@ GEM
css_parser (1.21.1) css_parser (1.21.1)
addressable addressable
csv (3.3.5) csv (3.3.5)
cuprite (0.15) cuprite (0.17)
capybara (~> 3.0) capybara (~> 3.0)
ferrum (~> 0.14.0) ferrum (~> 0.17.0)
database_cleaner (2.1.0) database_cleaner (2.1.0)
database_cleaner-active_record (>= 2, < 3) database_cleaner-active_record (>= 2, < 3)
database_cleaner-active_record (2.2.2) database_cleaner-active_record (2.2.2)
@@ -278,7 +278,7 @@ GEM
database_cleaner-core (2.0.1) database_cleaner-core (2.0.1)
datafoodconsortium-connector (1.2.0) datafoodconsortium-connector (1.2.0)
virtual_assembly-semantizer (~> 1.0, >= 1.0.5) virtual_assembly-semantizer (~> 1.0, >= 1.0.5)
date (3.5.0) date (3.5.1)
debug (1.11.0) debug (1.11.0)
irb (~> 1.10) irb (~> 1.10)
reline (>= 0.3.8) reline (>= 0.3.8)
@@ -315,7 +315,7 @@ GEM
activemodel activemodel
erb (6.0.1) erb (6.0.1)
erubi (1.13.1) erubi (1.13.1)
et-orbi (1.3.0) et-orbi (1.4.0)
tzinfo tzinfo
eventmachine (1.2.7) eventmachine (1.2.7)
eventmachine_httpserver (0.2.1) eventmachine_httpserver (0.2.1)
@@ -326,19 +326,22 @@ GEM
factory_bot_rails (6.2.0) factory_bot_rails (6.2.0)
factory_bot (~> 6.2.0) factory_bot (~> 6.2.0)
railties (>= 5.0.0) railties (>= 5.0.0)
faraday (2.9.0) faraday (2.14.1)
faraday-net_http (>= 2.0, < 3.2) faraday-net_http (>= 2.0, < 3.5)
json
logger
faraday-follow_redirects (0.4.0) faraday-follow_redirects (0.4.0)
faraday (>= 1, < 3) faraday (>= 1, < 3)
faraday-net_http (3.1.1) faraday-net_http (3.4.2)
net-http net-http (~> 0.5)
ferrum (0.14) ferrum (0.17.1)
addressable (~> 2.5) addressable (~> 2.5)
base64 (~> 0.2)
concurrent-ruby (~> 1.1) concurrent-ruby (~> 1.1)
webrick (~> 1.7) webrick (~> 1.7)
websocket-driver (>= 0.6, < 0.8) websocket-driver (~> 0.7)
ffaker (2.25.0) ffaker (2.25.0)
ffi (1.17.2) ffi (1.17.3)
flipper (1.3.6) flipper (1.3.6)
concurrent-ruby (< 2) concurrent-ruby (< 2)
flipper-active_record (1.3.6) flipper-active_record (1.3.6)
@@ -369,8 +372,8 @@ GEM
foreman (0.90.0) foreman (0.90.0)
thor (~> 1.4) thor (~> 1.4)
formatador (0.2.5) formatador (0.2.5)
fugit (1.11.1) fugit (1.12.1)
et-orbi (~> 1, >= 1.2.11) et-orbi (~> 1.4)
raabro (~> 1.4) raabro (~> 1.4)
fuubar (2.5.1) fuubar (2.5.1)
rspec-core (~> 3.0) rspec-core (~> 3.0)
@@ -396,12 +399,13 @@ GEM
sysexits (~> 1.1) sysexits (~> 1.1)
hashdiff (1.2.1) hashdiff (1.2.1)
hashery (2.1.2) hashery (2.1.2)
hashie (5.0.0) hashie (5.1.0)
logger
highline (3.1.2) highline (3.1.2)
reline reline
htmlentities (4.4.2) htmlentities (4.4.2)
http_parser.rb (0.8.0) http_parser.rb (0.8.0)
i18n (1.14.7) i18n (1.14.8)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
i18n-js (3.9.2) i18n-js (3.9.2)
i18n (>= 0.6.6) i18n (>= 0.6.6)
@@ -425,10 +429,11 @@ GEM
activerecord (>= 3.0) activerecord (>= 3.0)
invisible_captcha (2.3.0) invisible_captcha (2.3.0)
rails (>= 5.2) rails (>= 5.2)
io-console (0.8.1) io-console (0.8.2)
ipaddress (0.8.3) ipaddress (0.8.3)
irb (1.15.3) irb (1.17.0)
pp (>= 0.6.0) pp (>= 0.6.0)
prism (>= 1.3.0)
rdoc (>= 4.0.0) rdoc (>= 4.0.0)
reline (>= 0.4.2) reline (>= 0.4.2)
jmespath (1.6.2) jmespath (1.6.2)
@@ -438,7 +443,7 @@ GEM
thor (>= 0.14, < 2.0) thor (>= 0.14, < 2.0)
jquery-ui-rails (4.2.1) jquery-ui-rails (4.2.1)
railties (>= 3.2.16) railties (>= 3.2.16)
json (2.15.2) json (2.18.1)
json-canonicalization (1.0.0) json-canonicalization (1.0.0)
json-jwt (1.17.0) json-jwt (1.17.0)
activesupport (>= 4.2) activesupport (>= 4.2)
@@ -464,7 +469,7 @@ GEM
activesupport (>= 4.2) activesupport (>= 4.2)
jwt (2.10.2) jwt (2.10.2)
base64 base64
knapsack_pro (8.4.0) knapsack_pro (9.2.2)
rake rake
language_server-protocol (3.17.0.5) language_server-protocol (3.17.0.5)
launchy (3.0.0) launchy (3.0.0)
@@ -474,11 +479,12 @@ GEM
launchy (>= 2.2, < 4) launchy (>= 2.2, < 4)
link_header (0.0.8) link_header (0.0.8)
lint_roller (1.1.0) lint_roller (1.1.0)
listen (3.9.0) listen (3.10.0)
logger
rb-fsevent (~> 0.10, >= 0.10.3) rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10) rb-inotify (~> 0.9, >= 0.9.10)
logger (1.7.0) logger (1.7.0)
loofah (2.24.1) loofah (2.25.0)
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.12.0) nokogiri (>= 1.12.0)
mail (2.9.0) mail (2.9.0)
@@ -501,7 +507,8 @@ GEM
logger logger
mini_mime (1.1.5) mini_mime (1.1.5)
mini_portile2 (2.8.6) mini_portile2 (2.8.6)
minitest (5.26.2) minitest (6.0.1)
prism (~> 1.5)
monetize (1.13.0) monetize (1.13.0)
money (~> 6.12) money (~> 6.12)
money (6.16.0) money (6.16.0)
@@ -510,8 +517,8 @@ GEM
multi_json (1.17.0) multi_json (1.17.0)
multi_xml (0.6.0) multi_xml (0.6.0)
mutex_m (0.3.0) mutex_m (0.3.0)
net-http (0.7.0) net-http (0.9.1)
uri uri (>= 0.11.1)
net-imap (0.5.12) net-imap (0.5.12)
date date
net-protocol net-protocol
@@ -523,7 +530,8 @@ GEM
net-protocol net-protocol
newrelic_rpm (9.24.0) newrelic_rpm (9.24.0)
nio4r (2.7.5) nio4r (2.7.5)
nokogiri (1.18.10) nokogiri (1.19.1)
mini_portile2 (~> 2.8.2)
racc (~> 1.4) racc (~> 1.4)
nokogiri-html5-inference (0.3.0) nokogiri-html5-inference (0.3.0)
nokogiri (~> 1.14) nokogiri (~> 1.14)
@@ -539,7 +547,7 @@ GEM
logger logger
rack (>= 2.2.3) rack (>= 2.2.3)
rack-protection rack-protection
omniauth-rails_csrf_protection (1.0.2) omniauth-rails_csrf_protection (2.0.1)
actionpack (>= 4.2) actionpack (>= 4.2)
omniauth (~> 2.0) omniauth (~> 2.0)
omniauth_openid_connect (0.8.0) omniauth_openid_connect (0.8.0)
@@ -568,7 +576,7 @@ GEM
parallel (1.27.0) parallel (1.27.0)
paranoia (2.6.4) paranoia (2.6.4)
activerecord (>= 5.1, < 7.2) activerecord (>= 5.1, < 7.2)
parser (3.3.10.0) parser (3.3.10.2)
ast (~> 2.4.1) ast (~> 2.4.1)
racc racc
paypal-sdk-core (0.3.4) paypal-sdk-core (0.3.4)
@@ -576,7 +584,7 @@ GEM
xml-simple xml-simple
paypal-sdk-merchant (1.117.2) paypal-sdk-merchant (1.117.2)
paypal-sdk-core (~> 0.3.0) paypal-sdk-core (~> 0.3.0)
pdf-reader (2.15.0) pdf-reader (2.15.1)
Ascii85 (>= 1.0, < 3.0, != 2.0.0) Ascii85 (>= 1.0, < 3.0, != 2.0.0)
afm (>= 0.2.1, < 2) afm (>= 0.2.1, < 2)
hashery (~> 2.0) hashery (~> 2.0)
@@ -586,15 +594,16 @@ GEM
pp (0.6.3) pp (0.6.3)
prettyprint prettyprint
prettyprint (0.2.0) prettyprint (0.2.0)
prism (1.7.0) prism (1.9.0)
private_address_check (0.5.0) private_address_check (0.5.0)
pry (0.15.2) pry (0.16.0)
coderay (~> 1.1) coderay (~> 1.1)
method_source (~> 1.0) method_source (~> 1.0)
reline (>= 0.6.0)
psych (5.3.1) psych (5.3.1)
date date
stringio stringio
public_suffix (7.0.0) public_suffix (7.0.2)
puffing-billy (4.0.2) puffing-billy (4.0.2)
addressable (~> 2.5) addressable (~> 2.5)
em-http-request (~> 1.1, >= 1.1.0) em-http-request (~> 1.1, >= 1.1.0)
@@ -610,7 +619,7 @@ GEM
railties (>= 4.2) railties (>= 4.2)
raabro (1.4.0) raabro (1.4.0)
racc (1.8.1) racc (1.8.1)
rack (2.2.21) rack (2.2.22)
rack-mini-profiler (2.3.4) rack-mini-profiler (2.3.4)
rack (>= 1.2.0) rack (>= 1.2.0)
rack-oauth2 (2.3.0) rack-oauth2 (2.3.0)
@@ -684,7 +693,7 @@ GEM
activesupport (>= 6.1.5) activesupport (>= 6.1.5)
i18n i18n
rb-fsevent (0.11.2) rb-fsevent (0.11.2)
rb-inotify (0.10.1) rb-inotify (0.11.1)
ffi (~> 1.0) ffi (~> 1.0)
rdf (3.3.4) rdf (3.3.4)
bcp47_spec (~> 0.2) bcp47_spec (~> 0.2)
@@ -693,7 +702,7 @@ GEM
logger (~> 1.5) logger (~> 1.5)
ostruct (~> 0.6) ostruct (~> 0.6)
readline (~> 0.0) readline (~> 0.0)
rdoc (7.0.1) rdoc (7.2.0)
erb erb
psych (>= 4.0.0) psych (>= 4.0.0)
tsort tsort
@@ -702,16 +711,16 @@ GEM
redcarpet (3.6.1) redcarpet (3.6.1)
redis (5.4.1) redis (5.4.1)
redis-client (>= 0.22.0) redis-client (>= 0.22.0)
redis-client (0.26.1) redis-client (0.26.4)
connection_pool connection_pool
regexp_parser (2.11.3) regexp_parser (2.11.3)
reline (0.6.3) reline (0.6.3)
io-console (~> 0.5) io-console (~> 0.5)
request_store (1.7.0) request_store (1.7.0)
rack (>= 1.4) rack (>= 1.4)
responders (3.1.1) responders (3.2.0)
actionpack (>= 5.2) actionpack (>= 7.0)
railties (>= 5.2) railties (>= 7.0)
rexml (3.4.4) rexml (3.4.4)
roadie (5.2.1) roadie (5.2.1)
css_parser (~> 1.4) css_parser (~> 1.4)
@@ -766,7 +775,7 @@ GEM
rswag-ui (2.17.0) rswag-ui (2.17.0)
actionpack (>= 5.2, < 8.2) actionpack (>= 5.2, < 8.2)
railties (>= 5.2, < 8.2) railties (>= 5.2, < 8.2)
rubocop (1.81.7) rubocop (1.84.2)
json (~> 2.3) json (~> 2.3)
language_server-protocol (~> 3.17.0.2) language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0) lint_roller (~> 1.1.0)
@@ -774,25 +783,25 @@ GEM
parser (>= 3.3.0.2) parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0) regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.47.1, < 2.0) rubocop-ast (>= 1.49.0, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0) unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.48.0) rubocop-ast (1.49.0)
parser (>= 3.3.7.2) parser (>= 3.3.7.2)
prism (~> 1.4) prism (~> 1.7)
rubocop-capybara (2.22.1) rubocop-capybara (2.22.1)
lint_roller (~> 1.1) lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1) rubocop (~> 1.72, >= 1.72.1)
rubocop-factory_bot (2.28.0) rubocop-factory_bot (2.28.0)
lint_roller (~> 1.1) lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1) rubocop (~> 1.72, >= 1.72.1)
rubocop-rails (2.34.2) rubocop-rails (2.34.3)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
lint_roller (~> 1.1) lint_roller (~> 1.1)
rack (>= 1.1) rack (>= 1.1)
rubocop (>= 1.75.0, < 2.0) rubocop (>= 1.75.0, < 2.0)
rubocop-ast (>= 1.44.0, < 2.0) rubocop-ast (>= 1.44.0, < 2.0)
rubocop-rspec (3.8.0) rubocop-rspec (3.9.0)
lint_roller (~> 1.1) lint_roller (~> 1.1)
rubocop (~> 1.81) rubocop (~> 1.81)
rubocop-rspec_rails (2.32.0) rubocop-rspec_rails (2.32.0)
@@ -807,8 +816,8 @@ GEM
ffi (~> 1.12) ffi (~> 1.12)
logger logger
rubyzip (2.4.1) rubyzip (2.4.1)
rufus-scheduler (3.8.2) rufus-scheduler (3.9.2)
fugit (~> 1.1, >= 1.1.6) fugit (~> 1.1, >= 1.11.1)
rugged (1.9.0) rugged (1.9.0)
sanitize (7.0.0) sanitize (7.0.0)
crass (~> 1.0.2) crass (~> 1.0.2)
@@ -830,10 +839,9 @@ GEM
logger logger
rack (>= 2.2.4, < 3.3) rack (>= 2.2.4, < 3.3)
redis-client (>= 0.23.0, < 1) redis-client (>= 0.23.0, < 1)
sidekiq-scheduler (5.0.3) sidekiq-scheduler (6.0.1)
rufus-scheduler (~> 3.2) rufus-scheduler (~> 3.2)
sidekiq (>= 6, < 8) sidekiq (>= 7.3, < 9)
tilt (>= 1.4.0)
simplecov (0.22.0) simplecov (0.22.0)
docile (~> 1.1) docile (~> 1.1)
simplecov-html (~> 0.11) simplecov-html (~> 0.11)
@@ -844,7 +852,7 @@ GEM
caxlsx (<= 4.0) caxlsx (<= 4.0)
csv csv
rodf rodf
spring (4.4.0) spring (4.4.2)
spring-commands-rspec (1.0.4) spring-commands-rspec (1.0.4)
spring (>= 0.9.1) spring (>= 0.9.1)
spring-commands-rubocop (0.4.0) spring-commands-rubocop (0.4.0)
@@ -885,14 +893,14 @@ GEM
faraday (~> 2.0) faraday (~> 2.0)
faraday-follow_redirects faraday-follow_redirects
sysexits (1.2.0) sysexits (1.2.0)
taler (0.1.0) taler (0.2.0)
temple (0.10.4) temple (0.10.4)
terminal-table (4.0.0) terminal-table (4.0.0)
unicode-display_width (>= 1.1.1, < 4) unicode-display_width (>= 1.1.1, < 4)
thor (1.4.0) thor (1.5.0)
thread-local (1.1.0) thread-local (1.1.0)
tilt (2.6.1) tilt (2.7.0)
timeout (0.4.4) timeout (0.6.0)
tsort (0.2.0) tsort (0.2.0)
ttfunk (1.8.0) ttfunk (1.8.0)
bigdecimal (~> 3.1) bigdecimal (~> 3.1)
@@ -914,7 +922,7 @@ GEM
unicode-display_width (3.2.0) unicode-display_width (3.2.0)
unicode-emoji (~> 4.1) unicode-emoji (~> 4.1)
unicode-emoji (4.2.0) unicode-emoji (4.2.0)
uniform_notifier (1.17.0) uniform_notifier (1.18.0)
uri (1.1.1) uri (1.1.1)
valid_email2 (5.2.3) valid_email2 (5.2.3)
activemodel (>= 3.2) activemodel (>= 3.2)
@@ -952,7 +960,7 @@ GEM
crack (>= 0.3.2) crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0) hashdiff (>= 0.4.0, < 2.0.0)
webrick (1.9.2) webrick (1.9.2)
websocket-driver (0.7.7) websocket-driver (0.8.0)
base64 base64
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5) websocket-extensions (0.1.5)

View File

@@ -1,5 +0,0 @@
angular.module('Darkswarm').controller "HomeCtrl", ($scope) ->
$scope.brandStoryExpanded = false
$scope.toggleBrandStory = ->
$scope.brandStoryExpanded = !$scope.brandStoryExpanded

View File

@@ -1,17 +1,18 @@
# frozen_string_literal: true # frozen_string_literal: true
class SearchableDropdownComponent < ViewComponent::Base class SearchableDropdownComponent < ViewComponent::Base
REMOVED_SEARCH_PLUGIN = { 'tom-select-options-value': '{ "plugins": [] }' }.freeze
MINIMUM_OPTIONS_FOR_SEARCH_FIELD = 11 # at least 11 options are required for the search field MINIMUM_OPTIONS_FOR_SEARCH_FIELD = 11 # at least 11 options are required for the search field
def initialize( def initialize(
form:,
name:, name:,
options:, options:,
selected_option:, selected_option:,
placeholder_value:, form: nil,
placeholder_value: '',
include_blank: false, include_blank: false,
aria_label: '', aria_label: '',
multiple: false,
remote_url: nil,
other_attrs: {} other_attrs: {}
) )
@f = form @f = form
@@ -21,13 +22,15 @@ class SearchableDropdownComponent < ViewComponent::Base
@placeholder_value = placeholder_value @placeholder_value = placeholder_value
@include_blank = include_blank @include_blank = include_blank
@aria_label = aria_label @aria_label = aria_label
@multiple = multiple
@remote_url = remote_url
@other_attrs = other_attrs @other_attrs = other_attrs
end end
private private
attr_reader :f, :name, :options, :selected_option, :placeholder_value, :include_blank, attr_reader :f, :name, :options, :selected_option, :placeholder_value, :include_blank,
:aria_label, :other_attrs :aria_label, :multiple, :remote_url, :other_attrs
def classes def classes
"fullwidth #{'no-input' if remove_search_plugin?}" "fullwidth #{'no-input' if remove_search_plugin?}"
@@ -36,11 +39,33 @@ class SearchableDropdownComponent < ViewComponent::Base
def data def data
{ {
controller: "tom-select", controller: "tom-select",
'tom-select-placeholder-value': placeholder_value 'tom-select-placeholder-value': placeholder_value,
}.merge(remove_search_plugin? ? REMOVED_SEARCH_PLUGIN : {}) 'tom-select-options-value': tom_select_options_value,
'tom-select-remote-url-value': remote_url,
}
end
def tom_select_options_value
plugins = []
plugins << 'virtual_scroll' if @remote_url.present?
plugins << 'dropdown_input' unless remove_search_plugin?
plugins << 'remove_button' if multiple
{
plugins:,
maxItems: multiple ? nil : 1,
}
end
def uses_form_builder?
f.present?
end end
def remove_search_plugin? def remove_search_plugin?
@remove_search_plugin ||= options.count < MINIMUM_OPTIONS_FOR_SEARCH_FIELD # Remove the search plugin when:
# - the select is multiple (it already includes a search field), or
# - there is no remote URL and the options are below the search threshold
@remove_search_plugin ||= multiple ||
(@remote_url.nil? && options.count < MINIMUM_OPTIONS_FOR_SEARCH_FIELD)
end end
end end

View File

@@ -1 +1,4 @@
= f.select name, options_for_select(options, selected_option), { include_blank: }, class: classes, data:, 'aria-label': aria_label, **other_attrs - if uses_form_builder?
= f.select name, options, { selected: selected_option, include_blank:, multiple: }, class: classes, data:, 'aria-label': aria_label, **other_attrs
- else
= select_tag name, options_for_select(options, selected_option), include_blank:, multiple:, class: classes, data:, 'aria-label': aria_label, **other_attrs

View File

@@ -28,7 +28,7 @@ module Admin
flash[:success] = I18n.t('admin.products_v3.bulk_update.success') flash[:success] = I18n.t('admin.products_v3.bulk_update.success')
redirect_to [:index, redirect_to [:index,
{ page: @page, per_page: @per_page, search_term: @search_term, { page: @page, per_page: @per_page, search_term: @search_term,
producer_id: @producer_id, category_id: @category_id }] producer_id: @producer_id, category_id: @category_id, tags_name_in: @tags }]
elsif product_set.errors.present? elsif product_set.errors.present?
@error_counts = { saved: product_set.saved_count, invalid: product_set.invalid.count } @error_counts = { saved: product_set.saved_count, invalid: product_set.invalid.count }
@@ -120,7 +120,7 @@ module Admin
@search_term = params[:search_term] || params[:_search_term] @search_term = params[:search_term] || params[:_search_term]
@producer_id = params[:producer_id] || params[:_producer_id] @producer_id = params[:producer_id] || params[:_producer_id]
@category_id = params[:category_id] || params[:_category_id] @category_id = params[:category_id] || params[:_category_id]
@tags = params[:tags_name_in] || params[:_tags_name_in] @tags = params[:tags_name_in] || []
end end
def init_pagination_params def init_pagination_params

View File

@@ -4,6 +4,7 @@ module Admin
class ReportsController < Spree::Admin::BaseController class ReportsController < Spree::Admin::BaseController
include ActiveStorage::SetCurrent include ActiveStorage::SetCurrent
include ReportsActions include ReportsActions
include Reports::AjaxSearch
helper ReportsHelper helper ReportsHelper

View File

@@ -0,0 +1,108 @@
# frozen_string_literal: true
module Reports
module AjaxSearch
extend ActiveSupport::Concern
def search_enterprise_fees
report = report_class.new(spree_current_user, params, render: false)
fee_ids = enterprise_fee_ids(report.search.result)
query = EnterpriseFee.where(id: fee_ids)
render json: build_search_response(query)
end
def search_enterprise_fee_owners
report = report_class.new(spree_current_user, params, render: false)
owner_ids = enterprise_fee_owner_ids(report.search.result)
query = Enterprise.where(id: owner_ids)
render json: build_search_response(query)
end
def search_distributors
query = frontend_data.distributors
render json: build_search_response(query)
end
def search_order_cycles
query = frontend_data.order_cycles
render json: build_search_response(query)
end
def search_order_customers
query = frontend_data.order_customers
render json: build_search_response(query)
end
def search_suppliers
query = frontend_data.orders_suppliers
render json: build_search_response(query)
end
private
def build_search_response(query)
page = (params[:page] || 1).to_i
per_page = 30
filtered_query = apply_search_filter(query)
total_count = filtered_query.size
items = paginated_items(filtered_query, page, per_page)
results = format_results(items)
{ results: results, pagination: { more: (page * per_page) < total_count } }
end
def apply_search_filter(query)
search_term = params[:q]
return query if search_term.blank?
escaped_search_term = ActiveRecord::Base.sanitize_sql_like(search_term)
pattern = "%#{escaped_search_term}%"
# Handle different model types
if query.model == OrderCycle
query.where("order_cycles.name ILIKE ?", pattern)
elsif query.model == Customer
query.where("customers.email ILIKE ?", pattern)
else
query.where("name ILIKE ?", pattern)
end
end
def paginated_items(query, page, per_page)
if query.model == Customer
query.order(:email).offset((page - 1) * per_page).limit(per_page).pluck(:email, :id)
elsif query.model == OrderCycle
query.order('order_cycles.orders_close_at DESC')
.offset((page - 1) * per_page)
.limit(per_page).pluck(
:name, :id
)
else
query.order(:name).offset((page - 1) * per_page).limit(per_page).pluck(:name, :id)
end
end
def format_results(items)
items.map { |label, value| { value:, label: } }
end
def frontend_data
@frontend_data ||= Reporting::FrontendData.new(spree_current_user)
end
def enterprise_fee_owner_ids(orders)
EnterpriseFee.where(id: enterprise_fee_ids(orders)).select(:enterprise_id)
end
def enterprise_fee_ids(orders)
Spree::Adjustment.enterprise_fee.where(order_id: orders.select(:id)).select(:originator_id)
end
end
end

View File

@@ -138,7 +138,7 @@ module Spree
providers.delete("Spree::Gateway::StripeSCA") unless show_stripe? providers.delete("Spree::Gateway::StripeSCA") unless show_stripe?
providers.map(&:constantize) providers
end end
# Show Stripe as an option if enabled, or if the # Show Stripe as an option if enabled, or if the

View File

@@ -95,8 +95,7 @@ module Spree
private private
def load_payment_source def load_payment_source
if @payment.payment_method.is_a?(Spree::Gateway) && if @payment.payment_method.is_a?(Gateway::StripeSCA) &&
@payment.payment_method.payment_profiles_supported? &&
params[:card].present? && params[:card].present? &&
(params[:card] != 'new') (params[:card] != 'new')
@payment.source = CreditCard.find_by(id: params[:card]) @payment.source = CreditCard.find_by(id: params[:card])

View File

@@ -139,7 +139,7 @@ module CheckoutHelper
def stripe_card_options(cards) def stripe_card_options(cards)
cards.map do |cc| cards.map do |cc|
[ [
"#{cc.brand} #{cc.last_digits} #{I18n.t(:card_expiry_abbreviation)}:" \ "#{cc.cc_type} #{cc.last_digits} #{I18n.t(:card_expiry_abbreviation)}:" \
"#{cc.month.to_s.rjust(2, '0')}/#{cc.year}", cc.id "#{cc.month.to_s.rjust(2, '0')}/#{cc.year}", cc.id
] ]
end end

View File

@@ -34,29 +34,8 @@ module ReportsHelper
end end
end end
def fee_name_options(orders)
EnterpriseFee.where(id: enterprise_fee_ids(orders))
.pluck(:name, :id)
end
def fee_owner_options(orders)
Enterprise.where(id: enterprise_fee_owner_ids(orders))
.pluck(:name, :id)
end
delegate :currency_symbol, to: :'Spree::Money' delegate :currency_symbol, to: :'Spree::Money'
def enterprise_fee_owner_ids(orders)
EnterpriseFee.where(id: enterprise_fee_ids(orders))
.pluck(:enterprise_id)
end
def enterprise_fee_ids(orders)
Spree::Adjustment.enterprise_fee
.where(order_id: orders.map(&:id))
.pluck(:originator_id)
end
def datepicker_time(datetime) def datepicker_time(datetime)
datetime = Time.zone.parse(datetime) if datetime.is_a? String datetime = Time.zone.parse(datetime) if datetime.is_a? String
datetime.strftime('%Y-%m-%d %H:%M') datetime.strftime('%Y-%m-%d %H:%M')

View File

@@ -0,0 +1,18 @@
# frozen_string_literal: true
module Spree
module Admin
module PaymentMethodsHelper
def payment_method_type_name(class_name)
scope = "spree.admin.payment_methods.providers"
key = class_name.demodulize.downcase
I18n.t(key, scope:)
end
def payment_method_type_options(providers)
providers.map { |p| [payment_method_type_name(p), p] }
end
end
end
end

View File

@@ -6,11 +6,10 @@ class PaymentMailer < ApplicationMailer
def authorize_payment(payment) def authorize_payment(payment)
@payment = payment @payment = payment
@order = @payment.order @order = @payment.order
subject = I18n.t('spree.payment_mailer.authorize_payment.subject', @hide_ofn_navigation = @payment.order.distributor.hide_ofn_navigation
distributor: @order.distributor.name)
I18n.with_locale valid_locale(@order.user) do I18n.with_locale valid_locale(@order.user) do
mail(to: @order.email, mail(to: @order.email,
subject:, subject: default_i18n_subject(distributor: @order.distributor.name),
reply_to: @order.distributor.contact.email) reply_to: @order.distributor.contact.email)
end end
end end
@@ -18,11 +17,20 @@ class PaymentMailer < ApplicationMailer
def authorization_required(payment) def authorization_required(payment)
@order = payment.order @order = payment.order
shop_owner = @order.distributor.owner shop_owner = @order.distributor.owner
subject = I18n.t('spree.payment_mailer.authorization_required.subject',
order: @order)
I18n.with_locale valid_locale(shop_owner) do I18n.with_locale valid_locale(shop_owner) do
mail(to: shop_owner.email, mail(to: shop_owner.email, reply_to: @order.email)
subject:, end
end
def refund_available(payment, taler_order_status_url)
@order = payment.order
@shop = @order.distributor.name
@amount = payment.display_amount
@taler_order_status_url = taler_order_status_url
I18n.with_locale valid_locale(@order.user) do
mail(to: @order.email,
subject: default_i18n_subject(shop: @shop),
reply_to: @order.email) reply_to: @order.email)
end end
end end

View File

@@ -11,6 +11,7 @@ module Spree
def cancel_email(order_or_order_id, resend = false) def cancel_email(order_or_order_id, resend = false)
@order = find_order(order_or_order_id) @order = find_order(order_or_order_id)
@hide_ofn_navigation = @order.distributor.hide_ofn_navigation
I18n.with_locale valid_locale(@order.user) do I18n.with_locale valid_locale(@order.user) do
mail(to: @order.email, mail(to: @order.email,
subject: mail_subject(t('spree.order_mailer.cancel_email.subject'), resend), subject: mail_subject(t('spree.order_mailer.cancel_email.subject'), resend),
@@ -51,6 +52,7 @@ module Spree
def invoice_email(order_or_order_id, options = {}) def invoice_email(order_or_order_id, options = {})
@order = find_order(order_or_order_id) @order = find_order(order_or_order_id)
@hide_ofn_navigation = @order.distributor.hide_ofn_navigation
current_user = if options[:current_user_id].present? current_user = if options[:current_user_id].present?
find_user(options[:current_user_id]) find_user(options[:current_user_id])
end end

View File

@@ -4,6 +4,7 @@ module Spree
class ShipmentMailer < ApplicationMailer class ShipmentMailer < ApplicationMailer
def shipped_email(shipment, delivery:) def shipped_email(shipment, delivery:)
@shipment = shipment.respond_to?(:id) ? shipment : Spree::Shipment.find(shipment) @shipment = shipment.respond_to?(:id) ? shipment : Spree::Shipment.find(shipment)
@hide_ofn_navigation = @shipment.order.distributor.hide_ofn_navigation
@delivery = delivery @delivery = delivery
@order = @shipment.order @order = @shipment.order
subject = base_subject subject = base_subject

View File

@@ -19,6 +19,7 @@ class SubscriptionMailer < ApplicationMailer
@type = 'empty' @type = 'empty'
@changes = changes @changes = changes
@order = order @order = order
@hide_ofn_navigation = @order.distributor.hide_ofn_navigation
send_mail(order) send_mail(order)
end end
@@ -26,11 +27,13 @@ class SubscriptionMailer < ApplicationMailer
@type = 'placement' @type = 'placement'
@changes = changes @changes = changes
@order = order @order = order
@hide_ofn_navigation = @order.distributor.hide_ofn_navigation
send_mail(order) send_mail(order)
end end
def failed_payment_email(order) def failed_payment_email(order)
@order = order @order = order
@hide_ofn_navigation = @order.distributor.hide_ofn_navigation
send_mail(order) send_mail(order)
end end

View File

@@ -4,7 +4,7 @@ class Invoice < ApplicationRecord
self.belongs_to_required_by_default = false self.belongs_to_required_by_default = false
belongs_to :order, class_name: 'Spree::Order' belongs_to :order, class_name: 'Spree::Order'
serialize :data, Hash, coder: YAML serialize :data, type: Hash, coder: YAML
before_validation :serialize_order before_validation :serialize_order
after_create :cancel_previous_invoices after_create :cancel_previous_invoices
default_scope { order(created_at: :desc) } default_scope { order(created_at: :desc) }

View File

@@ -76,6 +76,7 @@ class ProxyOrder < ApplicationRecord
def cart? def cart?
order&.state == 'complete' && order&.state == 'complete' &&
order_cycle.orders_close_at.present? &&
order_cycle.orders_close_at > Time.zone.now order_cycle.orders_close_at > Time.zone.now
end end

View File

@@ -4,5 +4,5 @@ class ReportRenderingOptions < ApplicationRecord
self.belongs_to_required_by_default = false self.belongs_to_required_by_default = false
belongs_to :user, class_name: "Spree::User" belongs_to :user, class_name: "Spree::User"
serialize :options, Hash, coder: YAML serialize :options, type: Hash, coder: YAML
end end

View File

@@ -6,6 +6,11 @@ module Spree
class Ability class Ability
include CanCan::Ability include CanCan::Ability
REPORTS_SEARCH_ACTIONS = [
:search_enterprise_fees, :search_enterprise_fee_owners, :search_distributors,
:search_suppliers, :search_order_cycles, :search_order_customers
].freeze
def initialize(user) def initialize(user)
clear_aliased_actions clear_aliased_actions
@@ -260,7 +265,8 @@ module Spree
can [:admin, :index, :import], ::Admin::DfcProductImportsController can [:admin, :index, :import], ::Admin::DfcProductImportsController
# Reports page # Reports page
can [:admin, :index, :show, :create], ::Admin::ReportsController can [:admin, :index, :show, :create, *REPORTS_SEARCH_ACTIONS],
::Admin::ReportsController
can [:admin, :show, :create, :customers, :orders_and_distributors, :group_buys, :payments, can [:admin, :show, :create, :customers, :orders_and_distributors, :group_buys, :payments,
:orders_and_fulfillment, :products_and_inventory, :order_cycle_management, :orders_and_fulfillment, :products_and_inventory, :order_cycle_management,
:packing, :enterprise_fee_summary, :bulk_coop, :suppliers], :report :packing, :enterprise_fee_summary, :bulk_coop, :suppliers], :report
@@ -392,7 +398,7 @@ module Spree
end end
# Reports page # Reports page
can [:admin, :index, :show, :create], ::Admin::ReportsController can [:admin, :index, :show, :create, *REPORTS_SEARCH_ACTIONS], ::Admin::ReportsController
can [:admin, :customers, :group_buys, :sales_tax, :payments, can [:admin, :customers, :group_buys, :sales_tax, :payments,
:orders_and_distributors, :orders_and_fulfillment, :products_and_inventory, :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory,
:order_cycle_management, :xero_invoices, :enterprise_fee_summary, :bulk_coop], :report :order_cycle_management, :xero_invoices, :enterprise_fee_summary, :bulk_coop], :report

View File

@@ -25,9 +25,6 @@ module Spree
scope :with_payment_profile, -> { where.not(gateway_customer_profile_id: nil) } scope :with_payment_profile, -> { where.not(gateway_customer_profile_id: nil) }
# needed for some of the ActiveMerchant gateways (eg. SagePay)
alias_attribute :brand, :cc_type
def expiry=(expiry) def expiry=(expiry)
self[:month], self[:year] = expiry.split(" / ") self[:month], self[:year] = expiry.split(" / ")
self[:year] = "20#{self[:year]}" self[:year] = "20#{self[:year]}"

View File

@@ -5,7 +5,7 @@ module Spree
acts_as_taggable acts_as_taggable
include PaymentMethodDistributors include PaymentMethodDistributors
delegate :authorize, :purchase, :capture, :void, :credit, to: :provider delegate :authorize, :purchase, :capture, :void, :credit, :refund, to: :provider
validates :name, :type, presence: true validates :name, :type, presence: true
@@ -35,6 +35,10 @@ module Spree
end end
def method_missing(method, *) def method_missing(method, *)
message = "Deprecated delegation of Gateway##{method}"
Alert.raise(message)
raise message if Rails.env.local?
if @provider.nil? || !@provider.respond_to?(method) if @provider.nil? || !@provider.respond_to?(method)
super super
else else
@@ -42,19 +46,15 @@ module Spree
end end
end end
def payment_profiles_supported?
false
end
def method_type def method_type
'gateway' 'gateway'
end end
def supports?(source) def supports?(source)
return true unless provider_class.respond_to? :supports? return true unless provider_class.respond_to? :supports?
return false unless source.brand return false unless source.cc_type
provider_class.supports?(source.brand) provider_class.supports?(source.cc_type)
end end
end end
end end

View File

@@ -35,10 +35,6 @@ module Spree
ActiveMerchant::Billing::StripePaymentIntentsGateway ActiveMerchant::Billing::StripePaymentIntentsGateway
end end
def payment_profiles_supported?
true
end
def stripe_account_id def stripe_account_id
StripeAccount.find_by(enterprise_id: preferred_enterprise_id)&.stripe_user_id StripeAccount.find_by(enterprise_id: preferred_enterprise_id)&.stripe_user_id
end end
@@ -84,7 +80,7 @@ module Spree
end end
# NOTE: this method is required by Spree::Payment::Processing # NOTE: this method is required by Spree::Payment::Processing
def void(payment_intent_id, _creditcard, gateway_options) def void(payment_intent_id, gateway_options)
payment_intent_response = Stripe::PaymentIntent.retrieve( payment_intent_response = Stripe::PaymentIntent.retrieve(
payment_intent_id, stripe_account: stripe_account_id payment_intent_id, stripe_account: stripe_account_id
) )
@@ -101,7 +97,13 @@ module Spree
end end
# NOTE: this method is required by Spree::Payment::Processing # NOTE: this method is required by Spree::Payment::Processing
def credit(money, _creditcard, payment_intent_id, gateway_options) def credit(money, payment_intent_id, gateway_options)
gateway_options[:stripe_account] = stripe_account_id
provider.refund(money, payment_intent_id, gateway_options)
end
# NOTE: this method is required by Spree::Payment::Processing
def refund(money, payment_intent_id, gateway_options)
gateway_options[:stripe_account] = stripe_account_id gateway_options[:stripe_account] = stripe_account_id
provider.refund(money, payment_intent_id, gateway_options) provider.refund(money, payment_intent_id, gateway_options)
end end

View File

@@ -34,7 +34,7 @@ module Spree
# invalidate previously entered payments # invalidate previously entered payments
after_create :invalidate_old_payments after_create :invalidate_old_payments
after_save :create_payment_profile, if: :profiles_supported? after_save :create_payment_profile
# update the order totals, etc. # update the order totals, etc.
after_save :ensure_correct_adjustment, :update_order after_save :ensure_correct_adjustment, :update_order
@@ -217,18 +217,13 @@ module Spree
errors.blank? errors.blank?
end end
def profiles_supported?
payment_method.respond_to?(:payment_profiles_supported?) &&
payment_method.payment_profiles_supported?
end
def create_payment_profile def create_payment_profile
return unless source.is_a?(CreditCard) return unless source.is_a?(CreditCard)
return unless source.try(:save_requested_by_customer?) return unless source.try(:save_requested_by_customer?)
return unless source.number || source.gateway_payment_profile_id return unless source.number || source.gateway_payment_profile_id
return unless source.gateway_customer_profile_id.nil? return unless source.gateway_customer_profile_id.nil?
payment_method.create_profile(self) payment_method.try(:create_profile, self)
rescue ActiveMerchant::ConnectionError => e rescue ActiveMerchant::ConnectionError => e
gateway_error e gateway_error e
end end

View File

@@ -58,16 +58,7 @@ module Spree
protect_from_connection_error do protect_from_connection_error do
check_environment check_environment
response = if payment_method.payment_profiles_supported? response = payment_method.void(response_code, gateway_options)
# Gateways supporting payment profiles will need access to credit
# card object because this stores the payment profile information
# so supply the authorization itself as well as the credit card,
# rather than just the authorization code
payment_method.void(response_code, source, gateway_options)
else
# Standard ActiveMerchant void usage
payment_method.void(response_code, gateway_options)
end
record_response(response) record_response(response)
@@ -86,20 +77,11 @@ module Spree
credit_amount = calculate_refund_amount(credit_amount) credit_amount = calculate_refund_amount(credit_amount)
response = if payment_method.payment_profiles_supported? response = payment_method.credit(
payment_method.credit( (credit_amount * 100).round,
(credit_amount * 100).round, response_code,
source, gateway_options
response_code, )
gateway_options
)
else
payment_method.credit(
(credit_amount * 100).round,
response_code,
gateway_options
)
end
record_response(response) record_response(response)
@@ -125,20 +107,11 @@ module Spree
refund_amount = calculate_refund_amount(refund_amount) refund_amount = calculate_refund_amount(refund_amount)
response = if payment_method.payment_profiles_supported? response = payment_method.refund(
payment_method.refund( (refund_amount * 100).round,
(refund_amount * 100).round, response_code,
source, gateway_options
response_code, )
gateway_options
)
else
payment_method.refund(
(refund_amount * 100).round,
response_code,
gateway_options
)
end
record_response(response) record_response(response)

View File

@@ -93,10 +93,6 @@ module Spree
unscoped { find(*) } unscoped { find(*) }
end end
def payment_profiles_supported?
false
end
def source_required? def source_required?
true true
end end
@@ -113,11 +109,6 @@ module Spree
distributors.include?(distributor) distributors.include?(distributor)
end end
def self.clean_name
scope = "spree.admin.payment_methods.providers"
I18n.t(name.demodulize.downcase, scope:)
end
private private
def distributor_validation def distributor_validation

View File

@@ -21,6 +21,14 @@ module Spree
preference :backend_url, :string preference :backend_url, :string
preference :api_key, :password preference :api_key, :password
def actions
%w{void}
end
def can_void?(payment)
payment.state == "completed"
end
# Name of the view to display during checkout # Name of the view to display during checkout
def method_type def method_type
"check" # empty view "check" # empty view
@@ -38,10 +46,9 @@ module Spree
payment.source ||= self payment.source ||= self
payment.response_code ||= create_taler_order(payment) payment.response_code ||= create_taler_order(payment)
payment.redirect_auth_url ||= fetch_order_url(payment)
payment.save! if payment.changed? payment.save! if payment.changed?
payment.redirect_auth_url taler_order.status_url
end end
# Main method called by Spree::Payment::Processing during checkout # Main method called by Spree::Payment::Processing during checkout
@@ -53,14 +60,33 @@ module Spree
return unless payment.response_code return unless payment.response_code
taler_order = client.fetch_order(payment.response_code) taler_order = taler_order(id: payment.response_code)
status = taler_order["order_status"] status = taler_order.fetch("order_status")
success = (status == "paid") success = (status == "paid")
message = I18n.t(status, default: status, scope: "taler.order_status") message = I18n.t(status, default: status, scope: "taler.order_status")
ActiveMerchant::Billing::Response.new(success, message) ActiveMerchant::Billing::Response.new(success, message)
end end
def void(response_code, gateway_options)
payment = gateway_options[:payment]
taler_order = taler_order(id: response_code)
status = taler_order.fetch("order_status")
if status == "claimed"
return ActiveMerchant::Billing::Response.new(true, "Already expired")
end
raise "Unsupported action" if status != "paid"
amount = taler_order.fetch("contract_terms")["amount"]
taler_order.refund(refund: amount, reason: "void")
PaymentMailer.refund_available(payment, taler_order.status_url).deliver_later
ActiveMerchant::Billing::Response.new(true, "Refund initiated")
end
private private
def load_payment(order) def load_payment(order)
@@ -72,22 +98,20 @@ module Spree
# current demo backend only working with the KUDOS currency. # current demo backend only working with the KUDOS currency.
taler_amount = "KUDOS:#{payment.amount}" taler_amount = "KUDOS:#{payment.amount}"
urls = Rails.application.routes.url_helpers urls = Rails.application.routes.url_helpers
new_order = client.create_order( fulfillment_url = urls.payment_gateways_confirm_taler_url(payment_id: payment.id)
taler_amount, taler_order.create(
I18n.t("payment_method_taler.order_summary"), amount: taler_amount,
urls.payment_gateways_confirm_taler_url(payment_id: payment.id), summary: I18n.t("payment_method_taler.order_summary"),
fulfillment_url:,
) )
new_order["order_id"]
end end
def fetch_order_url(payment) def taler_order(id: nil)
order = client.fetch_order(payment.response_code) @taler_order ||= ::Taler::Order.new(
order["order_status_url"] backend_url: preferred_backend_url,
end password: preferred_api_key,
id:,
def client )
@client ||= ::Taler::Client.new(preferred_backend_url, preferred_api_key)
end end
end end
end end

View File

@@ -251,7 +251,7 @@ module Spree
transaction do transaction do
ExchangeVariant. ExchangeVariant.
where(exchange_variants: { variant_id: variants.with_deleted. where(exchange_variants: { variant_id: variants.with_deleted.
select(:id) }).destroy_all select(:id) }).destroy_all
yield yield
end end

View File

@@ -35,8 +35,8 @@ module Spree
taxons taxons
.pluck('spree_taxons.id, enterprises.id AS enterprise_id') .pluck('spree_taxons.id, enterprises.id AS enterprise_id')
.each_with_object({}) do |(taxon_id, enterprise_id), collection| .each_with_object({}) do |(taxon_id, enterprise_id), collection|
collection[enterprise_id.to_i] ||= Set.new collection[enterprise_id.to_i] ||= Set.new
collection[enterprise_id.to_i] << taxon_id collection[enterprise_id.to_i] << taxon_id
end end
end end

View File

@@ -167,8 +167,8 @@ module Spree
# In Rails 3, merging two scopes on the same column will consider only the last scope. # In Rails 3, merging two scopes on the same column will consider only the last scope.
def self.in_distributor(distributor) def self.in_distributor(distributor)
where(id: ExchangeVariant.select(:variant_id). where(id: ExchangeVariant.select(:variant_id).
joins(:exchange). joins(:exchange).
where('exchanges.incoming = ? AND exchanges.receiver_id = ?', false, distributor)) where('exchanges.incoming = ? AND exchanges.receiver_id = ?', false, distributor))
end end
def self.indexed def self.indexed
@@ -179,11 +179,11 @@ module Spree
# "where(id:" is necessary so that the returned relation has no includes # "where(id:" is necessary so that the returned relation has no includes
# The relation without includes will not be readonly and allow updates on it # The relation without includes will not be readonly and allow updates on it
where(spree_variants: { id: joins(:prices). where(spree_variants: { id: joins(:prices).
where(deleted_at: nil). where(deleted_at: nil).
where('spree_prices.currency' => where('spree_prices.currency' =>
currency || CurrentConfig.get(:currency)). currency || CurrentConfig.get(:currency)).
where.not(spree_prices: { amount: nil }). where.not(spree_prices: { amount: nil }).
select("spree_variants.id") }) select("spree_variants.id") })
end end
def self.linked_to(semantic_id) def self.linked_to(semantic_id)

View File

@@ -60,8 +60,8 @@ class ProductScopeQuery
def product_query_includes def product_query_includes
[ [
image: { attachment_attachment: :blob }, { image: { attachment_attachment: :blob },
variants: [:default_price, :stock_items, :variant_overrides] variants: [:default_price, :stock_items, :variant_overrides] }
] ]
end end

View File

@@ -42,10 +42,10 @@ class DfcCatalogImporter
.includes(:semantic_links).references(:semantic_links) .includes(:semantic_links).references(:semantic_links)
.where.not(semantic_links: { semantic_id: present_ids }) .where.not(semantic_links: { semantic_id: present_ids })
.select do |variant| .select do |variant|
# Variants that were in the same catalog before: # Variants that were in the same catalog before:
variant.semantic_links.map(&:semantic_id).any? do |semantic_id| variant.semantic_links.map(&:semantic_id).any? do |semantic_id|
FdcUrlBuilder.new(semantic_id).catalog_url == catalog_url FdcUrlBuilder.new(semantic_id).catalog_url == catalog_url
end end
end end
end end
end end

View File

@@ -51,8 +51,8 @@ class LineItemSyncer
def destroy_obsolete_items(order) def destroy_obsolete_items(order)
order.line_items. order.line_items.
where(variant_id: subscription_line_items. where(variant_id: subscription_line_items.
select(&:marked_for_destruction?). select(&:marked_for_destruction?).
map(&:variant_id)). map(&:variant_id)).
destroy_all destroy_all
end end

View File

@@ -130,12 +130,11 @@ module Orders
def order_cycle_fees def order_cycle_fees
return @order_cycle_fees if defined? @order_cycle_fees return @order_cycle_fees if defined? @order_cycle_fees
return [] unless order_cycle && distributor
@order_cycle_fees = begin @order_cycle_fees = begin
fees = [] fees = []
return fees unless order_cycle && distributor
order_cycle.exchanges.supplying_to(distributor).each do |exchange| order_cycle.exchanges.supplying_to(distributor).each do |exchange|
exchange.enterprise_fees.per_item.each do |enterprise_fee| exchange.enterprise_fees.per_item.each do |enterprise_fee|
fee_value = FeeValue.new(fee: enterprise_fee, role: exchange.role) fee_value = FeeValue.new(fee: enterprise_fee, role: exchange.role)

View File

@@ -14,12 +14,12 @@ module PermittedAttributes
def self.attributes def self.attributes
basic_permitted_attributes + [ basic_permitted_attributes + [
group_ids: [], user_ids: [], { group_ids: [], user_ids: [],
shipping_method_ids: [], payment_method_ids: [], shipping_method_ids: [], payment_method_ids: [],
address_attributes: PermittedAttributes::Address.attributes, address_attributes: PermittedAttributes::Address.attributes,
business_address_attributes: PermittedAttributes::BusinessAddress.attributes, business_address_attributes: PermittedAttributes::BusinessAddress.attributes,
producer_properties_attributes: [:id, :property_name, :value, :_destroy], producer_properties_attributes: [:id, :property_name, :value, :_destroy],
custom_tab_attributes: PermittedAttributes::CustomTab.attributes, custom_tab_attributes: PermittedAttributes::CustomTab.attributes },
] ]
end end

View File

@@ -25,8 +25,8 @@ module PermittedAttributes
private private
def attributes def attributes
self.class.basic_attributes + [incoming_exchanges: permitted_exchange_attributes, self.class.basic_attributes + [{ incoming_exchanges: permitted_exchange_attributes,
outgoing_exchanges: permitted_exchange_attributes] outgoing_exchanges: permitted_exchange_attributes }]
end end
def permitted_exchange_attributes def permitted_exchange_attributes

View File

@@ -26,11 +26,11 @@ module PermittedAttributes
def other_permitted_attributes def other_permitted_attributes
[ [
subscription_line_items_attributes: [ { subscription_line_items_attributes: [
:id, :quantity, :variant_id, :price_estimate, :_destroy :id, :quantity, :variant_id, :price_estimate, :_destroy
], ],
bill_address_attributes: PermittedAttributes::Address.attributes, bill_address_attributes: PermittedAttributes::Address.attributes,
ship_address_attributes: PermittedAttributes::Address.attributes ship_address_attributes: PermittedAttributes::Address.attributes }
] ]
end end
end end

View File

@@ -13,6 +13,8 @@
= hidden_field_tag :search_term, @search_term = hidden_field_tag :search_term, @search_term
= hidden_field_tag :producer_id, @producer_id = hidden_field_tag :producer_id, @producer_id
= hidden_field_tag :category_id, @category_id = hidden_field_tag :category_id, @category_id
- @tags.each do |tag|
= hidden_field_tag 'tags_name_in[]', tag
%table.products{ 'data-column-preferences-target': "table", class: (hide_producer_column?(producer_options) ? 'hide-producer' : '') } %table.products{ 'data-column-preferences-target': "table", class: (hide_producer_column?(producer_options) ? 'hide-producer' : '') }
%colgroup %colgroup

View File

@@ -1,23 +1,50 @@
- search_url_query = {report_type: :enterprise_fee_summary, report_subtype: :enterprise_fees_with_tax_report_by_order}
.row .row
.alpha.two.columns= label_tag nil, t(:report_hubs) .alpha.two.columns= label_tag nil, t(:report_hubs)
.omega.fourteen.columns= f.collection_select(:distributor_id_in, @data.distributors, :id, :name, {}, {class: "select2 fullwidth", multiple: true}) .omega.fourteen.columns
= render(SearchableDropdownComponent.new(form: f,
name: :distributor_id_in,
options: [],
selected_option: params.dig(:q, :distributor_id_in),
multiple: true,
remote_url: admin_reports_search_distributors_url))
.row .row
.alpha.two.columns= label_tag nil, t(:report_customers_cycle) .alpha.two.columns= label_tag nil, t(:report_customers_cycle)
.omega.fourteen.columns .omega.fourteen.columns
= f.select(:order_cycle_id_in, report_order_cycle_options(@data.order_cycles), {selected: params.dig(:q, :order_cycle_id_in)}, {class: "select2 fullwidth", multiple: true}) = render(SearchableDropdownComponent.new(form: f,
name: :order_cycle_id_in,
options: [],
selected_option: params.dig(:q, :order_cycle_id_in),
multiple: true,
remote_url: admin_reports_search_order_cycles_url))
.row .row
.alpha.two.columns= label_tag nil, t(:fee_name) .alpha.two.columns= label_tag nil, t(:fee_name)
.omega.fourteen.columns .omega.fourteen.columns
= f.select(:enterprise_fee_id_in, fee_name_options(@report.search.result), {selected: params.dig(:q, :enterprise_fee_id_in)}, {class: "select2 fullwidth", multiple: true}) = render(SearchableDropdownComponent.new(form: f,
name: :enterprise_fee_id_in,
options: [],
selected_option: params.dig(:q, :enterprise_fee_id_in),
multiple: true,
remote_url: admin_reports_search_enterprise_fees_url(search_url_query)))
.row .row
.alpha.two.columns= label_tag nil, t(:fee_owner) .alpha.two.columns= label_tag nil, t(:fee_owner)
.omega.fourteen.columns .omega.fourteen.columns
= f.select(:enterprise_fee_owner_id_in, fee_owner_options(@report.search.result), {selected: params.dig(:q, :enterprise_fee_owner_id_in)}, {class: "select2 fullwidth", multiple: true}) = render(SearchableDropdownComponent.new(form: f,
name: :enterprise_fee_owner_id_in,
options: [],
selected_option: params.dig(:q, :enterprise_fee_owner_id_in),
multiple: true,
remote_url: admin_reports_search_enterprise_fee_owners_url(search_url_query)))
.row .row
.alpha.two.columns= label_tag nil, t(:report_customers) .alpha.two.columns= label_tag nil, t(:report_customers)
.omega.fourteen.columns .omega.fourteen.columns
= f.select(:customer_id_in, customer_email_options(@data.order_customers), {selected: params.dig(:q, :customer_id_in)}, {class: "select2 fullwidth", multiple: true}) = render(SearchableDropdownComponent.new(form: f,
name: :customer_id_in,
options: [],
selected_option: params.dig(:q, :customer_id_in),
multiple: true,
remote_url: admin_reports_search_order_customers_url))

View File

@@ -1,27 +1,57 @@
- search_url_query = {report_type: :enterprise_fee_summary, report_subtype: :enterprise_fees_with_tax_report_by_producer}
.row .row
.alpha.two.columns= label_tag nil, t(:report_hubs) .alpha.two.columns= label_tag nil, t(:report_hubs)
.omega.fourteen.columns= f.collection_select(:distributor_id_in, @data.distributors, :id, :name, {}, {class: "select2 fullwidth", multiple: true}) .omega.fourteen.columns
= render(SearchableDropdownComponent.new(form: f,
name: :distributor_id_in,
options: [],
selected_option: params.dig(:q, :distributor_id_in),
multiple: true,
remote_url: admin_reports_search_distributors_url))
.row .row
.alpha.two.columns= label_tag nil, t(:report_producers) .alpha.two.columns= label_tag nil, t(:report_producers)
.omega.fourteen.columns= select_tag(:supplier_id_in, options_from_collection_for_select(@data.orders_suppliers, :id, :name, params[:supplier_id_in]), {class: "select2 fullwidth", multiple: true}) .omega.fourteen.columns
= render(SearchableDropdownComponent.new(name: :supplier_id_in,
options: [],
selected_option: params.dig(:supplier_id_in),
multiple: true,
remote_url: admin_reports_search_suppliers_url))
.row .row
.alpha.two.columns= label_tag nil, t(:report_customers_cycle) .alpha.two.columns= label_tag nil, t(:report_customers_cycle)
.omega.fourteen.columns .omega.fourteen.columns
= f.select(:order_cycle_id_in, report_order_cycle_options(@data.order_cycles), {selected: params.dig(:q, :order_cycle_id_in)}, {class: "select2 fullwidth", multiple: true}) = render(SearchableDropdownComponent.new(form: f,
name: :order_cycle_id_in,
options: [],
selected_option: params.dig(:q, :order_cycle_id_in),
multiple: true,
remote_url: admin_reports_search_order_cycles_url))
.row .row
.alpha.two.columns= label_tag nil, t(:fee_name) .alpha.two.columns= label_tag nil, t(:fee_name)
.omega.fourteen.columns .omega.fourteen.columns
= f.select(:enterprise_fee_id_in, fee_name_options(@report.search.result), {selected: params.dig(:q, :enterprise_fee_id_in)}, {class: "select2 fullwidth", multiple: true}) = render(SearchableDropdownComponent.new(form: f,
name: :enterprise_fee_id_in,
options: [],
selected_option: params.dig(:q, :enterprise_fee_id_in),
multiple: true,
remote_url: admin_reports_search_enterprise_fees_url(search_url_query)))
.row .row
.alpha.two.columns= label_tag nil, t(:fee_owner) .alpha.two.columns= label_tag nil, t(:fee_owner)
.omega.fourteen.columns .omega.fourteen.columns
= f.select(:enterprise_fee_owner_id_in, fee_owner_options(@report.search.result), {selected: params.dig(:q, :enterprise_fee_owner_id_in)}, {class: "select2 fullwidth", multiple: true}) = render(SearchableDropdownComponent.new(form: f,
name: :enterprise_fee_owner_id_in,
options: [],
selected_option: params.dig(:q, :enterprise_fee_owner_id_in),
multiple: true,
remote_url: admin_reports_search_enterprise_fee_owners_url(search_url_query)))
.row .row
.alpha.two.columns= label_tag nil, t(:report_customers) .alpha.two.columns= label_tag nil, t(:report_customers)
.omega.fourteen.columns .omega.fourteen.columns
= f.select(:customer_id_in, customer_email_options(@data.order_customers), {selected: params.dig(:q, :customer_id_in)}, {class: "select2 fullwidth", multiple: true}) = render(SearchableDropdownComponent.new(form: f,
name: :customer_id_in,
options: [],
selected_option: params.dig(:q, :customer_id_in),
multiple: true,
remote_url: admin_reports_search_order_customers_url))

View File

@@ -6,21 +6,21 @@
%p %p
= t :brandstory_intro = t :brandstory_intro
#brand-story-text.hide-show.slideable %details#brand-story-text
%p %summary
= t :brandstory_part1 %i.ofn-i_005-caret-down
%p %i.ofn-i_006-caret-up
= t :brandstory_part2 .brand-story-content
%p %p
= t :brandstory_part3 = t :brandstory_part1
%p %p
= t :brandstory_part4 = t :brandstory_part2
%p %p
%strong = t :brandstory_part3
= t :brandstory_part5_strong %p
%p = t :brandstory_part4
= t :brandstory_part6 %p
%strong
%a.text-vbig{"slide-toggle" => "#brand-story-text", "ng-click" => "toggleBrandStory()"} = t :brandstory_part5_strong
%i.ofn-i_005-caret-down{"ng-hide" => "brandStoryExpanded"} %p
%i.ofn-i_006-caret-up{ "ng-show" => "brandStoryExpanded"} = t :brandstory_part6

View File

@@ -5,7 +5,7 @@
- content_for :page_alert do - content_for :page_alert do
= render "shared/menu/alert" = render "shared/menu/alert"
%div{"ng-controller" => "HomeCtrl"} %div
= render "home/tagline" = render "home/tagline"
#panes #panes

View File

@@ -1,2 +1,2 @@
= t('spree.payment_mailer.authorization_required.message', order_number: @order.number) = t(".message", order_number: @order.number)
= link_to spree.edit_admin_order_url(@order), spree.edit_admin_order_url(@order) = link_to spree.edit_admin_order_url(@order), spree.edit_admin_order_url(@order)

View File

@@ -1,2 +1,2 @@
= t('spree.payment_mailer.authorize_payment.instructions', distributor: @payment.order.distributor.name, amount: @payment.display_amount) = t(".instructions", distributor: @payment.order.distributor.name, amount: @payment.display_amount)
= link_to main_app.authorize_payment_url(@payment), main_app.authorize_payment_url(@payment) = link_to main_app.authorize_payment_url(@payment), main_app.authorize_payment_url(@payment)

View File

@@ -0,0 +1,2 @@
%p= t(".message", shop: @shop, amount: @amount)
%p= link_to @taler_order_status_url, @taler_order_status_url

View File

@@ -3,6 +3,6 @@
.alpha.four.columns .alpha.four.columns
= label :payment_method, :type, t('.provider') = label :payment_method, :type, t('.provider')
.omega.twelve.columns .omega.twelve.columns
= collection_select(:payment_method, :type, @providers, :to_s, :clean_name, {}, { class: 'select2 fullwidth', 'provider-prefs-for' => "#{@object.id}"}) = select(:payment_method, :type, payment_method_type_options(@providers), {}, { class: 'select2 fullwidth', required: true, placeholder: t("admin.choose"), 'provider-prefs-for' => "#{@object.id}"})
%div{"ng-include" => "include_html" } %div{"ng-include" => "include_html" }

View File

@@ -37,7 +37,7 @@
- method.distributors.each do |distributor| - method.distributors.each do |distributor|
= distributor.name = distributor.name
%br/ %br/
%td= method.class.clean_name %td= payment_method_type_name(method.class.name)
- if spree_current_user.admin? - if spree_current_user.admin?
%td.align-center= method.environment.to_s.titleize %td.align-center= method.environment.to_s.titleize
%td.align-center= method.display_on.blank? ? t('.both') : t('.' + method.display_on.to_s) %td.align-center= method.display_on.blank? ? t('.both') : t('.' + method.display_on.to_s)

View File

@@ -18,5 +18,5 @@
%span{class: "state #{payment.state}"}= t(payment.state, scope: "spree.payment_states", default: payment.state.capitalize) %span{class: "state #{payment.state}"}= t(payment.state, scope: "spree.payment_states", default: payment.state.capitalize)
%td.actions %td.actions
- payment.actions.each do |action| - payment.actions.each do |action|
= link_to_with_icon "icon-#{action}", Spree.t(action), fire_admin_order_payment_path(@order, payment, e: action), = link_to "", fire_admin_order_payment_path(@order, payment, e: action),
no_text: true, data: { method: :put, action: action, disable_with: "" } class: "icon_link icon-#{action} no-text", data: { method: :put, action: action, disable_with: "" }, title: Spree.t(action)

View File

@@ -29,7 +29,7 @@
.sixteen.columns.alpha .sixteen.columns.alpha
.eight.columns.alpha .eight.columns.alpha
= f.field_container :variant_unit do = f.field_container :variant_unit do
= f.label :variant_unit, t(".units") = f.label :variant_unit_with_scale, t(".units")
%span.required * %span.required *
= f.select 'variant_unit', [], = f.select 'variant_unit', [],
{ include_blank: true }, { include_blank: true },

View File

@@ -14,7 +14,7 @@
= " - OFN #{t(:administration)}" = " - OFN #{t(:administration)}"
%link{:href => "https://fonts.googleapis.com/css?family=Open+Sans:400italic,600italic,400,600&subset=latin,cyrillic,greek,vietnamese", :rel => "stylesheet", :type => "text/css"} %link{:href => "https://fonts.googleapis.com/css?family=Open+Sans:400italic,600italic,400,600&subset=latin,cyrillic,greek,vietnamese", :rel => "stylesheet", :type => "text/css"}
= stylesheet_pack_tag 'admin-style-v3', media: "screen, print" = stylesheet_pack_tag 'admin-style', media: "screen, print"
= render "layouts/bugsnag_js" = render "layouts/bugsnag_js"
- if content_for? :minimal_js - if content_for? :minimal_js

View File

@@ -1,11 +1,16 @@
import { Controller } from "stimulus"; import { Controller } from "stimulus";
import TomSelect from "tom-select/dist/esm/tom-select.complete"; import TomSelect from "tom-select/dist/esm/tom-select.complete";
import showHttpError from "../../webpacker/js/services/show_http_error";
export default class extends Controller { export default class extends Controller {
static values = { options: Object, placeholder: String }; static values = {
options: Object,
placeholder: String,
remoteUrl: String,
};
connect(options = {}) { connect(options = {}) {
this.control = new TomSelect(this.element, { let tomSelectOptions = {
maxItems: 1, maxItems: 1,
maxOptions: null, maxOptions: null,
plugins: ["dropdown_input"], plugins: ["dropdown_input"],
@@ -16,7 +21,13 @@ export default class extends Controller {
}, },
...this.optionsValue, ...this.optionsValue,
...options, ...options,
}); };
if (this.remoteUrlValue) {
this.#addRemoteOptions(tomSelectOptions);
}
this.control = new TomSelect(this.element, tomSelectOptions);
} }
disconnect() { disconnect() {
@@ -29,4 +40,78 @@ export default class extends Controller {
const optionsArray = [...this.element.options]; const optionsArray = [...this.element.options];
return optionsArray.find((option) => [null, ""].includes(option.value))?.text; return optionsArray.find((option) => [null, ""].includes(option.value))?.text;
} }
#buildUrl(query, page = 1) {
const url = new URL(this.remoteUrlValue, window.location.origin);
url.searchParams.set("q", query);
url.searchParams.set("page", page);
return url.toString();
}
#fetchOptions(query, callback) {
const url = this.control.getUrl(query);
fetch(url)
.then((response) => {
if (!response.ok) {
showHttpError(response.status);
throw response;
}
return response.json();
})
.then((json) => {
/**
* Expected API shape:
* {
* results: [{ value, label }],
* pagination: { more: boolean }
* }
*/
if (json.pagination?.more) {
const currentUrl = new URL(url);
const currentPage = parseInt(currentUrl.searchParams.get("page") || "1");
const nextUrl = this.#buildUrl(query, currentPage + 1);
this.control.setNextUrl(query, nextUrl);
}
callback(json.results || []);
})
.catch((error) => {
callback();
console.error(error);
});
}
#addRemoteOptions(options) {
this.openedByClick = false;
options.firstUrl = (query) => {
return this.#buildUrl(query, 1);
};
options.load = this.#fetchOptions.bind(this);
options.onFocus = function () {
this.control.load("", () => {});
}.bind(this);
options.onDropdownOpen = function () {
this.openedByClick = true;
}.bind(this);
options.onType = function () {
this.openedByClick = false;
}.bind(this);
// As per TomSelect source code, Loading state is shown on the UI when this function returns true.
// By default it shows loading state only when there is some input in the search box.
// We want to show loading state on focus as well (when there is no input) to indicate that options are being loaded.
options.shouldLoad = function (query) {
return this.openedByClick || query.length > 0;
}.bind(this);
options.valueField = "value";
options.labelField = "label";
options.searchField = "label";
}
} }

View File

@@ -16,13 +16,13 @@
@import "flatpickr/dist/themes/material_blue"; @import "flatpickr/dist/themes/material_blue";
@import "shortcut-buttons-flatpickr/dist/themes/light"; @import "shortcut-buttons-flatpickr/dist/themes/light";
@import "../admin/globals/functions"; @import "globals/functions";
@import "globals/palette"; // admin_v3 @import "globals/palette"; // admin_v3
@import "globals/variables"; // admin_v3 @import "globals/variables"; // admin_v3
@import "../admin/globals/mixins"; @import "globals/mixins";
@import "mixins"; // admin_v3 @import "mixins"; // admin_v3
@import "../admin/plugins/font-awesome"; @import "plugins/font-awesome";
@import "../shared/variables/layout"; @import "../shared/variables/layout";
@import "../shared/variables/variables"; @import "../shared/variables/variables";
@@ -32,7 +32,7 @@
@import "shared/icons"; // admin_v3 @import "shared/icons"; // admin_v3
@import "shared/forms"; // admin_v3 @import "shared/forms"; // admin_v3
@import "shared/layout"; // admin_v3 @import "shared/layout"; // admin_v3
@import "../admin/shared/scroll_bar"; @import "shared/scroll_bar";
@import "../shared/trix"; @import "../shared/trix";
@@ -40,96 +40,94 @@
@import "plugins/powertip"; // admin_v3 @import "plugins/powertip"; // admin_v3
@import "sections/orders"; // admin_v3 @import "sections/orders"; // admin_v3
@import "../admin/sections/products"; @import "sections/products";
@import "../admin/hacks/mozilla"; @import "hacks/mozilla";
@import "../admin/hacks/opera"; @import "hacks/opera";
@import "../admin/hacks/ie"; @import "hacks/ie";
@import "components/actions"; // admin_v3 @import "components/actions"; // admin_v3
@import "../admin/components/alert-box"; @import "components/alert-box";
@import "../admin/components/alert_row"; @import "components/alert_row";
@import "components/buttons"; // admin_v3 @import "components/buttons"; // admin_v3
@import "components/date-picker"; // admin_v3 @import "components/date-picker"; // admin_v3
@import "../admin/components/dialogs"; @import "components/dialogs";
@import "../admin/components/input"; @import "components/input";
@import "../admin/components/jquery_dialog"; @import "components/jquery_dialog";
@import "components/messages"; // admin_v3 @import "components/messages"; // admin_v3
@import "components/navigation"; // admin_v3 @import "components/navigation"; // admin_v3
@import "../admin/components/ng-cloak"; @import "components/ng-cloak";
@import "../admin/components/page_actions"; @import "components/page_actions";
@import "components/pagination"; // admin_v3 @import "components/pagination"; // admin_v3
@import "../admin/components/per_page_controls"; @import "components/per_page_controls";
@import "../admin/components/product_autocomplete"; @import "components/product_autocomplete";
@import "../admin/components/progress"; @import "components/progress";
@import "../admin/components/save_bar"; @import "components/save_bar";
@import "components/sidebar"; // admin_v3 @import "components/sidebar"; // admin_v3
@import "../admin/components/simple_modal"; @import "components/simple_modal";
@import "../admin/components/states"; @import "components/states";
@import "../admin/components/stripe_connect_button"; @import "components/stripe_connect_button";
@import "../admin/components/subscriptions_states"; @import "components/subscriptions_states";
@import "../admin/components/table-filter"; @import "components/table-filter";
@import "../admin/components/table_loading"; @import "components/table_loading";
@import "../admin/components/timepicker"; @import "components/timepicker";
@import "../admin/components/todo"; @import "components/todo";
@import "../admin/components/tooltip"; @import "components/tooltip";
@import "../admin/components/wizard_progress"; @import "components/wizard_progress";
@import "../admin/pages/enterprise_form"; @import "pages/enterprise_form";
@import "../admin/pages/subscription_form"; @import "pages/subscription_form";
@import "../admin/pages/subscription_line_items"; @import "pages/subscription_line_items";
@import "../admin/pages/subscription_review"; @import "pages/subscription_review";
@import "../admin/advanced_settings"; @import "advanced_settings";
@import "../admin/alert"; @import "alert";
@import "../admin/animations"; @import "animations";
@import "pages/change_type_form"; // admin_v3 @import "pages/change_type_form"; // admin_v3
@import "../admin/connected_apps"; @import "connected_apps";
@import "../admin/customers"; @import "customers";
@import "dashboard/dashboard_item"; // admin_v3 @import "dashboard/dashboard_item"; // admin_v3
@import "pages/dashboard-single-ent"; // admin_v3 @import "pages/dashboard-single-ent"; // admin_v3
@import "../admin/dialog"; @import "dialog";
@import "../admin/disabled"; @import "disabled";
@import "components/dropdown"; // admin_v3 @import "components/dropdown"; // admin_v3
@import "pages/edit_variant"; // admin_v3 @import "pages/edit_variant"; // admin_v3
@import "pages/enterprise_index_panels"; // admin_v3 @import "pages/enterprise_index_panels"; // admin_v3
@import "../admin/enterprises"; @import "enterprises";
@import "../admin/filters_and_controls"; @import "filters_and_controls";
@import "../admin/grid"; @import "grid";
@import "../admin/icons"; @import "icons";
@import "../admin/index_panel_buttons"; @import "index_panel_buttons";
@import "../admin/index_panels"; @import "index_panels";
@import "../admin/modals"; @import "modals";
@import "../admin/offsets"; @import "offsets";
@import "../admin/openfoodnetwork"; @import "openfoodnetwork";
@import "../admin/order_cycles"; @import "order_cycles";
@import "../admin/orders"; @import "orders";
@import "pages/product_import"; // admin_v3 @import "pages/product_import"; // admin_v3
@import "../admin/products"; @import "products";
@import "../admin/products_v3"; @import "products_v3";
@import "../admin/question-mark-tooltip"; @import "question-mark-tooltip";
@import "../admin/relationships"; @import "relationships";
@import "../admin/reports"; @import "reports";
@import "components/select2"; // admin_v3 @import "components/select2"; // admin_v3
@import "components/sidebar-item"; // admin_v3 @import "components/sidebar-item"; // admin_v3
@import "../admin/side_menu"; @import "side_menu";
@import "../admin/tables"; @import "tables";
@import "../admin/tag_rules"; @import "tag_rules";
@import "../admin/terms_of_service_files"; @import "terms_of_service_files";
@import "../admin/validation"; @import "validation";
@import "../admin/variant_overrides"; @import "variant_overrides";
@import "../admin/welcome"; @import "welcome";
@import "shared/question-mark-icon"; @import "shared/question-mark-icon";
@import "../admin/question-mark-tooltip"; @import "~tom-select/src/scss/tom-select.default";
@import "tom-select/src/scss/tom-select.default";
@import "components/tom_select"; // admin_v3 @import "components/tom_select"; // admin_v3
@import "modal_component/modal_component"; @import "modal_component/modal_component";
@import "vertical_ellipsis_menu_component/vertical_ellipsis_menu_component"; // admin_v3 and only V3 @import "vertical_ellipsis_menu_component/vertical_ellipsis_menu_component"; // admin_v3 and only V3
@import "tag_list_input_component/tag_list_input_component"; @import "tag_list_input_component/tag_list_input_component";
@import "admin/trix"; @import "trix";
@import "terms_of_service_banner"; // admin_v3 @import "terms_of_service_banner"; // admin_v3

View File

@@ -1,110 +0,0 @@
#change_type {
section {
margin: 2em 0 0 0;
&,
& * {
color: $spree-blue;
}
}
.description {
background-color: $spree-light-blue;
margin-top: -2em;
padding: 4em 2em 2em 1em;
@media all and (max-width: 786px) {
margin-bottom: 2em;
}
}
.admin-cta {
border: 1px solid $spree-blue;
@include border-radius(3px);
text-align: center;
padding: 1em;
}
.error {
display: block;
color: #f57e80;
border: 1px solid #f57e80;
background-color: #fde6e7;
@include border-radius(3px);
margin-bottom: 1em;
padding: 0.5em;
}
a.selector {
position: relative;
border: 2px solid black;
text-align: center;
width: 100%;
cursor: pointer;
&,
& * {
color: white;
}
&:after,
&:before {
top: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-color: rgba(136, 183, 213, 0);
border-top-color: $spree-blue;
border-width: 12px;
margin-left: -12px;
}
&:hover {
&:after {
border-top-color: $spree-green;
}
}
&:before {
border-color: rgba(84, 152, 218, 0);
border-top-color: black;
border-width: 15px;
margin-left: -15px;
}
.bottom {
background: repeating-linear-gradient(
60deg,
rgba(84, 152, 218, 0),
rgba(84, 152, 218, 0) 5px,
rgba(255, 255, 255, 0.25) 5px,
rgba(255, 255, 255, 0.25) 10px
);
margin-top: 1em;
margin-left: -15px;
margin-right: -15px;
padding: 5px;
text-transform: uppercase;
}
&.selected {
background-color: black;
&:after,
&:hover &:after {
border-top-color: black;
}
}
}
}

View File

@@ -1,21 +0,0 @@
.dashboard_item.single-ent {
.header {
padding: 0.77778em 1.33333em 0.77778em 0.77778em;
height: auto !important;
}
.list {
.button.bottom {
width: 100%;
}
}
}
.button.big {
width: 100%;
font-size: 1rem;
@include border-radius(25px);
padding: 15px;
}

View File

@@ -1,244 +0,0 @@
div.dashboard_item {
margin-bottom: 30px;
.centered {
text-align: center;
}
.text-icon {
margin-top: 8px;
display: block;
font-size: 16px;
font-weight: bold;
color: #fff;
padding: 0px 6px;
border-radius: 10px;
&.green {
background-color: $spree-green;
}
&.warning {
background-color: $color-warning;
}
&.orange {
background-color: $color-warning;
}
}
div.header {
height: 50px;
border-radius: 6px 6px 0px 0px;
border: 1px solid $spree-blue;
position: relative;
a[ofn-with-tip] {
position: absolute;
right: 5px;
bottom: 5px;
}
&.warning {
border-color: $color-warning;
border-width: 3px;
h3 {
color: $color-warning;
}
}
&.orange {
border-color: $color-warning;
border-width: 3px;
h3 {
color: $color-warning;
}
}
h3.alpha {
height: 100%;
padding: 10px 5px 0px 3%;
}
a {
border-radius: 0px 4px 0px 0px;
height: 100%;
padding: 15px 2px 0px 2px;
}
}
.tabs {
height: 30px;
border: solid $spree-blue;
border-width: 0px 0px 1px 0px;
margin-top: 3px;
div.dashboard_tab {
cursor: pointer;
height: 30px;
color: #fff;
background-color: $spree-blue;
padding: 5px 5px 0px 5px;
text-align: center;
font-weight: bold;
border: solid $spree-blue;
border-width: 1px 1px 0px 1px;
&:hover {
background-color: $spree-green;
}
&.selected {
color: $spree-blue;
background-color: #fff;
}
}
}
.list {
max-height: 250px;
overflow-y: auto;
overflow-x: hidden;
&:focus {
outline: none;
}
}
.list-title {
border: solid $spree-blue;
border-width: 0px 1px 0px 1px;
span {
font-size: 105%;
padding: 10px 0px;
font-weight: bold;
}
span.alpha {
padding: 10px 2px 10px 5%;
}
}
.list-item {
border: solid $spree-blue;
border-width: 0px 1px 0px 1px;
height: 41px;
span.alpha {
font-weight: bold;
margin-left: -3px;
padding: 10px 2px 0px 5%;
}
span.omega {
padding-right: 13px;
margin-right: -3px;
text-align: right;
}
.icon-arrow-right {
padding-top: 6px;
font-size: 20px;
}
.icon-warning-sign {
color: $color-warning;
font-size: 30px;
}
.icon-remove-sign {
color: $color-warning;
font-size: 30px;
}
.icon-ok-sign {
color: $spree-green;
font-size: 30px;
}
&.orange {
color: $color-warning;
border: solid $color-warning;
}
&.warning {
color: $color-warning;
border: solid $color-warning;
}
&.orange,
&.warning {
border-width: 0px 3px 0px 3px;
}
&.even {
background-color: #fff;
}
&.odd {
background-color: $spree-light-blue;
}
&.even,
&.odd {
&:hover {
color: #ffffff;
background-color: $spree-green;
.icon-arrow-right {
color: #fff;
}
.icon-remove-sign {
color: #fff;
}
.icon-warning-sign {
color: #fff;
}
.icon-ok-sign {
color: #fff;
}
.text-icon {
&.green {
color: $spree-green;
background-color: #fff;
}
}
}
}
}
a.button {
color: #fff;
font-size: 110%;
font-weight: bold;
text-align: center;
&.orange {
background-color: $color-warning;
}
&.blue {
background-color: $spree-blue;
}
&.warning {
background-color: $color-warning;
}
&:hover {
background-color: $spree-green;
}
&.bottom {
border-radius: 0px 0px 6px 6px;
padding: 15px 15px;
}
}
}

View File

@@ -1,271 +0,0 @@
#content-header .ofn-drop-down {
border: none;
background-color: $spree-blue;
color: #fff;
float: none;
margin-left: 3px;
}
.ofn-drop-down {
.dropdown-content {
display: none;
}
.toggle-off {
display: none;
}
&:active:not(.disabled),
&:focus:not(.disabled) {
.dropdown-content {
display: inline-block;
}
}
}
.ofn-drop-down:hover,
.ofn-drop-down.expanded {
border: 1px solid #adadad;
color: #575757;
}
@mixin ofn-drop-down-style {
padding: 7px 15px;
border-radius: 3px;
border: 1px solid #d4d4d4;
background-color: #f5f5f5;
display: block;
color: #828282;
cursor: pointer;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
text-align: center;
margin-right: 10px;
&.disabled {
opacity: 0.5;
pointer-events: none;
&:hover {
cursor: default;
border-color: #d4d4d4;
color: #828282;
}
}
}
.ofn-drop-down-with-prepend {
display: flex;
&.right {
float: right;
}
.ofn-drop-down {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.ofn-drop-down-prepend {
@include ofn-drop-down-style;
border-right: none;
margin-left: 0;
margin-right: 0;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
cursor: default;
}
}
.ofn-drop-down {
@include ofn-drop-down-style;
position: relative;
float: left;
&.right {
float: right;
margin-right: 0px;
margin-left: 10px;
}
&:hover,
&.expanded {
border: 1px solid #adadad;
color: #575757;
}
> span {
width: auto;
text-transform: uppercase;
font-size: 85%;
font-weight: 600;
}
.menu {
margin-top: 1px;
position: absolute;
float: none;
top: 100%;
left: 0px;
padding: 5px 0px;
border: 1px solid #adadad;
background-color: #ffffff;
box-shadow: 1px 3px 10px #888888;
z-index: 100;
white-space: nowrap;
.filter {
padding-left: 5px;
padding-right: 5px;
position: relative;
> input[type="text"] {
border: 1px solid rgba(18, 18, 18, 0.1);
width: 100%;
padding-left: 30px;
padding-top: 10px;
padding-bottom: 10px;
font-size: 13px;
color: #454545;
}
&:after {
content: "\f002";
font-family: FontAwesome;
position: absolute;
left: 15px;
top: 13px;
color: #454545;
}
}
.menu_item {
margin: 0px;
padding: 2px 10px;
color: #454545;
text-align: left;
display: block;
.check {
display: inline-block;
text-align: center;
width: 40px;
&:before {
content: "\00a0";
}
}
.name {
display: inline-block;
padding: 0px 15px 0px 0px;
}
&.selected {
.check:before {
content: "\2713";
}
}
&.hidden {
display: none;
}
}
.menu_item:hover {
background-color: #ededed;
}
}
> details {
// Override padding on ofn-drop-down-style
margin: -7px -15px;
padding: 7px 15px;
}
> details > summary {
display: inline-block;
list-style: none;
width: auto;
text-transform: uppercase;
font-size: 85%;
font-weight: 600;
// Override padding on ofn-drop-down-style to increase clickable area
margin: -8px -15px;
padding: 8px 15px;
}
> details > summary:after {
content: "\f0d7";
font-family: FontAwesome;
}
> details[open] > summary:after {
content: "\f0d8";
font-family: FontAwesome;
}
}
.ofn-drop-down-v2 {
border: 1px solid $pale-blue;
background-color: white;
padding: 0px;
&:hover {
border-color: $spree-blue;
}
.ofn-drop-down-label {
color: $color-3;
padding: 10px;
width: 235px;
display: flex;
justify-content: space-between;
&:hover {
color: $color-3;
}
.label {
padding-right: 10px;
}
.icon-caret-down,
.icon-caret-up {
padding-right: 0px;
}
}
.menu {
width: 100%;
}
.menu_items {
max-height: 200px;
overflow-y: scroll;
.menu_item {
margin-bottom: 5px;
color: #454545;
font-weight: 400;
cursor: pointer;
padding-top: 4px;
padding-bottom: 5px;
text-transform: uppercase;
font-size: 85%;
}
}
}
.ofn-drop-down.ofn-drop-down-v2 {
// Add very specific styling here for components that are in transition:
// ie. the ones using the two classes above
.ofn-drop-down-label {
padding-top: 7px;
padding-bottom: 7px;
}
}

View File

@@ -1,120 +0,0 @@
.enterprise_package_panel,
.enterprise_producer_panel {
.info {
p {
font-size: 1rem;
margin: 10px 0px;
}
}
a.selector {
display: block;
position: relative;
margin-bottom: 20px;
border: 2px solid black;
text-align: center;
// width: 100%;
cursor: pointer;
&,
& * {
color: white;
}
&:hover {
&:after {
border-top-color: $spree-green;
}
}
&.disabled {
background-color: #c1c1c1;
}
.bottom {
background: repeating-linear-gradient(
60deg,
rgba(84, 152, 218, 0),
rgba(84, 152, 218, 0) 5px,
rgba(255, 255, 255, 0.25) 5px,
rgba(255, 255, 255, 0.25) 10px
);
margin-top: 1em;
margin-left: -15px;
margin-right: -15px;
padding: 5px;
text-transform: uppercase;
}
&.selected {
background-color: #000000;
&:after {
top: 50%;
left: 0;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-right: 20px solid #000000;
margin-top: -20px;
margin-left: -20px;
}
}
}
}
.enterprise_status_panel {
.status-ok {
margin: 30px 0px;
i.icon-ok-sign {
color: $spree-green;
font-size: 1.5rem;
}
}
td.description {
font-size: 0.9rem;
}
td.severity {
text-align: center;
i {
font-size: 1.5rem;
&.issue {
color: $color-warning;
}
&.warning {
color: #ff9848;
}
}
}
}
tags-input .tags li.tag-item {
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
-ms-border-radius: 3px;
-o-border-radius: 3px;
border-radius: 3px;
margin: 2px 0 2px 3px;
background-image: none;
background-color: #5fa5e8;
border: none;
box-shadow: none;
color: white !important;
font-size: 85%;
height: 25px;
}
tags-input .tags .tag-item .remove-button {
color: white;
}
table th.actions .no-text[class*="icon-"],
table td.actions .no-text[class*="icon-"] {
cursor: pointer;
}

View File

@@ -1,20 +1,38 @@
// Basic color palette for admin // Basic color palette for admin styles v3
$spree-green: #9fc820; $white: #ffffff !default; // White
$spree-blue: #5498da; $green: #9fc820 !default; // Green
$teal: #008397 !default; // Teal (Allports)
$orient: #006878 !default; // Orient (Cerulean)
$dark-blue: #004e5b !default; // Dark Blue (Sherpa)
$pale-blue: #cee1f4; // Pale blue
$red: #c85136 !default; // Red/Orange (Mojo)
$bright-orange: #ffa92e; // Bright orange
$yellow: #ff9300 !default; // Yellow
$mystic: #d9e8eb !default; // Mystic
$lighter-grey: #f8f9fa !default; // Lighter grey
$light-grey: #eff1f2 !default; // Light grey (Porcelain)
$medium-light-grey: #babdbe !default; // Silver Sand
$medium-grey: #919191 !default; // Medium grey
$dark-grey: #2e3132 !default; // Dark Grey
$near-black: #191c1d !default; // Near-black (Shark)
$fair-pink: #ffefeb !default; // Fair Pink
$roof-terracotta: #b83b1f !default; // Roof Terracotta
// Old colour variables for backwards compatibility
$spree-green: $green;
$spree-blue: $teal;
$spree-light-blue: #eff5fc; $spree-light-blue: #eff5fc;
$pale-blue: #cee1f4; $color-1: $white;
$bright-orange: #ffa92e; $color-2: $green;
$medium-grey: #919191; $color-3: $teal;
$light-grey: #ccc; $color-4: $dark-blue;
$color-5: $red;
$color-1: #ffffff !default; // White $color-6: $yellow;
$color-2: $spree-green !default; // Green $color-7: $light-grey;
$color-3: $spree-blue !default; // Light Blue $color-8: $near-black;
$color-4: #6788a2 !default; // Dark Blue $color-9: $dark-grey;
$color-5: #c60f13 !default; // Red $color-10: $orient;
$color-6: #ff9300 !default; // Yellow $color-11: $mystic;
$color-14: #f8f9fa !default; // Lighter grey $color-12: $fair-pink;
$color-13: $roof-terracotta;
$dark-grey: #333; $color-14: $lighter-grey;
$light-grey: #ddd;
$near-black: #222;

View File

@@ -1,189 +0,0 @@
.select2-container {
&:hover .select2-choice,
&.select2-container-active .select2-choice {
background-color: $color-sel-hover-bg !important;
border-color: $color-sel-hover-bg !important;
}
.select2-choice {
background-image: none !important;
background-color: $color-sel-bg;
border: none !important;
box-shadow: none !important;
@include border-radius($border-radius);
color: $color-1 !important;
font-size: 90%;
height: 31px;
line-height: inherit !important;
padding: 5px 15px 7px;
span {
display: block;
padding: 2px;
}
.select2-search-choice-close {
background-image: none !important;
font-size: 100% !important;
@extend .icon-remove;
@extend [class^="icon-"], :before;
margin-top: 2px;
}
}
&.select2-container-active {
.select2-choice {
box-shadow: none !important;
}
&.select2-dropdown-open .select2-choice div b {
@extend .icon-caret-up;
}
}
}
.select2-drop {
border-color: $color-sel-hover-bg;
box-shadow: none !important;
z-index: 1000000;
&.select2-drop-above {
border-color: $color-sel-hover-bg;
}
}
.select2-search {
@extend .icon-search;
font-size: 100%;
color: darken($color-border, 15);
padding: 0 9px 0 0;
&:before {
@extend [class^="icon-"], :before;
position: absolute;
top: 13px;
left: 13px;
}
input {
@extend input, [type="text"];
padding: 6px 0 6px 25px;
margin: 5px 0 0 5px;
font-family: $base-font-family;
font-size: 90%;
box-shadow: none;
background-image: none;
}
}
.select2-container .select2-choice .select2-arrow {
background-image: none;
background: transparent;
border: 0;
b {
padding-top: 7px;
display: block;
width: 100%;
height: 100%;
background: none;
font-family: FontAwesome;
font-weight: 200 !important;
&:before {
content: "\f0d7";
}
}
}
.select2-results {
padding-left: 0 !important;
li {
font-size: 85% !important;
&.select2-highlighted {
.select2-result-label {
&,
h6 {
color: $color-1 !important;
}
}
}
.select2-result-label {
color: $color-body-text;
min-height: 22px;
clear: both;
overflow: auto;
}
&.select2-no-results,
&.select2-searching {
padding: 5px;
background-color: transparent;
color: $color-body-text;
text-align: center;
font-weight: $font-weight-bold;
text-transform: uppercase;
}
}
.select2-highlighted {
background-color: $color-sel-bg;
}
}
.select2-container-multi {
&.select2-container-active,
&.select2-dropdown-open {
.select2-choices {
border-color: $color-sel-hover-bg !important;
box-shadow: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
}
.select2-choices {
@extend input, [type="text"];
padding: 6px 3px 3px 3px;
box-shadow: none;
background-image: none !important;
.select2-search-choice {
@include border-radius($border-radius);
margin: 0 0 3px 3px;
background-image: none;
background-color: $color-sel-bg;
border: none;
box-shadow: none;
color: $color-1 !important;
font-size: 85%;
&:hover {
background-color: $color-sel-hover-bg;
}
.select2-search-choice-close {
background-image: none !important;
font-size: 85% !important;
@extend .icon-remove;
@extend [class^="icon-"], :before;
margin-left: 2px;
color: $color-1;
}
}
}
}
label .select2-container {
margin-top: -6px;
.select2-choice {
span {
text-transform: none;
font-weight: normal;
}
}
}

View File

@@ -1,299 +0,0 @@
$pi-red: $color-warning;
$pi-green: lighten($spree-green, 10%);
$pi-orange: $bright-orange;
$pi-blue: lighten($spree-blue, 10%);
$pi-light-yellow: #faffaf;
// scss-lint:disable NestingDepth
div.panel-section {
.error {
color: $pi-red;
}
.warning {
color: $bright-orange;
}
.success {
color: $pi-green;
}
.info {
color: #68b7c0;
}
div.panel-header {
width: 100%;
clear: both;
float: left;
padding: 0.5em;
div {
font-size: 1.25em;
float: left;
}
div.header-caret {
width: 2em;
text-align: center;
min-height: 0.1em; //Empty div fix
}
div.header-icon {
width: 2.5em;
text-align: center;
padding-top: 0.18em;
i {
font-size: 1.5em;
line-height: 0.9em;
}
}
div.header-count {
min-width: 2em;
text-align: right;
padding-right: 0.5em;
}
div.header-description {
width: auto;
}
}
div.panel-header:hover {
cursor: pointer;
background-color: #f7f7f7;
}
div.panel-header.active {
background-color: #efefef;
text-shadow: 1px 1px 0px rgba(255, 255, 255, 0.75);
}
div.panel-content {
width: 100%;
clear: both;
margin-bottom: 0.5em;
background-color: #f9f9f9;
padding: 1.5em;
div.table-wrap {
width: 100%;
overflow: auto;
border-right: 1px solid #ceede3;
max-height: 23em;
}
table {
background-color: white;
margin-bottom: 0;
td,
th {
white-space: nowrap;
}
tr {
&.error {
color: #c84c4c;
}
&:hover td.invalid {
background-color: darken(#f05c51, 5%);
}
i {
display: block;
margin-bottom: -0.2em;
font-size: 1.4em !important;
}
}
td {
&.invalid {
background-color: #f05c51;
box-shadow: inset 0px 0px 1px red;
color: white;
}
}
}
div.import-errors {
margin-bottom: 0.85em;
p.line {
font-size: 1.15em;
margin-bottom: 0.2em;
color: #577084;
}
p.error {
color: #cb1b1b;
margin-bottom: 0.2em;
}
}
}
}
br.panels.clearfix {
clear: both;
}
.panel-section.import-settings {
.header-description {
padding-left: 1em;
}
span.header-error {
font-size: 0.85em;
color: $pi-red;
}
.select2-search {
display: none;
}
.select2-results {
margin: 0;
}
}
.post-save-results {
p {
font-size: 1.25em;
margin-bottom: 0.5em;
strong {
margin-right: 0.2em;
min-width: 1.8em;
display: inline-block;
text-align: right;
}
i {
font-size: 1.4em;
vertical-align: middle;
position: relative;
}
i.fa-check-circle {
color: $pi-green;
}
i.fa-info-circle {
color: $pi-blue;
}
}
p.save-error {
color: #ee4728;
font-size: 1.05em;
margin-top: 0.4em;
}
}
form.product-import,
div.post-save-results,
div.import-wrapper {
input[type="submit"] {
margin-right: 0.5em;
}
input[type="submit"],
button,
a.button {
min-width: 8em;
text-align: center;
}
}
div.import-wrapper {
.alert-box {
margin: 0 0 1.75em;
}
.ng-hide:not(.ng-hide-animate) {
// We have to use !important here to override angular's display properties
// scss-lint:disable ImportantRule
display: block !important;
position: absolute;
opacity: 0;
top: -9999px;
left: -9999px;
}
.ng-hide-add,
.ng-hide-remove,
.ng-hide-animate {
transition: all 0.4s ease-in-out;
}
form.product-import,
div.save-results {
transition: all 0.4s ease-in-out;
}
div.progress-interface {
text-align: center;
transition: all 0.4s ease-in-out;
button:disabled {
background: #ccc !important;
}
}
.post-save-results {
a.button {
float: left;
margin-right: 0.5em;
}
}
}
div.progress-bar {
height: 25px;
width: 30em;
max-width: 90%;
margin: 1em auto;
background: #f7f7f7;
padding: 3px;
border-radius: 0.3em;
border: 1px solid #eee;
span.progress-track {
display: block;
background: lighten($pi-green, 10%);
height: 100%;
border-radius: 0.3em;
box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);
transition: width 0.3s ease-in-out;
}
}
#upload-sidebar {
float: right;
background-color: lighten($spree-light-blue, 2.5%);
border: 1px solid lighten($pale-blue, 2.5%);
width: 50%;
padding: 0 1.5em 1.5em;
h4,
h5,
h6,
p {
margin: 1.25em 0 1em;
}
a.download {
display: block;
font-size: 1.05em;
margin-bottom: 0.5em;
i {
margin-right: 0.25em;
}
}
span.category {
display: inline-block;
background-color: $pi-blue;
color: white;
padding: 0.3em 0.6em;
margin: 0 0.4em 0.5em 0;
}
}

View File

@@ -1,6 +1,6 @@
// Customisations for the new Bulk Edit Products page only // Customisations for the new Bulk Edit Products page only
// Scoped to containing div, because Turbo messes with body classes // Scoped to containing div, because Turbo messes with body classes
@import "../admin_v3/pages/unit_popout"; @import "pages/unit_popout";
#products_v3_page { #products_v3_page {
#content > .row:first-child > .container:first-child { #content > .row:first-child > .container:first-child {
@@ -59,6 +59,7 @@
overflow: visible; overflow: visible;
background-color: white; background-color: white;
} }
.form-actions-wrapper2 { .form-actions-wrapper2 {
position: relative; position: relative;
// Stretch to cover table side borders // Stretch to cover table side borders
@@ -157,6 +158,7 @@
tr:first-child td { tr:first-child td {
border-top: 4px solid $color-tbl-bg; border-top: 4px solid $color-tbl-bg;
} }
tr:last-child td { tr:last-child td {
border-bottom: 1px solid $color-tbl-cell-shadow; border-bottom: 1px solid $color-tbl-cell-shadow;
} }
@@ -187,6 +189,7 @@
$columns: $columns:
"image", "name", "sku", "unit_scale", "unit", "price", "on_hand", "producer", "category", "image", "name", "sku", "unit_scale", "unit", "price", "on_hand", "producer", "category",
"tax_category", "tags", "inherits_properties"; "tax_category", "tags", "inherits_properties";
@each $col in $columns { @each $col in $columns {
&.hide-#{$col} { &.hide-#{$col} {
.col-#{$col} { .col-#{$col} {
@@ -237,6 +240,7 @@
align-items: center; align-items: center;
gap: 10px; gap: 10px;
} }
.per-page { .per-page {
width: 9em; width: 9em;
} }
@@ -286,6 +290,7 @@
.search-button { .search-button {
position: relative; position: relative;
> input { > input {
padding-left: 30px; padding-left: 30px;
} }
@@ -295,6 +300,7 @@
// Blurred and non-clickable // Blurred and non-clickable
$disabled-blur: 1.5px; $disabled-blur: 1.5px;
.disabled-section { .disabled-section {
position: relative; position: relative;
@@ -346,6 +352,7 @@
from { from {
transform: scaleY(1); transform: scaleY(1);
} }
to { to {
transform: scaleY(0); transform: scaleY(0);
} }
@@ -360,6 +367,7 @@
from { from {
transform: scaleY(0); transform: scaleY(0);
} }
to { to {
transform: scaleY(1); transform: scaleY(1);
} }

View File

@@ -1,63 +0,0 @@
.select2-container {
.select2-choice {
.select2-search-choice-close {
display: none !important;
}
.select2-arrow {
width: 22px;
border: none;
background-image: none;
background-color: transparent;
}
}
&.light {
.select2-choice {
background-color: #ffffff;
font-weight: normal;
color: $spree-blue !important;
border: 1px solid $color-border !important;
}
&:hover,
&.select2-container-active {
.select2-choice {
background-color: #ffffff !important;
border: 1px solid $spree-green !important;
.select2-arrow {
&:before {
color: $spree-blue;
}
}
}
}
}
&.select2-container-multi {
.select2-search-field {
max-height: 20px;
input {
padding: 0 !important;
margin: 0 0 0 5px !important;
}
}
.select2-search-choice {
display: flex;
align-items: center;
justify-content: center;
padding-left: 7px;
.select2-search-choice-close {
position: relative;
order: -1;
width: auto;
left: 0;
top: 0;
margin: 0;
padding: 0;
font-size: 100% !important;
}
}
}
}

View File

@@ -1,124 +0,0 @@
div.sidebar_item {
margin-bottom: 30px;
.centered {
text-align: center;
}
div.header {
font-size: 105%;
color: #fff;
padding: 10px 0px;
position: relative;
&.blue {
background-color: $spree-blue;
}
&.red {
background-color: $color-warning;
}
}
.list {
max-height: 400px;
overflow-y: auto;
overflow-x: hidden;
&.red {
color: $color-warning;
.list-item {
border: solid $color-warning;
border-width: 0px 3px 0px 3px;
a.alpha,
span.alpha {
margin-left: -3px;
}
&.odd {
background-color: #fcf6ef;
&:hover {
background-color: $spree-green;
}
}
}
a {
color: $color-warning;
}
}
}
.list-item {
.icon-arrow-right {
padding-top: 6px;
font-size: 20px;
}
border: solid $spree-blue;
border-width: 0px 1px 0px 1px;
a.alpha,
span.alpha {
font-weight: bold;
margin-left: -1px;
padding: 10px 2px 10px 5%;
overflow: hidden;
text-overflow: ellipsis;
}
span.omega {
padding: 8px 18px 8px 0px;
margin-right: -3px;
text-align: right;
}
.icon-remove-sign {
color: $color-warning;
font-size: 18px;
}
&.even {
background-color: #fff;
}
&.odd {
background-color: $spree-light-blue;
}
&.even,
&.odd {
&:hover {
color: #ffffff;
background-color: $spree-green;
a {
color: #ffffff;
}
}
}
}
a.button {
color: #fff;
padding: 15px 15px;
font-weight: bold;
text-align: center;
border-radius: 0px;
&.blue {
background-color: $spree-blue;
}
&.red {
background-color: $color-warning;
}
&:hover {
background-color: $spree-green;
}
}
}

Some files were not shown because too many files have changed in this diff Show More